Saves.cs 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984
  1. using System;
  2. using System.IO;
  3. using System.Text.RegularExpressions;
  4. namespace FF8
  5. {
  6. // ref http://wiki.ffrtt.ru/index.php/FF8/Variables copied the table into excel and tried to
  7. // changed the list into c# code. I was thinking atleast some of it would be useful.
  8. internal struct FF8Variables
  9. {
  10. internal enum Characters
  11. {
  12. // I noticed some values were in order of these characters so I made those values into arrays
  13. // and put the character names into an enum.
  14. Squall, Zell, Irvine, Quistis, Rinoa, Selphie, Seifer, Edea, Count // Count is the last value and is the number of characters in enum
  15. }
  16. unsafe fixed byte byte03[4]; //[0-3]unused in fields (always "FF-8")
  17. private ulong Steps; //[4]Steps (used to generate random encounters)
  18. private ulong Payslip; //[8]Payslip
  19. private unsafe fixed byte byte1215[4]; //[12-15]unused in fields
  20. private short SeedRankPts; //[16]SeeD rank points?
  21. private unsafe fixed byte byte1819[2]; //[18-19]unused in fields
  22. private ulong BattlesWon; //[20]Battles won. (Fun fact: this affects the basketball shot in Trabia.)
  23. private unsafe fixed byte byte2425[2]; //[24-25]unused in fields
  24. private ushort EscapedBattles; //[26]Battles escaped.
  25. private unsafe fixed ushort EnemiesKilled[(int)Characters.Count];
  26. //ushort ushort28; //[28]Enemies killed by Squall
  27. //ushort ushort30; //[30]Enemies killed by Zell
  28. //ushort ushort32; //[32]Enemies killed by Irvine
  29. //ushort ushort34; //[34]Enemies killed by Quistis
  30. //ushort ushort36; //[36]Enemies killed by Rinoa
  31. //ushort ushort38; //[38]Enemies killed by Selphie
  32. //ushort ushort40; //[40]Enemies killed by Seifer
  33. //ushort ushort42; //[42]Enemies killed by Edea
  34. private unsafe fixed ushort DeathCounter[(int)Characters.Count];
  35. //ushort ushort44; //[44]Squall death count
  36. //ushort ushort46; //[46]Zell death count
  37. //ushort ushort48; //[48]Irvine death count
  38. //ushort ushort50; //[50]Quistis death count
  39. //ushort ushort52; //[52]Rinoa death count
  40. //ushort ushort54; //[54]Selphie death count
  41. //ushort ushort56; //[56]Seifer death count
  42. //ushort ushort58; //[58]Edea death count
  43. private unsafe fixed byte byte6067[8]; //[60-67]unused in fields
  44. private ulong EnemiesKilledTotal; //[68]Enemies killed
  45. private ulong Gill; //[72]Amount of Gil the party currently has
  46. private ulong GillLaguna; //[76]Amount of Gil Laguna's party has
  47. private ulong FMVFrames; //[80]Counts the number of frames since the current movie started playing. (default fps is 15?)
  48. private ushort LastArea; //[84]Last area visited.
  49. private sbyte CurrentCarRent; //[86]Current car rent.
  50. private sbyte sbyte87; //[87]Built-in engine variable. No idea what it does. Scripts always check if it's equal to 0 or 10. Related to music.
  51. private sbyte sbyte88; //[88]Built-in engine variable. Used exclusively on save points. Never written to with field scripts. Related to Siren's Move-Find ability.
  52. private unsafe fixed byte byte89103[15]; //[89-103]unused in fields
  53. private ulong ulong104; //[104]Seems related to SARALYDISPON/SARALYON/MUSICLOAD/PHSPOWER opcodes
  54. private ulong ulong108; //[108]Music related
  55. private ulong ulong112; //[112]unused in fields
  56. private unsafe fixed byte DrawPtsFeild[32]; //[116-147]Draw points in field
  57. private unsafe fixed byte DrawPtsWorld[31]; //[148-179]Draw points in worldmap
  58. private unsafe fixed byte byte180255[76]; //[180-255]unused in fields
  59. private ushort StoryQuestprogress; //[256]Main Story quest progress.
  60. private byte byte258; //[258]not investigated
  61. private unsafe fixed byte byte259260[2]; //[259-260]unused in fields
  62. private byte byte261; //[261]not investigated
  63. private unsafe fixed byte byte262263[2]; //[262-263]unused in fields
  64. private byte byte264; //[264]not investigated
  65. private byte byte265; //[265]not investigated
  66. private byte WorldMapVersion; //[266]World map version? (3=Esthar locations unlocked)
  67. private byte byte267; //[267]unused in fields
  68. private byte byte268; //[268]not investigated
  69. private byte byte269; //[269]not investigated
  70. private byte byte270; //[270]not investigated
  71. private byte byte271; //[271]unused in fields
  72. private unsafe fixed byte byte272299[28]; //[272-299]SO MANY F***ING CARD GAME VARIABLES
  73. private byte CardQueenrecards; //[300]Card Queen re-cards.
  74. private unsafe fixed byte byte301303[3]; //[301-303]unused in fields
  75. private unsafe fixed byte TimberManiacsIssues[2]; //[304-305]Timber Maniacs issues found.
  76. private unsafe fixed byte Hacktuar[14]; //[306-319]Reserved for Hacktuar / FF8Voice
  77. private unsafe fixed byte UltimeciaGallery[3]; //[320-332]Ultimecia Gallery related (pictures viewed?)
  78. private byte UltimeciaArmory; //[333]Ultimecia Armory chest flags
  79. private byte UltimeciaCastle; //[334]Ultimecia Castle seals. See SEALEDOFF for details.
  80. private byte Card; //[335]Card related
  81. private byte BusRelated; //[336]Deling City bus related
  82. private unsafe fixed byte GatesOpened[3]; //[338-340]Deling Sewer gates opened
  83. private byte byte341; //[341]Does lots of things.5
  84. private byte BusSystem; //[342]Deling City bus system
  85. private byte byte343; //[343]G-Garden door/event flags.
  86. private byte byte344; //[344]B-Garden / G-Garden event flags (during GvG)
  87. private byte byte345; //[345]G-Garden door/event flags.
  88. private unsafe fixed byte byte346349[4]; //[346-349]FH Instrument (346 Zell, 347 Irvine, 348 Selphie, 349 Quistis)
  89. private unsafe fixed ushort ushort350356[7]; //[350-356]Health Bars (Garden mech fight)
  90. private byte byte358; //[358]Space station talk flags, Centra ruins related (beat odin?).
  91. private byte byte359; //[359]Centra ruins related (beat odin?).
  92. private ulong ulong360; //[360]Choice of FH music.
  93. private unsafe fixed byte byte364368[5]; //[364-368]Randomly generated code for Centra Ruins.
  94. private unsafe fixed byte byte369370[2]; //[369-370]Ultimecia Castle flags
  95. private byte byte371; //[371]unused in fields
  96. private unsafe fixed byte byte372376[5]; //[372-376]Ultimecia boss/timer/item flags
  97. private byte byte377; //[377]Ultimecia organ note controller
  98. private byte byte378; //[378]Centra Ruins timer (controls blackout messages from Odin)
  99. private byte byte379; //[379]unused in fields
  100. private ushort ushort380; //[380]Squall health during mech fight.
  101. private unsafe fixed byte byte382383[2]; //[382-383]unused in fields
  102. private byte byte384; //[384]Something about Laguna's time periods and GFs.
  103. private byte byte385; //[385]Laguna dialogue in pub. Only the +2 bit is ever set. Don't change the +1 bit.
  104. private byte byte387; //[387]Winhill progress?
  105. private byte byte388; //[388]Timber Maniacs HQ talk flags (main lobby)
  106. private byte byte389; //[389]Timber Maniacs HQ talk flags (office room)
  107. private byte byte390; //[390]Edea talk flags at her house
  108. private byte byte391; //[391]Laguna talk flags (in his office, disc 3)
  109. private byte byte392; //[392]unknown (used in Edea's house and in the Balamb Garden computer system)
  110. private unsafe fixed byte byte393399[7]; //[393-399]unused in fields
  111. private ulong ulong400and404; //[400 and 404]Related to monsters killed in Winhill, but I don't think it actually does anything. Will investigate.
  112. private byte byte408; //[408]unused in fields
  113. private byte byte409; //[409]Balamb Garden computer system
  114. private unsafe fixed byte byte410431[22]; //[410-431]unused in fields
  115. private byte byte432; //[432]BG Main hall flags
  116. private byte byte433; //[433]Flags. Switches are assigned all over BG. No idea what any of them control.
  117. private byte byte434; //[434]Flags. Switches are assigned all over BG. No idea what any of them control.
  118. private byte byte435; //[435]Flags. Switches are assigned all over BG. No idea what any of them control.
  119. private byte byte436; //[436]Moomba friendship level in the prison? Some actions cause these flags to be set.
  120. private byte byte437; //[437]In BG on Disc 2, keeps track of who's in your party. In the prison, it's the current floor you're on.
  121. private byte byte438; //[438]Cid vs Norg event flags
  122. private byte byte439; //[439]Cid vs Norg event flags
  123. private byte byte440; //[440]Event flags. (+1 Quad ambush, +2 quad item giver, +4/+8 Infirmary helped, +16 Nida, +64 Kadowaki Elixir, +128 Training center)
  124. private byte byte441; //[441]Cid vs Norg event flags
  125. private byte byte442; //[442]Rinoa Garden tour flags
  126. private ushort ushort443; //[443]Zell Health in Prison (Hacktuar)
  127. private unsafe fixed byte byte445447[3]; //[445-447]Propagator defeated flags
  128. private ushort ushort448; //[448]Unknown
  129. private unsafe fixed byte byte450451[2]; //[450-451]Various magazine/talk flags
  130. private byte byte452; //[452]Lunatic Pandora areas visited?
  131. private unsafe fixed byte byte453455[3]; //[453-455]Moomba teleport variables
  132. private unsafe fixed byte byte456457[2]; //[456-457]unused in fields
  133. private unsafe fixed byte byte458459[2]; //[458-459]Used with MUSICSKIP in some Balamb Garden areas
  134. private byte byte460; //[460]Random flags (some used for Card Club)
  135. private unsafe fixed byte byte461473[13]; //[461-473]unused in fields
  136. private byte byte474; //[474]Random flags (some used for Card Club)
  137. private unsafe fixed byte byte475478[4]; //[475-478]CC Group variables
  138. private byte byte479; //[479]If set to 0, disables all random battles during area loading.
  139. private byte byte480; //[480]State of students in classroom (what they're doing).
  140. private byte byte481; //[481]Controls a conversation in the cafeteria.
  141. private short short482; //[482]Error ratio of missiles
  142. private byte byte484; //[484]Missile Base progression?
  143. private byte byte485; //[485]ToUK Progression (initially 0b111010101, +2 on finish quest. No other pops)
  144. private byte byte486; //[486]ToUK room? (used to control map jumps in the maze)
  145. private byte byte487; //[487]Missile base progression (also does something in BG2F classroom)
  146. private byte byte488; //[488]Alternate Party Flags. Irvine +1/+16, Quistis +2/+32, Rinoa +4/+64, Zell +8/+128.1
  147. private byte byte489; //[489]Random talk flags?
  148. private byte byte490; //[490]Cafeteria cutscene
  149. private byte byte491; //[491]ToUK stuff
  150. private byte byte492; //[492]I think this is a door opener for the missile base if you choose a short time limit.
  151. private byte byte493; //[493]Missile base timer related?
  152. private unsafe fixed byte byte494527[34]; //[494-527]unused in fields
  153. private short short528; //[528]Sub-story progression (it's a progression variable for individual segments of the game)
  154. private byte byte530; //[530]X-ATM related (defeated it in battle?)
  155. private byte byte531; //[531]Functionally unused. Read from at dollet, only manipulated in debug rooms.
  156. private byte byte532; //[532]Controls footstep sounds at dollet (sand to concrete)
  157. private byte byte533; //[533]not investigated
  158. private byte byte534; //[534]not investigated
  159. private byte byte535; //[535]not investigated
  160. private byte byte536; //[536]not investigated
  161. private byte byte537; //[537]not investigated
  162. private byte byte538; //[538]not investigated
  163. private byte byte539; //[539]not investigated
  164. private unsafe fixed byte byte540591[52]; //[540-591]unused in fields
  165. private unsafe fixed byte byte592593[2]; //[592-593]Seems to control angles and character facing.
  166. private byte byte594; //[594]unused in fields
  167. private byte byte595; //[595]not investigated
  168. private byte byte596; //[596]not investigated
  169. private byte byte597; //[597]not investigated
  170. private byte byte598; //[598]not investigated
  171. private byte byte599; //[599]not investigated
  172. private byte byte600; //[600]not investigated
  173. private byte byte601; //[601]not investigated
  174. private byte byte602; //[602]not investigated
  175. private byte byte603; //[603]not investigated
  176. private byte byte604; //[604]not investigated
  177. private byte byte605; //[605]not investigated
  178. private byte byte606; //[606]not investigated
  179. private byte byte607; //[607]not investigated
  180. private byte byte608; //[608]not investigated
  181. private byte byte609; //[609]not investigated
  182. private byte byte610; //[610]not investigated
  183. private byte byte611; //[611]not investigated
  184. private byte byte612; //[612]not investigated
  185. private byte byte613; //[613]not investigated
  186. private byte byte614; //[614]not investigated
  187. private byte byte615; //[615]not investigated
  188. private byte byte616; //[616]not investigated
  189. private byte byte617; //[617]not investigated
  190. private byte byte618; //[618]not investigated
  191. private byte byte619; //[619]not investigated
  192. private byte byte620; //[620]not investigated
  193. private byte byte621; //[621]not investigated
  194. private byte byte622; //[622]not investigated
  195. private byte byte623; //[623]not investigated
  196. private byte byte624; //[624]not investigated
  197. private byte byte625; //[625]Balamb visited flags (+8 Zell's room)
  198. private byte byte626; //[626]not investigated
  199. private byte byte627; //[627]not investigated
  200. private byte byte628; //[628]unused in fields
  201. private byte byte629; //[629]not investigated
  202. private byte byte630; //[630]not investigated
  203. private byte byte631; //[631]not investigated
  204. private byte byte632; //[632]not investigated
  205. private byte byte633; //[633]not investigated
  206. private ushort ushort634; //[634]not investigated
  207. private byte byte636; //[636]not investigated
  208. private byte byte637; //[637]unused in fields
  209. private byte byte638; //[638]not investigated
  210. private byte byte639; //[639]unused in fields
  211. private byte byte640; //[640]not investigated
  212. private byte byte641; //[641]not investigated
  213. private byte byte642; //[642]not investigated
  214. private byte byte643; //[643]not investigated
  215. private byte byte644; //[644]not investigated
  216. private byte byte645; //[645]not investigated
  217. private byte byte646; //[646]not investigated
  218. private byte byte647; //[647]not investigated
  219. private byte byte648; //[648]not investigated
  220. private byte byte649; //[649]not investigated
  221. private unsafe fixed byte byte650655[6]; //[650-655]unused in fields
  222. private ushort ushort656; //[656]not investigated
  223. private byte byte658; //[658]not investigated
  224. private byte byte659; //[659]not investigated
  225. private byte byte660; //[660]not investigated
  226. private byte byte661; //[661]not investigated
  227. private byte byte662; //[662]not investigated
  228. private byte byte663; //[663]not investigated
  229. private byte byte664; //[664]not investigated
  230. private byte byte665; //[665]not investigated
  231. private ushort ushort666; //[666]not investigated
  232. private byte byte668; //[668]not investigated
  233. private unsafe fixed byte byte669671[3]; //[669-671]unused in fields
  234. private ushort ushort672; //[672]not investigated
  235. private byte byte674; //[674]unused in fields
  236. private byte byte675; //[675]not investigated
  237. private byte byte676; //[676]unused in fields
  238. private byte byte677; //[677]not investigated
  239. private byte byte678; //[678]not investigated
  240. private byte byte679; //[679]unused in fields
  241. private byte byte680; //[680]not investigated
  242. private byte byte681; //[681]not investigated
  243. private byte byte682; //[682]not investigated
  244. private byte byte683; //[683]not investigated
  245. private byte byte684; //[684]not investigated
  246. private byte byte685; //[685]not investigated
  247. private byte byte686; //[686]not investigated
  248. private byte byte687; //[687]not investigated
  249. private byte byte688; //[688]not investigated
  250. private byte byte689; //[689]not investigated
  251. private byte byte690; //[690]not investigated
  252. private byte byte691; //[691]not investigated
  253. private unsafe fixed byte byte692719[28]; //[692-719]unused in fields
  254. private byte byte720; //[720]Squall's costume (0=normal, 1=student, 2=SeeD, 3=Bandage on forehead)
  255. private byte byte721; //[721]Zell's Costume (0=normal, 1=student, 2=SeeD)
  256. private byte byte722; //[722]Selphie's costume (0=normal, 1=student, 2=SeeD)
  257. private byte byte723; //[723]Quistis' Costume (0=normal, 1=SeeD)
  258. private ushort ushort724; //[724]Dollet mission time
  259. private ushort ushort726; //[726]not investigated
  260. private byte byte728; //[728]Does lots of things.3
  261. private byte byte729; //[729]not investigated
  262. private byte byte730; //[730]Flags (+1 Joined Garden Festival Committee, +4 Gave Selphie tour of BG, +16 Kadowaki asks for Cid, +32 and +64 Tomb of Unknown Kind hints?, +128 Beat all card people?)
  263. private byte byte731; //[731]unused in fields
  264. private ushort ushort732; //[732]not investigated
  265. private byte byte734; //[734]Split Party Flags (+1 Zell, +2 Irvine, +4 Rinoa, +8 Quistis, +16 Selphie).2
  266. private byte byte735; //[735]not investigated
  267. private unsafe fixed byte byte736751[16]; //[736-751]unused in fields
  268. private byte byte752; //[752]not investigated
  269. private unsafe fixed byte byte7531023[271]; //[753-1023]unused in fields
  270. private byte byteAbove1023; //[Above 1023]Temporary variables used pretty much everywhere.
  271. }
  272. /// <summary>
  273. /// parse data from save game files
  274. /// </summary>
  275. /// <seealso cref="http://wiki.ffrtt.ru/index.php/FF8/GameSaveFormat#The_save_format"/>
  276. /// <seealso cref="https://github.com/myst6re/hyne"/>
  277. /// <seealso cref="https://cdn.discordapp.com/attachments/552838120895283210/570733614656913408/ff8_save.zip"/>
  278. /// <remarks>
  279. /// antiquechrono was helping. he even wrote a whole class using kaitai. Though I donno if we
  280. /// wanna use kaitai.
  281. /// </remarks>
  282. internal static class Saves
  283. {
  284. public class Data
  285. {
  286. public ushort LocationID;//0x0004
  287. public ushort firstcharacterscurrentHP;//0x0006
  288. public ushort firstcharactersmaxHP;//0x0008
  289. public ushort savecount;//0x000A
  290. public uint AmountofGil;//0x000C
  291. /// <summary>
  292. /// Stored playtime in seconds. Made into timespan for easy parsing.
  293. /// </summary>
  294. public TimeSpan timeplayed;//0x0020
  295. public byte firstcharacterslevel;//0x0024
  296. /// <summary>
  297. /// 0xFF = blank; The value should cast to Faces.ID
  298. /// </summary>
  299. public byte[] charactersportraits;//0x0025//0x0026//0x0027
  300. /// <summary>
  301. /// 12 characters 0x00 terminated
  302. /// </summary>
  303. public FF8String Squallsname;//0x0028 //12 characters 0x00 terminated
  304. public FF8String Rinoasname;//0x0034 //12 characters 0x00 terminated
  305. public FF8String Angelosname;//0x0040 //12 characters 0x00 terminated
  306. public FF8String Bokosname;//0x004C //12 characters 0x00 terminated
  307. // 0 = Disc 1
  308. public uint CurrentDisk;//0x0058
  309. public uint Currentsave;//0x005C
  310. public GFData[] GFs; // 0x0060 -> 0x045C //68 bytes per 16 total
  311. public CharacterData[] Characters; // 0x04A0 -> 0x08C8 //152 bytes per 8 total
  312. public byte[] Shops; //0x0960 //400 bytes
  313. public byte[] Configuration; //0x0AF0 //20 bytes
  314. public byte[] Party; //0x0B04 // 4 bytes 0xFF terminated.
  315. public byte[] KnownWeapons; //0x0B08 // 4 bytes
  316. public FF8String Grieversname; //0x0B0C // 12 bytes
  317. public ushort Unknown1; //0x0B18 (always 7966?)
  318. public ushort Unknown2; //0x0B1A
  319. public uint AmountofGil2; //0x0B1C
  320. public uint AmountofGil_Laguna; //0x0B20
  321. public ushort LimitBreakQuistis; //0x0B24
  322. public ushort LimitBreakZell; //0x0B26
  323. public byte LimitBreakIrvine; //0x0B28
  324. public byte LimitBreakSelphie; //0x0B29
  325. public byte LimitBreakAngelocompleted; //0x0B2A
  326. public byte LimitBreakAngeloknown; //0x0B2B
  327. public byte[] LimitBreakAngelopoints; //0x0B2C
  328. public byte[] Itemsbattleorder; //0x0B34
  329. public Item[] Items; //0x0B54 198 items (Item ID and Quantity)
  330. public TimeSpan Gametime; //0x0CE0
  331. public uint Countdown; //0x0CE4
  332. public uint Unknown3; //0x0CE8
  333. public uint Battlevictorycount; //0x0CEC
  334. public ushort Unknown4; //0x0CF0
  335. public ushort Battlebattleescaped; //0x0CF2
  336. public uint Unknown5; //0x0CF4
  337. public uint BattleTonberrykilledcount; //0x0CF8
  338. public bool BattleTonberrySrkilled; //0x0CFC (yeah, this is a boolean)
  339. public uint Unknown6; //0x0D00
  340. public uint BattleR1; //0x0D04 First "Bug" battle (R1 tip)
  341. public uint BattleELEMENTAL; //0x0D08 First "Bomb" battle (Elemental tip)
  342. public uint BattleMENTAL; //0x0D0C  First "T-Rex" battle (Mental tip)
  343. public uint BattleIRVINE; //0x0D10 First "Irvine" battle (Irvine's limit break tip)
  344. public byte[] BattleMAGIC; //0x0D14 Magic drawn once
  345. public byte[] BattleSCAN; //0x0D1C Ennemy scanned once
  346. public byte BattleRAUTO; //0x0D30 Renzokuken auto
  347. public byte BattleRINDICATOR; //0x0D31 Renzokuken indicator
  348. public byte BattleUNK; //0x0D32 dream/Odin/Phoenix/Gilgamesh/Angelo disabled/Angel Wing enabled/???/???
  349. public byte[] Tutorialinfos; //0x0D33
  350. public byte SeeDtestlevel; //0x0D43
  351. public uint Unknown; //0x0D44
  352. public uint Party2; //0x0D48 (last byte always = 255)
  353. public uint Unknown7; //0x0D4C
  354. public ushort Module; //0x0D50 (1= field, 2= worldmap, 3= battle)
  355. public ushort Currentfield; //0x0D52
  356. public ushort Previousfield; //0x0D54
  357. public short[] CoordX; //0x0D56 signed (party1, party2, party3)
  358. public short[] CoordY; //0x0D5C signed (party1, party2, party3)
  359. public ushort[] Triangle_ID; //0x0D62 (party1, party2, party3)
  360. public byte[] Direction; //0x0D68 (party1, party2, party3)
  361. public byte Padding; //0x0D6B
  362. public uint Unknown8; //0x0D6C
  363. public byte[] Fieldvars; //0x0D70 http://wiki.ffrtt.ru/index.php/FF8/Variables
  364. public byte[] Worldmap; //0x1270
  365. public byte[] TripleTriad; //0x12F0
  366. public byte[] ChocoboWorld; //0x1370
  367. public Data()
  368. {
  369. LocationID = 0;
  370. firstcharacterscurrentHP = 0;
  371. firstcharactersmaxHP = 0;
  372. savecount = 0;
  373. AmountofGil = 0;
  374. timeplayed = new TimeSpan();
  375. firstcharacterslevel = 0;
  376. charactersportraits = null;
  377. Squallsname = null;
  378. Rinoasname = null;
  379. Angelosname = null;
  380. Bokosname = null;
  381. CurrentDisk = 0;
  382. Currentsave = 0;
  383. GFs = new GFData[16];
  384. Characters = new CharacterData[8];
  385. Shops = null;
  386. Configuration = null;
  387. Party = null;
  388. KnownWeapons = null;
  389. Grieversname = null;
  390. }
  391. public struct Item { public byte ID; public byte QTY; };
  392. public void Read(BinaryReader br)
  393. {
  394. LocationID = br.ReadUInt16();//0x0004
  395. firstcharacterscurrentHP = br.ReadUInt16();//0x0006
  396. firstcharactersmaxHP = br.ReadUInt16();//0x0008
  397. savecount = br.ReadUInt16();//0x000A
  398. AmountofGil = br.ReadUInt32();//0x000C
  399. timeplayed = new TimeSpan(0, 0, (int)br.ReadUInt32());//0x0020
  400. firstcharacterslevel = br.ReadByte();//0x0024
  401. charactersportraits = br.ReadBytes(3);//0x0025//0x0026//0x0027 0xFF = blank.
  402. Squallsname = br.ReadBytes(12);//0x0028
  403. Rinoasname = br.ReadBytes(12);//0x0034
  404. Angelosname = br.ReadBytes(12);//0x0040
  405. Bokosname = br.ReadBytes(12);//0x004C
  406. CurrentDisk = br.ReadUInt32();//0x0058
  407. Currentsave = br.ReadUInt32();//0x005C
  408. for (int i = 0; i < GFs.Length; i++)
  409. {
  410. GFs[i].Read(br);
  411. }
  412. for (int i = 0; i < 8; i++)
  413. Characters[i].Read(br); // 0x04A0 -> 0x08C8 //152 bytes per 8 total
  414. Shops = br.ReadBytes(400); //0x0960 //400 bytes
  415. Configuration = br.ReadBytes(20); //0x0AF0 //20 bytes
  416. Party = br.ReadBytes(4); //0x0B04 // 4 bytes 0xFF terminated.
  417. KnownWeapons = br.ReadBytes(4); //0x0B08 // 4 bytes
  418. Grieversname = br.ReadBytes(12); //0x0B0C // 12 bytes
  419. Unknown = br.ReadUInt16();//0x0B18 (always 7966?)
  420. Unknown = br.ReadUInt16();//0x0B1A
  421. AmountofGil2 = br.ReadUInt32();//0x0B1C //dupilicate
  422. AmountofGil_Laguna = br.ReadUInt32();//0x0B20
  423. LimitBreakQuistis = br.ReadUInt16();//0x0B24
  424. LimitBreakZell = br.ReadUInt16();//0x0B26
  425. LimitBreakIrvine = br.ReadByte();//0x0B28
  426. LimitBreakSelphie = br.ReadByte();//0x0B29
  427. LimitBreakAngelocompleted = br.ReadByte();//0x0B2A
  428. LimitBreakAngeloknown = br.ReadByte();//0x0B2B
  429. LimitBreakAngelopoints = br.ReadBytes(8);//0x0B2C
  430. Itemsbattleorder = br.ReadBytes(32);//0x0B34
  431. Items = new Item[198];
  432. for (int i = 0; i < 198; i++)
  433. Items[0] = new Item { ID = br.ReadByte(), QTY = br.ReadByte() }; //0x0B54 198 items (Item ID and Quantity)
  434. Gametime = new TimeSpan(0, 0, (int)br.ReadUInt32());//0x0CE0
  435. Countdown = br.ReadUInt32();//0x0CE4
  436. Unknown = br.ReadUInt32();//0x0CE8
  437. Battlevictorycount = br.ReadUInt32();//0x0CEC
  438. Unknown = br.ReadUInt16();//0x0CF0
  439. Battlebattleescaped = br.ReadUInt16();//0x0CF2
  440. Unknown = br.ReadUInt32();//0x0CF4
  441. BattleTonberrykilledcount = br.ReadUInt32();//0x0CF8
  442. BattleTonberrySrkilled = br.ReadUInt32()>0;//0x0CFC (yeah, this is a boolean)
  443. Unknown = br.ReadUInt32();//0x0D00
  444. BattleR1 = br.ReadUInt32();//0x0D04 First "Bug" battle (R1 tip)
  445. BattleELEMENTAL = br.ReadUInt32();//0x0D08 First "Bomb" battle (Elemental tip)
  446. BattleMENTAL = br.ReadUInt32();//0x0D0C  First "T-Rex" battle (Mental tip)
  447. BattleIRVINE = br.ReadUInt32();//0x0D10 First "Irvine" battle (Irvine's limit break tip)
  448. BattleMAGIC = br.ReadBytes(8);//0x0D14 Magic drawn once
  449. BattleSCAN = br.ReadBytes(20);//0x0D1C Ennemy scanned once
  450. BattleRAUTO = br.ReadByte();//0x0D30 Renzokuken auto
  451. BattleRINDICATOR = br.ReadByte();//0x0D31 Renzokuken indicator
  452. BattleUNK = br.ReadByte();//0x0D32 dream/Odin/Phoenix/Gilgamesh/Angelo disabled/Angel Wing enabled/???/???
  453. Tutorialinfos = br.ReadBytes(16);//0x0D33
  454. SeeDtestlevel = br.ReadByte();//0x0D43
  455. Unknown = br.ReadUInt32();//0x0D44
  456. Party2 = br.ReadUInt32();//0x0D48 (last byte always = 255) //dupicate
  457. Unknown = br.ReadUInt32();//0x0D4C
  458. Module = br.ReadUInt16();//0x0D50 (1= field, 2= worldmap, 3= battle)
  459. Currentfield = br.ReadUInt16();//0x0D52
  460. Previousfield = br.ReadUInt16();//0x0D54
  461. CoordX = new short[3];
  462. for (int i =0; i<3;i++)
  463. CoordX[i] = br.ReadInt16();//0x0D56 signed (party1, party2, party3)
  464. CoordY = new short [3];
  465. for (int i = 0; i < 3; i++)
  466. CoordY[i] = br.ReadInt16();//0x0D5C signed (party1, party2, party3)
  467. Triangle_ID = new ushort[3];
  468. for (int i = 0; i < 3; i++)
  469. Triangle_ID[i] = br.ReadUInt16();//0x0D62 (party1, party2, party3)
  470. Direction = br.ReadBytes(3 * 1);//0x0D68 (party1, party2, party3)
  471. Padding = br.ReadByte();//0x0D6B
  472. Unknown = br.ReadUInt32();//0x0D6C
  473. //Fieldvars = br.ReadBytes(256 + 1024);//0x0D70 http://wiki.ffrtt.ru/index.php/FF8/Variables
  474. //Worldmap = br.ReadBytes(128);//0x1270
  475. //TripleTriad = br.ReadBytes(128);//0x12F0
  476. //ChocoboWorld = br.ReadBytes(64);//0x1370
  477. }
  478. }
  479. /// <summary>
  480. /// Data for each Character
  481. /// </summary>
  482. /// <see cref="http://wiki.ffrtt.ru/index.php/FF8/GameSaveFormat#Characters"/>
  483. public struct CharacterData
  484. {
  485. public ushort MaxHPs; //0x00
  486. public uint Experience; //0x02
  487. public byte ModelID; //0x04
  488. public byte WeaponID; //0x08
  489. public byte STR; //0x09
  490. public byte VIT; //0x0A
  491. public byte MAG; //0x0B
  492. public byte SPR; //0x0C
  493. public byte SPD; //0x0D
  494. public byte LCK; //0x0E
  495. public ushort[] Magics; //0x0F
  496. public byte[] Commands; //0x10
  497. public byte Paddingorunusedcommand; //0x50
  498. public uint Abilities; //0x53
  499. public ushort JunctionnedGFs; //0x54
  500. public byte Unknown1; //0x58
  501. public byte Alternativemodel; //0x5A (Normal, SeeD, Soldier...)
  502. public byte JunctionHP; //0x5B
  503. public byte JunctionSTR; //0x5C
  504. public byte JunctionVIT; //0x5D
  505. public byte JunctionMAG; //0x5E
  506. public byte JunctionSPR; //0x5F
  507. public byte JunctionSPD; //0x60
  508. public byte JunctionEVA; //0x61
  509. public byte JunctionHIT; //0x62
  510. public byte JunctionLCK; //0x63
  511. public byte Junctionelementalattack; //0x64
  512. public byte Junctionmentalattack; //0x65
  513. public uint Junctionelementaldefense; //0x66
  514. public uint Junctionmentaldefense; //0x67
  515. public byte Unknown2; //0x6B (padding?)
  516. public ushort[] CompatibilitywithGFs; //0x6F
  517. public ushort Numberofkills; //0x70
  518. public ushort NumberofKOs; //0x90
  519. public byte Exists; //0x92
  520. public byte Unknown3; //0x94
  521. public byte MentalStatus; //0x95
  522. public byte Unknown4; //0x96
  523. public void Read(BinaryReader br)
  524. {
  525. MaxHPs = br.ReadUInt16();//0x02
  526. Experience = br.ReadUInt32();//0x04
  527. ModelID = br.ReadByte();//0x08
  528. WeaponID = br.ReadByte();//0x09
  529. STR = br.ReadByte();//0x0A
  530. VIT = br.ReadByte();//0x0B
  531. MAG = br.ReadByte();//0x0C
  532. SPR = br.ReadByte();//0x0D
  533. SPD = br.ReadByte();//0x0E
  534. LCK = br.ReadByte();//0x0F
  535. Magics = new ushort[32];
  536. for (int i = 0; i < 32; i++)
  537. Magics[i] = br.ReadUInt16();//0x10
  538. Commands = br.ReadBytes(3);//0x50
  539. Paddingorunusedcommand = br.ReadByte();//0x53
  540. Abilities = br.ReadUInt32();//0x54
  541. JunctionnedGFs = br.ReadUInt16();//0x58
  542. Unknown1 = br.ReadByte();//0x5A
  543. Alternativemodel = br.ReadByte();//0x5B (Normal, SeeD, Soldier...)
  544. JunctionHP = br.ReadByte();//0x5C
  545. JunctionSTR = br.ReadByte();//0x5D
  546. JunctionVIT = br.ReadByte();//0x5E
  547. JunctionMAG = br.ReadByte();//0x5F
  548. JunctionSPR = br.ReadByte();//0x60
  549. JunctionSPD = br.ReadByte();//0x61
  550. JunctionEVA = br.ReadByte();//0x62
  551. JunctionHIT = br.ReadByte();//0x63
  552. JunctionLCK = br.ReadByte();//0x64
  553. Junctionelementalattack = br.ReadByte();//0x65
  554. Junctionmentalattack = br.ReadByte();//0x66
  555. Junctionelementaldefense = br.ReadUInt32();//0x67
  556. Junctionmentaldefense = br.ReadUInt32();//0x6B
  557. Unknown2 = br.ReadByte();//0x6F (padding?)
  558. CompatibilitywithGFs = new ushort[16];
  559. for (int i = 0; i < 16; i++)
  560. CompatibilitywithGFs[i] = br.ReadUInt16();//0x70
  561. Numberofkills = br.ReadUInt16();//0x90
  562. NumberofKOs = br.ReadUInt16();//0x92
  563. Exists = br.ReadByte();//0x94
  564. Unknown3 = br.ReadByte();//0x95
  565. MentalStatus = br.ReadByte();//0x96
  566. Unknown4 = br.ReadByte();//0x97
  567. }
  568. }
  569. /// <summary>
  570. /// Data for each GF
  571. /// </summary>
  572. /// <see cref="http://wiki.ffrtt.ru/index.php/FF8/GameSaveFormat#Guardian_Forces"/>
  573. public struct GFData
  574. {
  575. public FF8String Name; //Offset (0x00 terminated)
  576. public uint Experience; //0x00
  577. public byte Unknown; //0x0C
  578. public byte Exists; //0x10
  579. public ushort HP; //0x11
  580. public byte[] Complete; //0x12 abilities (1 bit = 1 ability completed, 9 bits unused)
  581. public byte[] APs; //0x14 (1 byte = 1 ability of the GF, 2 bytes unused)
  582. public ushort NumberKills; //0x24 of kills
  583. public ushort NumberKOs; //0x3C of KOs
  584. public byte Learning; //0x3E ability
  585. public byte[] Forgotten; //0x41 abilities (1 bit = 1 ability of the GF forgotten, 2 bits unused)
  586. public void Read(BinaryReader br)
  587. {
  588. Name = br.ReadBytes(12);//0x00 (0x00 terminated)
  589. Experience = br.ReadUInt32();//0x0C
  590. Unknown = br.ReadByte();//0x10
  591. Exists = br.ReadByte();//0x11
  592. HP = br.ReadUInt16();//0x12
  593. Complete = br.ReadBytes(16);//0x14 abilities (1 bit = 1 ability completed, 9 bits unused)
  594. APs = br.ReadBytes(24);//0x24 (1 byte = 1 ability of the GF, 2 bytes unused)
  595. NumberKills = br.ReadUInt16();//0x3C of kills
  596. NumberKOs = br.ReadUInt16();//0x3E of KOs
  597. Learning = br.ReadByte();//0x41 ability
  598. Forgotten = br.ReadBytes(3);//0x42 abilities (1 bit = 1 ability of the GF forgotten, 2 bits unused)
  599. }
  600. }
  601. /// <summary>
  602. /// Locations used by save files.
  603. /// </summary>
  604. /// <seealso cref="https://github.com/myst6re/hyne/blob/master/Data.cpp"/>
  605. public static string[] Locations = new string[] {
  606. ("???")
  607. ,("Plaines d'Arkland - Balamb")
  608. ,("Monts Gaulg - Balamb")
  609. ,("Baie de Rinaul - Balamb")
  610. ,("Cap Raha - Balamb")
  611. ,("Forêt de Rosfall - Timber")
  612. ,("Mandy Beach - Timber")
  613. ,("Lac Obel - Timber")
  614. ,("Vallée de Lanker - Timber")
  615. ,("Ile Nantakhet - Timber")
  616. ,("Yaulny Canyon - Timber")
  617. ,("Val Hasberry - Dollet")
  618. ,("Cap Holy Glory - Dollet")
  619. ,("Longhorn Island - Dollet")
  620. ,("Péninsule Malgo - Dollet")
  621. ,("Plateau Monterosa - Galbadia")
  622. ,("Lallapalooza Canyon - Galbadia")
  623. ,("Shenand Hill - Timber")
  624. ,("Péninsule Gotland - Galbadia")
  625. ,("Ile de l'Enfer - Galbadia")
  626. ,("Plaine Galbadienne")
  627. ,("Wilburn Hill - Galbadia")
  628. ,("Archipel Rem - Galbadia")
  629. ,("Dingo Désert - Galbadia")
  630. ,("Cap Winhill")
  631. ,("Archipel Humphrey - Winhill")
  632. ,("Ile Winter - Trabia")
  633. ,("Val de Solvard - Trabia")
  634. ,("Crête d'Eldbeak - Trabia")
  635. ,("")
  636. ,("Plaine d'Hawkind - Trabia")
  637. ,("Atoll Albatross - Trabia")
  638. ,("Vallon de Bika - Trabia")
  639. ,("Péninsule Thor - Trabia")
  640. ,("")
  641. ,("Crête d'Heath - Trabia")
  642. ,("Trabia Crater - Trabia")
  643. ,("Mont Vienne - Trabia")
  644. ,("Plaine de Mordor - Esthar")
  645. ,("Mont Nortes - Esthar")
  646. ,("Atoll Fulcura - Esthar")
  647. ,("Forêt Grandidi - Esthar")
  648. ,("Iles Millefeuilles - Esthar")
  649. ,("Grandes plaines d'Esthar")
  650. ,("Esthar City")
  651. ,("Salt Lake - Esthar")
  652. ,("Côte Ouest - Esthar")
  653. ,("Mont Sollet - Esthar")
  654. ,("Vallée d'Abadan - Esthar")
  655. ,("Ile Minde - Esthar")
  656. ,("Désert Kashkabald - Esthar")
  657. ,("Ile Paradisiaque - Esthar")
  658. ,("Pic de Talle - Esthar")
  659. ,("Atoll Shalmal - Esthar")
  660. ,("Vallée de Lolestern - Centra")
  661. ,("Aiguille d'Almage - Centra")
  662. ,("Vallon Lenown - Centra")
  663. ,("Cap de l'espoir - Centra")
  664. ,("Mont Yorn - Centra")
  665. ,("Ile Pampa - Esthar")
  666. ,("Val Serengetti - Centra")
  667. ,("Péninsule Nectalle - Centra")
  668. ,("Centra Crater - Centra")
  669. ,("Ile Poccarahi - Centra")
  670. ,("Bibliothèque - BGU")
  671. ,("Entrée - BGU")
  672. ,("Salle de cours - BGU")
  673. ,("Cafétéria - BGU")
  674. ,("Niveau MD - BGU")
  675. ,("Hall 1er étage - BGU")
  676. ,("Hall - BGU")
  677. ,("Infirmerie - BGU")
  678. ,("Dortoirs doubles - BGU")
  679. ,("Dortoirs simples - BGU")
  680. ,("Bureau proviseur - BGU")
  681. ,("Parking - BGU")
  682. ,("Salle de bal - BGU")
  683. ,("Campus - BGU")
  684. ,("Serre de combat - BGU")
  685. ,("Zone secrète - BGU")
  686. ,("Corridor - BGU")
  687. ,("Temple - BGU")
  688. ,("Pont - BGU")
  689. ,("Villa Dincht - Balamb")
  690. ,("Hôtel - Balamb")
  691. ,("Place centrale - Balamb")
  692. ,("Place de la gare - Balamb")
  693. ,("Port - Balamb")
  694. ,("Résidence - Balamb")
  695. ,("Train")
  696. ,("Voiture")
  697. ,("Vaisseau")
  698. ,("Mine de souffre")
  699. ,("Place du village - Dollet")
  700. ,("Zuma Beach")
  701. ,("Port - Dollet")
  702. ,("Pub - Dollet")
  703. ,("Hôtel - Dollet")
  704. ,("Résidence - Dollet")
  705. ,("Tour satellite - Dollet")
  706. ,("Refuge montagneux - Dollet")
  707. ,("Centre ville - Timber")
  708. ,("Chaîne de TV - Timber")
  709. ,("Base des Hiboux - Timber")
  710. ,("Pub - Timber")
  711. ,("Hôtel - Timber")
  712. ,("Train - Timber")
  713. ,("Résidence - Timber")
  714. ,("Ecran géant - Timber")
  715. ,("Centre de presse - Timber")
  716. ,("Forêt de Timber")
  717. ,("Entrée - Fac de Galbadia")
  718. ,("Station Fac de Galbadia")
  719. ,("Hall - Fac de Galbadia")
  720. ,("Corridor - Fac de Galbadia")
  721. ,("Salle d'attente - Fac Galbadia")
  722. ,("Salle de cours - Fac Galbadia")
  723. ,("Salle de réunion - Fac Galbadia")
  724. ,("Dortoirs - Fac de Galbadia")
  725. ,("Ascenseur - Fac de Galbadia")
  726. ,("Salle recteur - Fac Galbadia")
  727. ,("Auditorium - Fac de Galbadia")
  728. ,("Stade - Fac de Galbadia")
  729. ,("Stand - Fac de Galbadia")
  730. ,("2nde entrée - Fac Galbadia")
  731. ,("Gymnase - Fac de Galbadia")
  732. ,("Palais président - Deling City")
  733. ,("Manoir Caraway - Deling City")
  734. ,("Gare - Deling City")
  735. ,("Place centrale - Deling City")
  736. ,("Hôtel - Deling City")
  737. ,("Bar - Deling City")
  738. ,("Sortie - Deling City")
  739. ,("Parade - Deling City")
  740. ,("Egout - Deling City")
  741. ,("Prison du désert - Galbadia")
  742. ,("Désert")
  743. ,("Base des missiles")
  744. ,("Village de Winhill")
  745. ,("Pub - Winhill")
  746. ,("Maison vide - Winhill")
  747. ,("Manoir - Winhill")
  748. ,("Résidence - Winhill")
  749. ,("Hôtel - Winhill")
  750. ,("Voiture - Winhill")
  751. ,("Tombe du roi inconnu")
  752. ,("Horizon")
  753. ,("Habitations - Horizon")
  754. ,("Ecrans solaires - Horizon")
  755. ,("Villa du maire - Horizon")
  756. ,("Usine - Horizon")
  757. ,("Salle des fêtes - Horizon")
  758. ,("Hôtel - Horizon")
  759. ,("Résidence - Horizon")
  760. ,("Gare - Horizon")
  761. ,("Aqueduc d'Horizon")
  762. ,("Station balnéaire")
  763. ,("Salt Lake")
  764. ,("Bâtiment mystérieux")
  765. ,("Esthar City")
  766. ,("Laboratoire Geyser - Esthar")
  767. ,("Aérodrome - Esthar")
  768. ,("Lunatic Pandora approche")
  769. ,("Résidence président - Esthar")
  770. ,("Hall - Résidence président")
  771. ,("Couloir - Résidence président")
  772. ,("Bureau - Résidence président")
  773. ,("Accueil - Labo Geyser")
  774. ,("Laboratoire Geyser")
  775. ,("Deleted")
  776. ,("Lunar Gate")
  777. ,("Parvis - Lunar Gate")
  778. ,("Glacière - Lunar gate")
  779. ,("Mausolée - Esthar")
  780. ,("Entrée - Mausolée")
  781. ,("Pod de confinement - Mausolée")
  782. ,("Salle de contrôle - Mausolée")
  783. ,("Tears Point")
  784. ,("Labo Lunatic Pandora")
  785. ,("Zone d'atterrissage de secours")
  786. ,("Zone d'atterrissage officielle")
  787. ,("Lunatic Pandora")
  788. ,("Site des fouilles - Centra")
  789. ,("Orphelinat")
  790. ,("Salle de jeux - Orphelinat")
  791. ,("Dortoir - Orphelinat")
  792. ,("Jardin - Orphelinat")
  793. ,("Front de mer - Orphelinat")
  794. ,("Champ - Orphelinat")
  795. ,("Ruines de Centra")
  796. ,("Entrée - Fac de Trabia")
  797. ,("Cimetière - Fac de Trabia")
  798. ,("Garage - Fac de Trabia")
  799. ,("Campus - Fac Trabia")
  800. ,("Amphithéatre - Fac de Trabia")
  801. ,("Stade - Fac de Trabia")
  802. ,("Dôme mystérieux")
  803. ,("Ville du désert - Shumi Village")
  804. ,("Ascenseur - Shumi Village")
  805. ,("Shumi Village")
  806. ,("Habitation - Shumi Village")
  807. ,("Résidence - Shumi Village")
  808. ,("Habitat - Shumi Village")
  809. ,("Hôtel - Shumi Village")
  810. ,("Trabia canyon")
  811. ,("Vaisseau des Seeds blancs")
  812. ,("Navire des Seeds Blancs")
  813. ,("Cabine - Navire Seeds blancs")
  814. ,("Cockpit - Hydre")
  815. ,("Siège passager - Hydre")
  816. ,("Couloir - Hydre")
  817. ,("Hangar - Hydre")
  818. ,("Accès - Hydre")
  819. ,("Air Room - Hydre")
  820. ,("Salle de pression - Hydre")
  821. ,("Centre de recherches Deep Sea")
  822. ,("Laboratoire - Deep Sea")
  823. ,("Salle de travail - Deep Sea")
  824. ,("Fouilles - Deep Sea")
  825. ,("Salle de contrôle - Base lunaire")
  826. ,("Centre médical - Base lunaire")
  827. ,("Pod - Base lunaire")
  828. ,("Dock - Base lunaire")
  829. ,("Passage - Base lunaire")
  830. ,("Vestiaire - Base lunaire")
  831. ,("Habitats - Base lunaire")
  832. ,("Hyper Espace")
  833. ,("Forêt Chocobo")
  834. ,("Jungle")
  835. ,("Citadelle d'Ultimecia - Vestibule")
  836. ,("Citadelle d'Ultimecia - Hall")
  837. ,("Citadelle d'Ultimecia - Terrasse")
  838. ,("Citadelle d'Ultimecia - Cave")
  839. ,("Citadelle d'Ultimecia - Couloir")
  840. ,("Elévateur - Citadelle")
  841. ,("Escalier - Citadelle d'Ultimecia")
  842. ,("Salle du trésor - Citadelle")
  843. ,("Salle de rangement - Citadelle")
  844. ,("Citadelle d'Ultimecia - Galerie")
  845. ,("Citadelle d'Ultimecia - Ecluse")
  846. ,("Citadelle - Armurerie")
  847. ,("Citadelle d'Ultimecia - Prison")
  848. ,("Citadelle d'Ultimecia - Fossé")
  849. ,("Citadelle d'Ultimecia - Jardin")
  850. ,("Citadelle d'Ultimecia - Chapelle")
  851. ,("Clocher - Citadelle d'Ultimecia")
  852. ,("Chambre d'Ultimecia - Citadelle")
  853. ,("???")
  854. ,("Citadelle d'Ultimecia")
  855. ,("Salle d'initiation")
  856. ,("Reine des cartes")
  857. ,("???")
  858. ,("???")
  859. ,("???")
  860. ,("???")
  861. ,("???")
  862. };
  863. //C:\Users\pcvii\OneDrive\Documents\Square Enix\FINAL FANTASY VIII Steam\user_1727519
  864. // might crash linux. just trying to get something working.
  865. public static string SteamFolder { get; private set; }
  866. public static string CD2000Folder { get; private set; }
  867. public static Data[,] FileList { get; private set; }
  868. public static void Init()
  869. {
  870. FileList = new Data[2, 30];
  871. CD2000Folder = Path.Combine(Memory.FF8DIR, "Save");
  872. SteamFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "Square Enix", "FINAL FANTASY VIII Steam");
  873. if (Directory.Exists(SteamFolder))
  874. {
  875. string[] dirs = Directory.GetDirectories(SteamFolder);
  876. if (dirs.Length > 0)
  877. {
  878. SteamFolder = Directory.GetDirectories(SteamFolder)[0];
  879. foreach (string file in Directory.EnumerateFiles(SteamFolder))
  880. {
  881. Match n = Regex.Match(file, @"slot(\d+)_save(\d+).ff8");
  882. if (n.Success && n.Groups.Count > 0)
  883. {
  884. FileList[int.Parse(n.Groups[1].Value) - 1, int.Parse(n.Groups[2].Value) - 1] = read(file);
  885. }
  886. }
  887. }
  888. }
  889. else if (Directory.Exists(CD2000Folder))
  890. {
  891. string[] files = Directory.GetFiles(CD2000Folder, "*", SearchOption.AllDirectories);
  892. if (files.Length > 0)
  893. {
  894. foreach (string file in files)
  895. {
  896. Match n = Regex.Match(file, @"Slot(\d+)[\\/]save(\d+)");
  897. if (n.Success && n.Groups.Count > 0)
  898. {
  899. FileList[int.Parse(n.Groups[1].Value) - 1, int.Parse(n.Groups[2].Value) - 1] = read(file);
  900. }
  901. }
  902. }
  903. }
  904. }
  905. private static Data read(string file)
  906. {
  907. byte[] decmp;
  908. using (FileStream fs = File.OpenRead(file))
  909. using (BinaryReader br = new BinaryReader(fs))
  910. {
  911. uint size = br.ReadUInt32();
  912. //uint fsLen = BitConverter.ToUInt32(FI, loc * 12);
  913. //uint fSpos = BitConverter.ToUInt32(FI, (loc * 12) + 4);
  914. //bool compe = BitConverter.ToUInt32(FI, (loc * 12) + 8) != 0;
  915. //fs.Seek(0, SeekOrigin.Begin);
  916. byte[] tmp = br.ReadBytes((int)fs.Length - 4);
  917. decmp = LZSS.DecompressAllNew(tmp);
  918. }
  919. //using (FileStream fs = File.Create(Path.Combine(@"d:\", Path.GetFileName(file))))
  920. //using (BinaryWriter bw = new BinaryWriter(fs))
  921. //{
  922. // bw.Write(decmp);
  923. //}
  924. using (MemoryStream ms = new MemoryStream(decmp))
  925. using (BinaryReader br = new BinaryReader(ms))
  926. {
  927. ms.Seek(0x184, SeekOrigin.Begin);
  928. Data d = new Data();
  929. d.Read(br);
  930. return d;
  931. }
  932. }
  933. }
  934. }