dc.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. /*
  2. dc.c - Dreamcast support for uCON64
  3. Copyright (c) 2004 NoisyB <noisyb@gmx.net>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. */
  16. #ifdef HAVE_CONFIG_H
  17. #include "config.h"
  18. #endif
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #ifdef HAVE_UNISTD_H
  23. #include <unistd.h>
  24. #endif
  25. #include "misc/file.h"
  26. #include "misc/misc.h"
  27. #include "misc/property.h"
  28. #include "misc/string.h"
  29. #ifdef USE_ZLIB
  30. #include "misc/archive.h"
  31. #endif
  32. #include "misc/getopt2.h" // st_getopt2_t
  33. #include "ucon64.h"
  34. #include "ucon64_misc.h"
  35. #include "dc.h"
  36. const st_getopt2_t dc_usage[] =
  37. {
  38. {
  39. NULL, 0, 0, 0,
  40. NULL, "Dreamcast" /* "1998 SEGA http://www.sega.com" */,
  41. NULL
  42. },
  43. {
  44. "dc", 0, 0, UCON64_DC,
  45. NULL, "force recognition",
  46. &ucon64_wf[WF_OBJ_DC_SWITCH]
  47. },
  48. #if 0
  49. {
  50. "vms", 1, 0, UCON64_VMS,
  51. "SAV", "convert NES SAV file to a VMS file for use with NesterDC",
  52. NULL
  53. },
  54. #endif
  55. {
  56. "scr", 0, 0, UCON64_SCR,
  57. NULL, "scramble 1ST_READ.BIN for selfboot CDs",
  58. &ucon64_wf[WF_OBJ_DC_DEFAULT]
  59. },
  60. {
  61. "unscr", 0, 0, UCON64_UNSCR,
  62. NULL, "unscramble 1ST_READ.BIN for non-selfboot CDs",
  63. &ucon64_wf[WF_OBJ_DC_DEFAULT]
  64. },
  65. #if 0
  66. {
  67. "ip", 1, 0, UCON64_IP,
  68. "FILE", "extract ip.bin FILE from IMAGE; " OPTION_LONG_S "rom=IMAGE",
  69. NULL
  70. },
  71. #endif
  72. {
  73. "mkip", 0, 0, UCON64_MKIP,
  74. NULL, "generate IP.BIN file with default values",
  75. &ucon64_wf[WF_OBJ_DC_NO_ROM]
  76. },
  77. {
  78. "parse", 1, 0, UCON64_PARSE,
  79. "TEMPLATE", "parse TEMPLATE file into a IP.BIN;\n"
  80. "creates an empty template when TEMPLATE does not exist",
  81. &ucon64_wf[WF_OBJ_DC_NO_ROM]
  82. },
  83. {NULL, 0, 0, 0, NULL, NULL, NULL}
  84. };
  85. static int
  86. calc_crc (const unsigned char *buf, int size)
  87. {
  88. int i, c, n = 0xffff;
  89. for (i = 0; i < size; i++)
  90. {
  91. n ^= (buf[i] << 8);
  92. for (c = 0; c < 8; c++)
  93. if (n & 0x8000)
  94. n = (n << 1) ^ 4129;
  95. else
  96. n = (n << 1);
  97. }
  98. return n & 0xffff;
  99. }
  100. static void
  101. update_crc (char *ip)
  102. {
  103. int n = calc_crc ((unsigned char *) (ip + 0x40), 16);
  104. char buf[5];
  105. sprintf (buf, "%04X", n);
  106. if (memcmp (buf, ip + 0x20, 4))
  107. {
  108. printf ("Setting CRC to %s (was %.4s)\n", buf, ip + 0x20);
  109. memcpy (ip + 0x20, buf, 4);
  110. }
  111. }
  112. static unsigned int seed;
  113. static void
  114. dc_srand (unsigned int n)
  115. {
  116. seed = n & 0xffff;
  117. }
  118. static unsigned int
  119. dc_rand ()
  120. {
  121. seed = (seed * 2109 + 9273) & 0x7fff;
  122. return (seed + 0xc000) & 0xffff;
  123. }
  124. #if 0
  125. // header for SAV -> VMS conversion
  126. static const uint8_t nstrsave_bin[1024] = {
  127. 0x4e, 0x45, 0x53, 0x52, 0x4f, 0x4d, 0x2e, 0x4e, // 0x8 (8)
  128. 0x45, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x10 (16)
  129. 0x4e, 0x65, 0x73, 0x74, 0x65, 0x72, 0x44, 0x43, // 0x18 (24)
  130. 0x20, 0x53, 0x61, 0x76, 0x65, 0x52, 0x61, 0x6d, // 0x20 (32)
  131. 0x20, 0x46, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x00, // 0x28 (40)
  132. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x30 (48)
  133. 0x2a, 0x2a, 0x2a, 0x4e, 0x65, 0x73, 0x74, 0x65, // 0x38 (56)
  134. 0x72, 0x44, 0x43, 0x2a, 0x2a, 0x2a, 0x00, 0x00, // 0x40 (64)
  135. 0x01, 0x00, 0x00, 0x00, 0x01, 0x3f, 0x00, 0x00, // 0x48 (72)
  136. 0x80, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x50 (80)
  137. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x58 (88)
  138. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x60 (96)
  139. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x68 (104)
  140. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x70 (112)
  141. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x78 (120)
  142. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x80 (128)
  143. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x88 (136)
  144. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x90 (144)
  145. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x98 (152)
  146. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xa0 (160)
  147. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xa8 (168)
  148. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xb0 (176)
  149. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xb8 (184)
  150. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xc0 (192)
  151. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xc8 (200)
  152. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xd0 (208)
  153. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xd8 (216)
  154. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xe0 (224)
  155. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xe8 (232)
  156. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xf0 (240)
  157. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xf8 (248)
  158. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x100 (256)
  159. 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x108 (264)
  160. 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x110 (272)
  161. 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x118 (280)
  162. 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x120 (288)
  163. 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x128 (296)
  164. 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x130 (304)
  165. 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x138 (312)
  166. 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x140 (320)
  167. 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x148 (328)
  168. 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x150 (336)
  169. 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x158 (344)
  170. 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x160 (352)
  171. 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x168 (360)
  172. 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x170 (368)
  173. 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x178 (376)
  174. 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x180 (384)
  175. 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x188 (392)
  176. 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x190 (400)
  177. 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x198 (408)
  178. 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1a0 (416)
  179. 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1a8 (424)
  180. 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1b0 (432)
  181. 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1b8 (440)
  182. 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1c0 (448)
  183. 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1c8 (456)
  184. 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1d0 (464)
  185. 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1d8 (472)
  186. 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1e0 (480)
  187. 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1e8 (488)
  188. 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1f0 (496)
  189. 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1f8 (504)
  190. 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x200 (512)
  191. 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x208 (520)
  192. 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x210 (528)
  193. 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x218 (536)
  194. 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x220 (544)
  195. 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x228 (552)
  196. 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x230 (560)
  197. 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x238 (568)
  198. 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x240 (576)
  199. 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x248 (584)
  200. 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x250 (592)
  201. 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x258 (600)
  202. 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x260 (608)
  203. 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x268 (616)
  204. 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x270 (624)
  205. 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x278 (632)
  206. 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x280 (640)
  207. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x288 (648)
  208. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x290 (656)
  209. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x298 (664)
  210. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2a0 (672)
  211. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2a8 (680)
  212. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2b0 (688)
  213. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2b8 (696)
  214. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2c0 (704)
  215. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2c8 (712)
  216. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2d0 (720)
  217. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2d8 (728)
  218. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2e0 (736)
  219. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2e8 (744)
  220. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2f0 (752)
  221. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2f8 (760)
  222. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x300 (768)
  223. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x308 (776)
  224. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x310 (784)
  225. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x318 (792)
  226. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x320 (800)
  227. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x328 (808)
  228. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x330 (816)
  229. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x338 (824)
  230. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x340 (832)
  231. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x348 (840)
  232. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x350 (848)
  233. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x358 (856)
  234. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x360 (864)
  235. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x368 (872)
  236. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x370 (880)
  237. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x378 (888)
  238. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x380 (896)
  239. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x388 (904)
  240. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x390 (912)
  241. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x398 (920)
  242. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3a0 (928)
  243. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3a8 (936)
  244. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3b0 (944)
  245. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3b8 (952)
  246. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3c0 (960)
  247. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3c8 (968)
  248. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3d0 (976)
  249. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3d8 (984)
  250. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3e0 (992)
  251. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3e8 (1000)
  252. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3f0 (1008)
  253. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3f8 (1016)
  254. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // 0x400 (1024)
  255. };
  256. #endif
  257. int
  258. dc_init (st_rominfo_t *rominfo)
  259. {
  260. int result = -1;
  261. rominfo->console_usage = dc_usage[0].help;
  262. return result;
  263. }
  264. static int
  265. check_areasym (char *ptr, int len)
  266. {
  267. int i, a = 0;
  268. for (i = 0; i < len; i++)
  269. switch (ptr[i])
  270. {
  271. case 'J':
  272. a |= (1<<0);
  273. break;
  274. case 'U':
  275. a |= (1<<1);
  276. break;
  277. case 'E':
  278. a |= (1<<2);
  279. break;
  280. case ' ':
  281. break;
  282. default:
  283. fprintf (stderr, "ERROR: Unknown area symbol '%c'\n", ptr[i]);
  284. return -1;
  285. }
  286. for (i = 0; i < len; i++)
  287. if ((a & (1<<i)) == 0)
  288. ptr[i] = ' ';
  289. else
  290. ptr[i] = "JUE"[i];
  291. return 0;
  292. }
  293. typedef struct
  294. {
  295. char *name;
  296. int pos;
  297. int len;
  298. int (*extra_check) (char *, int);
  299. char *def;
  300. char *comment;
  301. } st_templ_t;
  302. st_templ_t templ[] =
  303. {
  304. {"hardware_id", 0x0, 0x10, NULL, "SEGA SEGAKATANA", "Hardware ID (always \"SEGA SEGAKATANA\")"},
  305. {"maker_id", 0x10, 0x10, NULL, "SEGA ENTERPRISES", "Maker ID (always \"SEGA ENTERPRISES\")"},
  306. {"device_info", 0x20, 0x10, NULL, "0000 CD-ROM1/1", "Device Information"},
  307. {"area_symbols", 0x30, 0x8, check_areasym, "JUE", "Area Symbols"},
  308. {"peripherals", 0x38, 0x8, NULL, "E000F10", "Peripherals"},
  309. {"product_no", 0x40, 0xa, NULL, "T0000", "Product number (\"HDR-nnnn\" etc.)"},
  310. {"version", 0x4a, 0x6, NULL, "V1.000", "Product version"},
  311. {"release_date", 0x50, 0x10, NULL, "20000627", "Release date (YYYYMMDD)"},
  312. {"boot_filename", 0x60, 0x10, NULL, "1ST_READ.BIN", "Boot filename (usually \"1ST_READ.BIN\")"},
  313. {"sw_maker_name", 0x70, 0x10, NULL, "YOUR NAME HERE", "Name of the company that produced the disc"},
  314. {"game_title", 0x80, 0x80, NULL, "TITLE OF THE SOFTWARE", "Name of the software"},
  315. {NULL, 0, 0, NULL, NULL, NULL}
  316. };
  317. static int
  318. parse_templ (const char *templ_file, char *ip)
  319. {
  320. int filled_in[MAXBUFSIZE];
  321. static char buf[MAXBUFSIZE];
  322. int i;
  323. memset (filled_in, 0, sizeof (filled_in));
  324. for (i = 0; templ[i].name; i++)
  325. {
  326. char *p = buf;
  327. get_property (templ_file, templ[i].name, p, templ[i].def);
  328. strtriml (strtrimr (p));
  329. if (!(*p))
  330. continue;
  331. memset (ip + templ[i].pos, ' ', templ[i].len);
  332. if ((int) strlen (p) > templ[i].len)
  333. {
  334. fprintf (stderr, "ERROR: Data for field \"%s\" is too long... stripping to %d chars\n",
  335. templ[i].name, templ[i].len);
  336. p[templ[i].len] = 0;
  337. }
  338. memcpy (ip + templ[i].pos, p, strlen (p));
  339. if (templ[i].extra_check)
  340. if (templ[i].extra_check (ip + templ[i].pos, templ[i].len) == -1)
  341. return -1;
  342. filled_in[i] = 1;
  343. }
  344. for (i = 0; templ[i].name; i++)
  345. if (!filled_in[i])
  346. {
  347. fprintf (stderr, "ERROR: Missing value for \"%s\"\n", templ[i].name);
  348. return -1;
  349. }
  350. return 0;
  351. }
  352. int
  353. dc_parse (const char *templ_file)
  354. {
  355. char ip[0x8000], dest_name[FILENAME_MAX];
  356. if (access (templ_file, F_OK) == -1)
  357. {
  358. int i = 0;
  359. printf ("Creating empty template file: \"%s\"\n", templ_file);
  360. for (i = 0; templ[i].name; i++)
  361. set_property (templ_file, templ[i].name, templ[i].def, templ[i].comment);
  362. printf (ucon64_msg[WROTE], templ_file);
  363. }
  364. if (parse_templ (templ_file, ip) == -1)
  365. return -1;
  366. update_crc (ip);
  367. strcpy (dest_name, "ip.bin");
  368. ucon64_file_handler (dest_name, NULL, 0);
  369. ucon64_fwrite (ip, 0, 0x8000, dest_name, "wb");
  370. printf (ucon64_msg[WROTE], dest_name);
  371. return 0;
  372. }
  373. int
  374. dc_mkip (void)
  375. {
  376. dc_parse ("default");
  377. return 0;
  378. }
  379. static int
  380. load_chunk (FILE * fh, unsigned char *ptr, int32_t sz)
  381. {
  382. #define MAXCHUNK (2048*1024)
  383. static int idx[MAXCHUNK / 32];
  384. int32_t i;
  385. /* Convert chunk size to number of slices */
  386. sz /= 32;
  387. /* Initialize index table with unity,
  388. so that each slice gets loaded exactly once */
  389. for (i = 0; i < sz; i++)
  390. idx[i] = i;
  391. for (i = sz - 1; i >= 0; --i)
  392. {
  393. /* Select a replacement index */
  394. int x = (dc_rand () * i) >> 16;
  395. /* Swap */
  396. int tmp = idx[i];
  397. idx[i] = idx[x];
  398. idx[x] = tmp;
  399. /* Load resulting slice */
  400. if (fread (ptr + 32 * idx[i], 1, 32, fh) != 32)
  401. return -1;
  402. }
  403. return 0;
  404. }
  405. static int
  406. load_file (FILE * fh, unsigned char *ptr, uint32_t filesz)
  407. {
  408. uint32_t chunksz;
  409. dc_srand (filesz);
  410. /* Descramble 2 meg blocks for as long as possible, then
  411. gradually reduce the window down to 32 bytes (1 slice) */
  412. for (chunksz = MAXCHUNK; chunksz >= 32; chunksz >>= 1)
  413. while (filesz >= chunksz)
  414. {
  415. load_chunk (fh, ptr, chunksz);
  416. filesz -= chunksz;
  417. ptr += chunksz;
  418. }
  419. /* Load final incomplete slice */
  420. if (filesz)
  421. if (fread (ptr, 1, filesz, fh) != filesz)
  422. return -1;
  423. return 0;
  424. }
  425. static int
  426. save_chunk (FILE * fh, unsigned char *ptr, int32_t sz)
  427. {
  428. static int idx[MAXCHUNK / 32];
  429. int32_t i;
  430. /* Convert chunk size to number of slices */
  431. sz /= 32;
  432. /* Initialize index table with unity,
  433. so that each slice gets saved exactly once */
  434. for (i = 0; i < sz; i++)
  435. idx[i] = i;
  436. for (i = sz - 1; i >= 0; --i)
  437. {
  438. /* Select a replacement index */
  439. int x = (dc_rand () * i) >> 16;
  440. /* Swap */
  441. int tmp = idx[i];
  442. idx[i] = idx[x];
  443. idx[x] = tmp;
  444. /* Save resulting slice */
  445. if (fwrite (ptr + 32 * idx[i], 1, 32, fh) != 32)
  446. return -1;
  447. }
  448. return 0;
  449. }
  450. static int
  451. save_file (FILE * fh, unsigned char *ptr, uint32_t filesz)
  452. {
  453. uint32_t chunksz;
  454. dc_srand (filesz);
  455. /* Descramble 2 meg blocks for as long as possible, then
  456. gradually reduce the window down to 32 bytes (1 slice) */
  457. for (chunksz = MAXCHUNK; chunksz >= 32; chunksz >>= 1)
  458. while (filesz >= chunksz)
  459. {
  460. save_chunk (fh, ptr, chunksz);
  461. filesz -= chunksz;
  462. ptr += chunksz;
  463. }
  464. /* Save final incomplete slice */
  465. if (filesz)
  466. if (fwrite (ptr, 1, filesz, fh) != filesz)
  467. return -1;
  468. return 0;
  469. }
  470. static int
  471. descramble (const char *src, char *dst)
  472. {
  473. unsigned char *ptr = NULL;
  474. uint32_t sz = 0;
  475. FILE *fh;
  476. if (!(fh = fopen (src, "rb")))
  477. return -1;
  478. sz = fsizeof (src);
  479. if (!(ptr = (unsigned char *) malloc (sz)))
  480. return -1;
  481. load_file (fh, ptr, sz);
  482. fclose (fh);
  483. if (!(fh = fopen (dst, "wb")))
  484. return -1;
  485. if (fwrite (ptr, 1, sz, fh) != sz)
  486. return -1;
  487. fclose (fh);
  488. free (ptr);
  489. return 0;
  490. }
  491. static int
  492. scramble (const char *src, char *dst)
  493. {
  494. unsigned char *ptr = NULL;
  495. uint32_t sz = 0;
  496. FILE *fh;
  497. if (!(fh = fopen (src, "rb")))
  498. return -1;
  499. sz = fsizeof (src);
  500. if (!(ptr = (unsigned char *) malloc (sz)))
  501. return -1;
  502. if (fread (ptr, 1, sz, fh) != sz)
  503. return -1;
  504. fclose (fh);
  505. if (!(fh == fopen (dst, "wb")))
  506. return -1;
  507. save_file (fh, ptr, sz);
  508. fclose (fh);
  509. free (ptr);
  510. return 0;
  511. }
  512. int
  513. dc_scramble (void)
  514. {
  515. char dest_name[FILENAME_MAX];
  516. strcpy (dest_name, ucon64.rom);
  517. ucon64_file_handler (dest_name, NULL, 0);
  518. if (!scramble (ucon64.rom, dest_name))
  519. printf (ucon64_msg[WROTE], dest_name);
  520. else
  521. fprintf (stderr, ucon64_msg[WRITE_ERROR], dest_name);
  522. return 0;
  523. }
  524. int
  525. dc_unscramble (void)
  526. {
  527. char dest_name[FILENAME_MAX];
  528. strcpy (dest_name, ucon64.rom);
  529. ucon64_file_handler (dest_name, NULL, 0);
  530. if (!descramble (ucon64.rom, dest_name))
  531. printf (ucon64_msg[WROTE], dest_name);
  532. else
  533. fprintf (stderr, ucon64_msg[WRITE_ERROR], dest_name);
  534. return 0;
  535. }