Human68k CUI emulator with sound.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

v68doscall.c 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753
  1. #include <stdint.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <time.h>
  5. #include "v68.h"
  6. #include "v68io.h"
  7. #include "musashi/m68k.h"
  8. #include "musashi/m68kcpu.h"
  9. #include "sjis.h"
  10. #define DOS_CALL_EXIT 0x00
  11. #define DOS_CALL_GETCHAR 0x01
  12. #define DOS_CALL_PUTCHAR 0x02
  13. #define DOS_CALL_COMINP 0x03
  14. #define DOS_CALL_COMOUT 0x04
  15. #define DOS_CALL_PRNOUT 0x05
  16. #define DOS_CALL_INPOUT 0x06
  17. #define DOS_CALL_INKEY 0x07
  18. #define DOS_CALL_GETC 0x08
  19. #define DOS_CALL_PRINT 0x09
  20. #define DOS_CALL_GETS 0x0a
  21. #define DOS_CALL_KEYSNS 0x0b
  22. #define DOS_CALL_KFLUSH 0x0c
  23. #define DOS_CALL_FFLUSH 0x0d
  24. #define DOS_CALL_CHGDRV 0x0e
  25. #define DOS_CALL_DRVCTRL 0x0f
  26. #define DOS_CALL_CONSNS 0x10
  27. #define DOS_CALL_PRNSNS 0x11
  28. #define DOS_CALL_CINSNS 0x12
  29. #define DOS_CALL_COUTSNS 0x13
  30. #define DOS_CALL_FATCHK 0x17
  31. #define DOS_CALL_HENDSP 0x18
  32. #define DOS_CALL_CURDRV 0x19
  33. #define DOS_CALL_GETSS 0x1a
  34. #define DOS_CALL_FGETC 0x1b
  35. #define DOS_CALL_FGETS 0x1c
  36. #define DOS_CALL_FPUTC 0x1d
  37. #define DOS_CALL_FPUTS 0x1e
  38. #define DOS_CALL_ALLCLOSE 0x1f
  39. #define DOS_CALL_SUPER 0x20
  40. #define DOS_CALL_FNCKEY 0x21
  41. #define DOS_CALL_KNJCTRL 0x22
  42. #define DOS_CALL_CONCTRL 0x23
  43. #define DOS_CALL_KEYCTRL 0x24
  44. #define DOS_CALL_INTVCS 0x25
  45. #define DOS_CALL_PSPSET 0x26
  46. #define DOS_CALL_GETTIM2 0x27
  47. #define DOS_CALL_SETTIM2 0x28
  48. #define DOS_CALL_NAMESTS 0x29
  49. #define DOS_CALL_GETDATE 0x2a
  50. #define DOS_CALL_SETDATE 0x2b
  51. #define DOS_CALL_GETTIME 0x2c
  52. #define DOS_CALL_SETTIME 0x2d
  53. #define DOS_CALL_VERIFY 0x2e
  54. #define DOS_CALL_DUP0 0x2f
  55. #define DOS_CALL_VERNUM 0x30
  56. #define DOS_CALL_KEEPPR 0x31
  57. #define DOS_CALL_GETDPB 0x32
  58. #define DOS_CALL_BREAKCK 0x33
  59. #define DOS_CALL_DRVXCHG 0x34
  60. #define DOS_CALL_INTVCG 0x35
  61. #define DOS_CALL_DSKFRE 0x36
  62. #define DOS_CALL_NAMECK 0x37
  63. #define DOS_CALL_MKDIR 0x39
  64. #define DOS_CALL_RMDIR 0x3a
  65. #define DOS_CALL_CHDIR 0x3b
  66. #define DOS_CALL_CREATE 0x3c
  67. #define DOS_CALL_OPEN 0x3d
  68. #define DOS_CALL_CLOSE 0x3e
  69. #define DOS_CALL_READ 0x3f
  70. #define DOS_CALL_WRITE 0x40
  71. #define DOS_CALL_DELETE 0x41
  72. #define DOS_CALL_SEEK 0x42
  73. #define DOS_CALL_CHMOD 0x43
  74. #define DOS_CALL_IOCTRL 0x44
  75. #define DOS_CALL_DUP 0x45
  76. #define DOS_CALL_DUP2 0x46
  77. #define DOS_CALL_CURDIR 0x47
  78. #define DOS_CALL_MALLOC 0x48
  79. #define DOS_CALL_MFREE 0x49
  80. #define DOS_CALL_SETBLOCK 0x4a
  81. #define DOS_CALL_EXEC 0x4b
  82. #define DOS_CALL_EXIT2 0x4c
  83. #define DOS_CALL_WAIT 0x4d
  84. #define DOS_CALL_FILES 0x4e
  85. #define DOS_CALL_NFILES 0x4f
  86. #define DOS_CALL_SETPDB 0x80
  87. #define DOS_CALL_GETPDB 0x81
  88. #define DOS_CALL_SETENV 0x82
  89. #define DOS_CALL_GETENV 0x83
  90. #define DOS_CALL_VERIFYG 0x84
  91. #define DOS_CALL_COMMON 0x85
  92. #define DOS_CALL_RENAME 0x86
  93. #define DOS_CALL_FILEDATE 0x87
  94. #define DOS_CALL_MALLOC2 0x88
  95. #define DOS_CALL_MAKETMP 0x8a
  96. #define DOS_CALL_NEWFILE 0x8b
  97. #define DOS_CALL_LOCK 0x8c
  98. #define DOS_CALL_ASSIGN 0x8f
  99. #define DOS_CALL_FFLUSH_SET 0xaa
  100. #define DOS_CALL_OS_PATCH 0xab
  101. #define DOS_CALL_GETFCB 0xac
  102. #define DOS_CALL_S_MALLOC 0xad
  103. #define DOS_CALL_S_MFREE 0xae
  104. #define DOS_CALL_S_PROCESS 0xaf
  105. #define DOS_CALL_EXITVC 0xf0
  106. #define DOS_CALL_CTRLVC 0xf1
  107. #define DOS_CALL_ERRJVC 0xf2
  108. #define DOS_CALL_DISKRED 0xf3
  109. #define DOS_CALL_DISKWRT 0xf4
  110. #define DOS_CALL_INDOSFLG 0xf5
  111. #define DOS_CALL_SUPER_JSR 0xf6
  112. #define DOS_CALL_BUS_ERR 0xf7
  113. #define DOS_CALL_OPEN_PR 0xf8
  114. #define DOS_CALL_KILL_PR 0xf9
  115. #define DOS_CALL_GET_PR 0xfa
  116. #define DOS_CALL_SUSPEND_PR 0xfb
  117. #define DOS_CALL_SLEEP_PR 0xfc
  118. #define DOS_CALL_SEND_PR 0xfd
  119. #define DOS_CALL_TIME_PR 0xfe
  120. #define DOS_CALL_CHANGE_PR 0xff
  121. static const char *dos_call_names[256] = {
  122. /* 0x00 */ "_EXIT",
  123. /* 0x01 */ "_GETCHAR",
  124. /* 0x02 */ "_PUTCHAR",
  125. /* 0x03 */ "_COMINP",
  126. /* 0x04 */ "_COMOUT",
  127. /* 0x05 */ "_PRNOUT",
  128. /* 0x06 */ "_INPOUT",
  129. /* 0x07 */ "_INKEY",
  130. /* 0x08 */ "_GETC",
  131. /* 0x09 */ "_PRINT",
  132. /* 0x0a */ "_GETS",
  133. /* 0x0b */ "_KEYSNS",
  134. /* 0x0c */ "_KFLUSH",
  135. /* 0x0d */ "_FFLUSH",
  136. /* 0x0e */ "_CHGDRV",
  137. /* 0x0f */ "_DRVCTRL",
  138. /* 0x10 */ "_CONSNS",
  139. /* 0x11 */ "_PRNSNS",
  140. /* 0x12 */ "_CINSNS",
  141. /* 0x13 */ "_COUTSNS",
  142. /* 0x14 */ "?",
  143. /* 0x15 */ "?",
  144. /* 0x16 */ "?",
  145. /* 0x17 */ "_FATCHK",
  146. /* 0x18 */ "_HENDSP",
  147. /* 0x19 */ "_CURDRV",
  148. /* 0x1a */ "_GETSS",
  149. /* 0x1b */ "_FGETC",
  150. /* 0x1c */ "_FGETS",
  151. /* 0x1d */ "_FPUTC",
  152. /* 0x1e */ "_FPUTS",
  153. /* 0x1f */ "_ALLCLOSE",
  154. /* 0x20 */ "_SUPER",
  155. /* 0x21 */ "_FNCKEY",
  156. /* 0x22 */ "_KNJCTRL",
  157. /* 0x23 */ "_CONCTRL",
  158. /* 0x24 */ "_KEYCTRL",
  159. /* 0x25 */ "_INTVCS",
  160. /* 0x26 */ "_PSPSET",
  161. /* 0x27 */ "_GETTIM2",
  162. /* 0x28 */ "_SETTIM2",
  163. /* 0x29 */ "_NAMESTS",
  164. /* 0x2a */ "_GETDATE",
  165. /* 0x2b */ "_SETDATE",
  166. /* 0x2c */ "_GETTIME",
  167. /* 0x2d */ "_SETTIME",
  168. /* 0x2e */ "_VERIFY",
  169. /* 0x2f */ "_DUP0",
  170. /* 0x30 */ "_VERNUM",
  171. /* 0x31 */ "_KEEPPR",
  172. /* 0x32 */ "_GETDPB",
  173. /* 0x33 */ "_BREAKCK",
  174. /* 0x34 */ "_DRVXCHG",
  175. /* 0x35 */ "_INTVCG",
  176. /* 0x36 */ "_DSKFRE",
  177. /* 0x37 */ "_NAMECK",
  178. /* 0x38 */ "?",
  179. /* 0x39 */ "_MKDIR",
  180. /* 0x3a */ "_RMDIR",
  181. /* 0x3b */ "_CHDIR",
  182. /* 0x3c */ "_CREATE",
  183. /* 0x3d */ "_OPEN",
  184. /* 0x3e */ "_CLOSE",
  185. /* 0x3f */ "_READ",
  186. /* 0x40 */ "_WRITE",
  187. /* 0x41 */ "_DELETE",
  188. /* 0x42 */ "_SEEK",
  189. /* 0x43 */ "_CHMOD",
  190. /* 0x44 */ "_IOCTRL",
  191. /* 0x45 */ "_DUP",
  192. /* 0x46 */ "_DUP2",
  193. /* 0x47 */ "_CURDIR",
  194. /* 0x48 */ "_MALLOC",
  195. /* 0x49 */ "_MFREE",
  196. /* 0x4a */ "_SETBLOCK",
  197. /* 0x4b */ "_EXEC",
  198. /* 0x4c */ "_EXIT2",
  199. /* 0x4d */ "_WAIT",
  200. /* 0x4e */ "_FILES",
  201. /* 0x4f */ "_NFILES",
  202. /* 0x50 */ "?",
  203. /* 0x51 */ "?",
  204. /* 0x52 */ "?",
  205. /* 0x53 */ "?",
  206. /* 0x54 */ "?",
  207. /* 0x55 */ "?",
  208. /* 0x56 */ "?",
  209. /* 0x57 */ "?",
  210. /* 0x58 */ "?",
  211. /* 0x59 */ "?",
  212. /* 0x5a */ "?",
  213. /* 0x5b */ "?",
  214. /* 0x5c */ "?",
  215. /* 0x5d */ "?",
  216. /* 0x5e */ "?",
  217. /* 0x5f */ "?",
  218. /* 0x60 */ "?",
  219. /* 0x61 */ "?",
  220. /* 0x62 */ "?",
  221. /* 0x63 */ "?",
  222. /* 0x64 */ "?",
  223. /* 0x65 */ "?",
  224. /* 0x66 */ "?",
  225. /* 0x67 */ "?",
  226. /* 0x68 */ "?",
  227. /* 0x69 */ "?",
  228. /* 0x6a */ "?",
  229. /* 0x6b */ "?",
  230. /* 0x6c */ "?",
  231. /* 0x6d */ "?",
  232. /* 0x6e */ "?",
  233. /* 0x6f */ "?",
  234. /* 0x70 */ "?",
  235. /* 0x71 */ "?",
  236. /* 0x72 */ "?",
  237. /* 0x73 */ "?",
  238. /* 0x74 */ "?",
  239. /* 0x75 */ "?",
  240. /* 0x76 */ "?",
  241. /* 0x77 */ "?",
  242. /* 0x78 */ "?",
  243. /* 0x79 */ "?",
  244. /* 0x7a */ "?",
  245. /* 0x7b */ "?",
  246. /* 0x7c */ "?",
  247. /* 0x7d */ "?",
  248. /* 0x7e */ "?",
  249. /* 0x7f */ "?",
  250. /* 0x80 */ "_SETPDB",
  251. /* 0x81 */ "_GETPDB",
  252. /* 0x82 */ "_SETENV",
  253. /* 0x83 */ "_GETENV",
  254. /* 0x84 */ "_VERIFYG",
  255. /* 0x85 */ "_COMMON",
  256. /* 0x86 */ "_RENAME",
  257. /* 0x87 */ "_FILEDATE",
  258. /* 0x88 */ "_MALLOC2",
  259. /* 0x89 */ "?",
  260. /* 0x8a */ "_MAKETMP",
  261. /* 0x8b */ "_NEWFILE",
  262. /* 0x8c */ "_LOCK",
  263. /* 0x8d */ "?",
  264. /* 0x8e */ "?",
  265. /* 0x8f */ "_ASSIGN",
  266. /* 0x90 */ "?",
  267. /* 0x91 */ "?",
  268. /* 0x92 */ "?",
  269. /* 0x93 */ "?",
  270. /* 0x94 */ "?",
  271. /* 0x95 */ "?",
  272. /* 0x96 */ "?",
  273. /* 0x97 */ "?",
  274. /* 0x98 */ "?",
  275. /* 0x99 */ "?",
  276. /* 0x9a */ "?",
  277. /* 0x9b */ "?",
  278. /* 0x9c */ "?",
  279. /* 0x9d */ "?",
  280. /* 0x9e */ "?",
  281. /* 0x9f */ "?",
  282. /* 0xa0 */ "?",
  283. /* 0xa1 */ "?",
  284. /* 0xa2 */ "?",
  285. /* 0xa3 */ "?",
  286. /* 0xa4 */ "?",
  287. /* 0xa5 */ "?",
  288. /* 0xa6 */ "?",
  289. /* 0xa7 */ "?",
  290. /* 0xa8 */ "?",
  291. /* 0xa9 */ "?",
  292. /* 0xaa */ "_FFLUSH_SET",
  293. /* 0xab */ "_OS_PATCH",
  294. /* 0xac */ "_GETFCB",
  295. /* 0xad */ "_S_MALLOC",
  296. /* 0xae */ "_S_MFREE",
  297. /* 0xaf */ "_S_PROCESS",
  298. /* 0xb0 */ "?",
  299. /* 0xb1 */ "?",
  300. /* 0xb2 */ "?",
  301. /* 0xb3 */ "?",
  302. /* 0xb4 */ "?",
  303. /* 0xb5 */ "?",
  304. /* 0xb6 */ "?",
  305. /* 0xb7 */ "?",
  306. /* 0xb8 */ "?",
  307. /* 0xb9 */ "?",
  308. /* 0xba */ "?",
  309. /* 0xbb */ "?",
  310. /* 0xbc */ "?",
  311. /* 0xbd */ "?",
  312. /* 0xbe */ "?",
  313. /* 0xbf */ "?",
  314. /* 0xc0 */ "?",
  315. /* 0xc1 */ "?",
  316. /* 0xc2 */ "?",
  317. /* 0xc3 */ "?",
  318. /* 0xc4 */ "?",
  319. /* 0xc5 */ "?",
  320. /* 0xc6 */ "?",
  321. /* 0xc7 */ "?",
  322. /* 0xc8 */ "?",
  323. /* 0xc9 */ "?",
  324. /* 0xca */ "?",
  325. /* 0xcb */ "?",
  326. /* 0xcc */ "?",
  327. /* 0xcd */ "?",
  328. /* 0xce */ "?",
  329. /* 0xcf */ "?",
  330. /* 0xd0 */ "?",
  331. /* 0xd1 */ "?",
  332. /* 0xd2 */ "?",
  333. /* 0xd3 */ "?",
  334. /* 0xd4 */ "?",
  335. /* 0xd5 */ "?",
  336. /* 0xd6 */ "?",
  337. /* 0xd7 */ "?",
  338. /* 0xd8 */ "?",
  339. /* 0xd9 */ "?",
  340. /* 0xda */ "?",
  341. /* 0xdb */ "?",
  342. /* 0xdc */ "?",
  343. /* 0xdd */ "?",
  344. /* 0xde */ "?",
  345. /* 0xdf */ "?",
  346. /* 0xe0 */ "?",
  347. /* 0xe1 */ "?",
  348. /* 0xe2 */ "?",
  349. /* 0xe3 */ "?",
  350. /* 0xe4 */ "?",
  351. /* 0xe5 */ "?",
  352. /* 0xe6 */ "?",
  353. /* 0xe7 */ "?",
  354. /* 0xe8 */ "?",
  355. /* 0xe9 */ "?",
  356. /* 0xea */ "?",
  357. /* 0xeb */ "?",
  358. /* 0xec */ "?",
  359. /* 0xed */ "?",
  360. /* 0xee */ "?",
  361. /* 0xef */ "?",
  362. /* 0xf0 */ "_EXITVC",
  363. /* 0xf1 */ "_CTRLVC",
  364. /* 0xf2 */ "_ERRJVC",
  365. /* 0xf3 */ "_DISKRED",
  366. /* 0xf4 */ "_DISKWRT",
  367. /* 0xf5 */ "_INDOSFLG",
  368. /* 0xf6 */ "_SUPER_JSR",
  369. /* 0xf7 */ "_BUS_ERR",
  370. /* 0xf8 */ "_OPEN_PR",
  371. /* 0xf9 */ "_KILL_PR",
  372. /* 0xfa */ "_GET_PR",
  373. /* 0xfb */ "_SUSPEND_PR",
  374. /* 0xfc */ "_SLEEP_PR",
  375. /* 0xfd */ "_SEND_PR",
  376. /* 0xfe */ "_TIME_PR",
  377. /* 0xff */ "_CHANGE_PR",
  378. };
  379. int v68_dos_call(uint16_t instr) {
  380. uint8_t call = instr & 0xff;
  381. if(v68.log_calls)
  382. printf("DOS %02x %s\n", call, dos_call_names[call]);
  383. switch(call) {
  384. case DOS_CALL_EXIT:
  385. v68.running = 0;
  386. v68_mem_free(v68.cur_prog_addr, m68k_read_memory_32(v68.cur_prog_addr - 0x0c));
  387. v68_queue_next_command();
  388. break;
  389. case DOS_CALL_EXIT2:
  390. v68.running = 0;
  391. v68_mem_free(v68.cur_prog_addr, m68k_read_memory_32(v68.cur_prog_addr - 0x0c));
  392. v68_queue_next_command();
  393. break;
  394. case DOS_CALL_PRINT: {
  395. uint32_t str_addr = m68k_read_memory_32(m68k_get_reg(0, M68K_REG_A7));
  396. logcall("str=%08x\n", str_addr);
  397. if(str_addr < v68.ram_size) {
  398. uint8_t *str_ptr = &v68.ram[str_addr];
  399. size_t l = strnlen((char *)str_ptr, v68.ram_size - str_addr);
  400. sjis_print_utf8(str_ptr, l);
  401. fflush(stdout);
  402. }
  403. }
  404. break;
  405. case DOS_CALL_PUTCHAR: {
  406. uint16_t chr = m68k_read_memory_16(m68k_get_reg(0, M68K_REG_A7));
  407. uint8_t chrbuf[2] = { chr >> 8, chr };
  408. sjis_print_utf8(chrbuf[0] ? chrbuf : chrbuf+1, chrbuf[0] ? 2 : 1);
  409. }
  410. break;
  411. case DOS_CALL_KEEPPR: {
  412. uint32_t prglen = m68k_read_memory_32(m68k_get_reg(0, M68K_REG_A7));
  413. uint16_t code = m68k_read_memory_16(m68k_get_reg(0, M68K_REG_A7) + 4);
  414. logcall("prglen=%d (%dkB) code=%04x\n", prglen, prglen/1024, code);
  415. v68_mem_dump();
  416. logcall("shrinking mem 0x%08x\n", v68.cur_prog_addr);
  417. v68_mem_shrink(v68.cur_prog_addr, prglen);
  418. v68_mem_dump();
  419. v68_queue_next_command();
  420. }
  421. break;
  422. case DOS_CALL_SUPER: {
  423. uint32_t sp = m68k_get_reg(0, M68K_REG_A7);
  424. uint32_t stack = m68k_read_memory_32(sp);
  425. logcall("stack=%08x\n", stack);
  426. FLAG_S = 1;
  427. m68k_set_reg(M68K_REG_SR, m68k_get_reg(0, M68K_REG_SR) | 0x2000);
  428. m68k_set_reg(M68K_REG_A7, sp);
  429. }
  430. break;
  431. case DOS_CALL_IOCTRL: {
  432. uint16_t md = m68k_read_memory_16(m68k_get_reg(0, M68K_REG_A7));
  433. switch(md) {
  434. case 0: {
  435. uint16_t fileno = m68k_read_memory_16(m68k_get_reg(0, M68K_REG_A7) + 2);
  436. if(fileno == 0) m68k_set_reg(M68K_REG_D0, 0x80c1);
  437. else if(fileno == 1 || fileno == 2) m68k_set_reg(M68K_REG_D0, 0x80c2);
  438. else m68k_set_reg(M68K_REG_D0, 0);
  439. }
  440. break;
  441. default:
  442. logcall("IOCTRL %04x\n", md);
  443. }
  444. }
  445. break;
  446. case DOS_CALL_SETBLOCK: {
  447. uint32_t memptr = m68k_read_memory_32(m68k_get_reg(0, M68K_REG_A7));
  448. uint32_t len = m68k_read_memory_32(m68k_get_reg(0, M68K_REG_A7) + 4);
  449. logcall("memptr=0x%08x len=%d\n", memptr, len);
  450. v68_mem_dump();
  451. logcall("Shrinking mem\n");
  452. int r = v68_mem_shrink(memptr, len);
  453. v68_mem_dump();
  454. m68k_set_reg(M68K_REG_D0, r);
  455. }
  456. break;
  457. case DOS_CALL_MALLOC: {
  458. uint32_t len = m68k_read_memory_32(m68k_get_reg(0, M68K_REG_A7));
  459. uint32_t remaining = v68_mem_remaining();
  460. if(len > remaining) len = remaining;
  461. uint32_t m = v68_mem_alloc(len, v68.cur_prog_addr);
  462. logcall("len=0x%08x (%d) result=0x%08x\n", len, len, m);
  463. m68k_set_reg(M68K_REG_D0, m);
  464. v68_mem_dump();
  465. }
  466. break;
  467. case DOS_CALL_FPUTS: {
  468. uint32_t mesptr = m68k_read_memory_32(m68k_get_reg(0, M68K_REG_A7));
  469. uint16_t fileno = m68k_read_memory_16(m68k_get_reg(0, M68K_REG_A7) + 4);
  470. uint8_t *str_ptr = &v68.ram[mesptr];
  471. size_t l = strnlen((char *)str_ptr, v68.ram_size - mesptr);
  472. if(fileno == 2) {
  473. sjis_print_utf8(str_ptr, l);
  474. } else {
  475. logcall("FPUTS mesptr=%08x \"%s\" fileno=%d\n", mesptr, v68.ram + mesptr, fileno);
  476. }
  477. }
  478. break;
  479. case DOS_CALL_VERNUM: {
  480. m68k_set_reg(M68K_REG_D0, 0x36380302);
  481. }
  482. break;
  483. case DOS_CALL_GETDATE: {
  484. time_t t = time(NULL);
  485. struct tm result;
  486. localtime_r(&t, &result);
  487. uint32_t d = ((result.tm_wday & 0x07) << 16) | (((result.tm_year - 80) & 0x7f) << 9) | ((result.tm_mon & 0x0f) << 5) | (result.tm_mday & 0x1f);
  488. m68k_set_reg(M68K_REG_D0, d);
  489. }
  490. break;
  491. case DOS_CALL_GETTIME: {
  492. time_t t = time(NULL);
  493. struct tm result;
  494. localtime_r(&t, &result);
  495. uint16_t d = ((result.tm_hour & 0x1f) << 11) | ((result.tm_min & 0x3f) << 5) | ((result.tm_sec >> 1) & 0x1f);
  496. m68k_set_reg(M68K_REG_D0, d);
  497. }
  498. break;
  499. case DOS_CALL_GETTIM2: {
  500. time_t t = time(NULL);
  501. struct tm result;
  502. localtime_r(&t, &result);
  503. uint16_t d = ((result.tm_hour & 0x1f) << 16) | ((result.tm_min & 0x3f) << 8) | (result.tm_sec & 0x3f);
  504. m68k_set_reg(M68K_REG_D0, d);
  505. }
  506. break;
  507. case DOS_CALL_CREATE: {
  508. uint32_t file = m68k_read_memory_32(m68k_get_reg(0, M68K_REG_A7));
  509. uint16_t attr = m68k_read_memory_16(m68k_get_reg(0, M68K_REG_A7) + 4);
  510. uint8_t *str_ptr = &v68.ram[file];
  511. size_t l = strnlen((char *)str_ptr, v68.ram_size - file - 1);
  512. str_ptr[l] = 0;
  513. logcall("filename=%s attr=0x%04x\n", str_ptr, attr);
  514. int fd = v68_io_create((char *)str_ptr, attr);
  515. m68k_set_reg(M68K_REG_D0, fd);
  516. /* Fill fd bitmap */
  517. if(fd > 0) {
  518. fd -= 4;
  519. uint32_t fdmapaddr = v68.cur_prog_addr + 0x24 + (fd >> 3);
  520. m68k_write_memory_8(fdmapaddr, m68k_read_memory_8(fdmapaddr) | (1 << (fd & 0x07)));
  521. }
  522. }
  523. break;
  524. case DOS_CALL_OPEN: {
  525. uint32_t file = m68k_read_memory_32(m68k_get_reg(0, M68K_REG_A7));
  526. uint16_t mode = m68k_read_memory_16(m68k_get_reg(0, M68K_REG_A7) + 4);
  527. uint8_t *str_ptr = &v68.ram[file];
  528. size_t l = strnlen((char *)str_ptr, v68.ram_size - file - 1);
  529. str_ptr[l] = 0;
  530. int fd = v68_io_open((char *)str_ptr, mode);
  531. logcall("filename=\"%s\" mode=0x%04x fd=%d\n", str_ptr, mode, fd);
  532. m68k_set_reg(M68K_REG_D0, fd);
  533. /* Fill fd bitmap */
  534. if(fd > 0) {
  535. fd -= 4;
  536. uint32_t fdmapaddr = v68.cur_prog_addr + 0x24 + (fd >> 3);
  537. m68k_write_memory_8(fdmapaddr, m68k_read_memory_8(fdmapaddr) | (1 << (fd & 0x07)));
  538. }
  539. }
  540. break;
  541. case DOS_CALL_CLOSE: {
  542. uint16_t fd = m68k_read_memory_16(m68k_get_reg(0, M68K_REG_A7));
  543. int r = v68_io_close(fd);
  544. m68k_set_reg(M68K_REG_D0, r);
  545. logcall("fd=%d\n", fd);
  546. /* Unset bit from fd bitmap */
  547. if(!r) {
  548. fd -= 4;
  549. uint32_t fdmapaddr = v68.cur_prog_addr + 0x24 + (fd >> 3);
  550. m68k_write_memory_8(fdmapaddr, m68k_read_memory_8(fdmapaddr) & ~(1 << (fd & 0x07)));
  551. }
  552. }
  553. break;
  554. case DOS_CALL_WRITE: {
  555. uint16_t fd = m68k_read_memory_16(m68k_get_reg(0, M68K_REG_A7));
  556. uint32_t buffer = m68k_read_memory_32(m68k_get_reg(0, M68K_REG_A7) + 2);
  557. uint32_t len = m68k_read_memory_32(m68k_get_reg(0, M68K_REG_A7) + 6);
  558. int r = v68_io_write(fd, &v68.ram[buffer], len);
  559. logcall("fd=%d buffer=0x%08x len=%d r=%d\n", fd, buffer, len, r);
  560. m68k_set_reg(M68K_REG_D0, r);
  561. }
  562. break;
  563. case DOS_CALL_READ: {
  564. uint16_t fd = m68k_read_memory_16(m68k_get_reg(0, M68K_REG_A7));
  565. uint32_t buffer = m68k_read_memory_32(m68k_get_reg(0, M68K_REG_A7) + 2);
  566. uint32_t len = m68k_read_memory_32(m68k_get_reg(0, M68K_REG_A7) + 6);
  567. int pos_before = v68_io_tell(fd);
  568. int r = v68_io_read(fd, &v68.ram[buffer], len);
  569. logcall("fd=%d buffer=0x%08x len=%d r=%d pos_before=0x%08x pos=0x%08x\n", fd, buffer, len, r, pos_before, v68_io_tell(fd));
  570. m68k_set_reg(M68K_REG_D0, r);
  571. }
  572. break;
  573. case DOS_CALL_FGETC: {
  574. uint16_t fd = m68k_read_memory_16(m68k_get_reg(0, M68K_REG_A7));
  575. uint8_t b = 0;
  576. int r = v68_io_read(fd, &b, 1);
  577. logcall("fd=%d r=%d\n", fd, r);
  578. m68k_set_reg(M68K_REG_D0, b);
  579. }
  580. break;
  581. case DOS_CALL_SEEK: {
  582. uint16_t fd = m68k_read_memory_16(m68k_get_reg(0, M68K_REG_A7));
  583. uint32_t ofs = m68k_read_memory_32(m68k_get_reg(0, M68K_REG_A7) + 2);
  584. uint32_t whence = m68k_read_memory_16(m68k_get_reg(0, M68K_REG_A7) + 6);
  585. int r = v68_io_seek(fd, ofs, whence);
  586. logcall("fd=%d ofs=0x%08x whence=0x%04x r=0x%08x pos=0x%08x\n", fd, ofs, whence, r, v68_io_tell(fd));
  587. m68k_set_reg(M68K_REG_D0, r);
  588. }
  589. break;
  590. case DOS_CALL_INTVCS: {
  591. uint16_t intno = m68k_read_memory_16(m68k_get_reg(0, M68K_REG_A7));
  592. uint32_t jobadr = m68k_read_memory_32(m68k_get_reg(0, M68K_REG_A7) + 2);
  593. if(intno <= 0xff) {
  594. m68k_write_memory_32(intno * 4, jobadr);
  595. }
  596. logcall("intno=%04x jobaddr=%08x\n", intno, jobadr);
  597. m68k_set_reg(M68K_REG_D0, 0);
  598. }
  599. break;
  600. case DOS_CALL_INTVCG: {
  601. uint16_t intno = m68k_read_memory_16(m68k_get_reg(0, M68K_REG_A7));
  602. m68k_set_reg(M68K_REG_D0, m68k_read_memory_32(intno * 4));
  603. }
  604. break;
  605. case DOS_CALL_PRNSNS: {
  606. m68k_set_reg(M68K_REG_D0, 0);
  607. }
  608. break;
  609. case DOS_CALL_CONCTRL: {
  610. uint16_t md = m68k_read_memory_16(m68k_get_reg(0, M68K_REG_A7));
  611. switch(md) {
  612. case 0x01: {
  613. uint32_t mesptr = m68k_read_memory_32(m68k_get_reg(0, M68K_REG_A7) + 2);
  614. uint8_t *str_ptr = &v68.ram[mesptr];
  615. size_t l = strnlen((char *)str_ptr, v68.ram_size - mesptr);
  616. sjis_print_utf8(str_ptr, l);
  617. }
  618. break;
  619. default:
  620. logcall("conctrl md=%d\n", md);
  621. }
  622. }
  623. break;
  624. case DOS_CALL_NAMECK: {
  625. #define IS_SLASH(a) ((a) == '/' || (a) == '\\')
  626. uint32_t filename = m68k_read_memory_32(m68k_get_reg(0, M68K_REG_A7));
  627. uint32_t buffer = m68k_read_memory_32(m68k_get_reg(0, M68K_REG_A7) + 4);
  628. uint32_t len = strnlen((char *)&v68.ram[filename], v68.ram_size - filename);
  629. /* Do some checks on the input filename */
  630. if(v68.ram[filename] == ':' || v68.ram[filename] == '-' || v68.ram[filename] == '"' || v68.ram[filename] == '\'' || v68.ram[filename] == ',' || v68.ram[filename] == '[' || v68.ram[filename] == ']') {
  631. m68k_set_reg(M68K_REG_D0, 0xfffffff3); // -13 Invalid file name specification
  632. break;
  633. }
  634. if(buffer + 91 >= v68.ram_size) { /* Check if there's enough room for 91 bytes */
  635. m68k_set_reg(M68K_REG_D0, 0xfffffff3); // -13 Invalid file name specification
  636. break;
  637. }
  638. memset(&v68.ram[buffer], 0, 91);
  639. int last_slash = -1;
  640. int last_dot = -1;
  641. /* Drive name */
  642. int drv = v68_io_curdrv(); /* If drive is not specified, get cur drive */
  643. if(len >= 2 && m68k_read_memory_8(filename + 1) == ':') {
  644. drv = toupper(m68k_read_memory_8(filename)) - 'A';
  645. last_slash = 1;
  646. }
  647. if(drv < 0 || drv >= 26) {
  648. m68k_set_reg(M68K_REG_D0, 0xfffffff1); // -15 Invalid drive specification
  649. break;
  650. }
  651. v68.ram[buffer + 0] = drv + 'A';
  652. v68.ram[buffer + 1] = ':';
  653. for(int i = 0; i < len; i++) {
  654. if(IS_SLASH(v68.ram[filename + i])) {
  655. last_slash = i;
  656. }
  657. }
  658. for(int i = last_slash + 1; i < len; i++) {
  659. if(v68.ram[filename + i] == '.') {
  660. last_dot = i;
  661. }
  662. }
  663. if(IS_SLASH(v68.ram[filename])) { /* Starts with a slash */
  664. if(last_slash > 62) {
  665. m68k_set_reg(M68K_REG_D0, 0xfffffff3); // -13 Invalid file name specification
  666. break;
  667. }
  668. for(int i = 0; i < last_slash; i++) {
  669. int c = v68.ram[filename + i];
  670. v68.ram[buffer + i + 2] = (c == '/' ? '\\' : c);
  671. }
  672. } else if(v68.ram[filename + 1] == ':') {
  673. v68.ram[buffer + 2] = '\\';
  674. int s = IS_SLASH(v68.ram[filename + 2]) ? 3 : 2;
  675. if(last_slash - s > 63) {
  676. m68k_set_reg(M68K_REG_D0, 0xfffffff3); // -13 Invalid file name specification
  677. break;
  678. }
  679. for(int i = 0; i < last_slash - 2; i++) {
  680. int c = v68.ram[filename + i + s];
  681. v68.ram[buffer + i + 3] = (c == '/' ? '\\' : c);
  682. }
  683. } else {
  684. char curdir[65];
  685. v68_io_getcwd(drv, curdir, 64);
  686. int l = strnlen(curdir, sizeof(curdir) - 1);
  687. if(l + last_slash > 62) {
  688. m68k_set_reg(M68K_REG_D0, 0xfffffff3); // -13 Invalid file name specification
  689. break;
  690. }
  691. v68.ram[buffer + 2] = '\\';
  692. for(int i = 0; i < l; i++) {
  693. int c = curdir[i];
  694. v68.ram[buffer + 3 + i] = c == '/' ? '\\' : c;
  695. }
  696. v68.ram[buffer + 3 + l] = '\\';
  697. for(int i = 0; i < last_slash; i++) {
  698. int c = v68.ram[filename + i];
  699. v68.ram[buffer + 4 + l + i] = c == '/' ? '\\' : c;
  700. }
  701. }
  702. /* filename */
  703. if(last_slash + 1 < len) {
  704. int flen = len - last_slash - 1;
  705. if(last_dot > last_slash && last_dot - last_slash < flen) flen = last_dot - last_slash - 1;
  706. if(flen > 18) flen = 18;
  707. memcpy(&v68.ram[buffer + 67], &v68.ram[filename + last_slash + 1], flen);
  708. }
  709. /* extension */
  710. if(last_dot > -1 && last_dot + 1 < len) {
  711. int flen = len - last_dot;
  712. if(flen > 4) flen = 4;
  713. memcpy(&v68.ram[buffer + 86], &v68.ram[filename + last_dot], flen);
  714. }
  715. }
  716. break;
  717. case DOS_CALL_GETPDB: {
  718. m68k_set_reg(M68K_REG_D0, v68.cur_prog_addr - 0x10);
  719. }
  720. break;
  721. default:
  722. logcall("V68 DOS CALL %04x %s\n", instr, dos_call_names[call]);
  723. break;
  724. }
  725. return 0;
  726. }