Jump to content

Mutank

Members
  • Posts

    28
  • Joined

  • Last visited

Posts posted by Mutank

  1. 2 hours ago, Plastic Memories said:

    1/ You should use Regex Filter function of Textractor to filter out those symbol like arrows ,[...] ,random numbers
    https://github.com/Artikash/Textractor/issues/355

    2/ If Textractor can't hook and display text from a game properly , you should contact with dev of Textractor on github to inform him about the game ,the engine and update Textractor

    3/If you can provide some more screenshots , visual novel name or something it would be great .Because people can't understand which engine or which game you want to translates ( Love Fetish series is very vague, because each game even from the same dev team can uses different modded engine - example like the game I'm translating from Softhouse Chara  )

    4/ If everything has failed , you can use Visual Novel OCR tool from @mingShiba .Good luck with your translation o/

    As for textractor, I'm really hoping that I do manage to find a way to find the correct thread, as the regex filter function is my best shot at tackling the symbol issue.

    I did post an issue on the textractor page, still waiting for an answer on that one. That being said he seems to be spending most of his time on other projects these days,

    so I'm not sure as to how much he'll be able to help.

     

    the exact games are Love Fetish: vol. 1~3; I'm having the same issue in all three games( haven't tried the later ones yet)

    I'll  take a look at the OCR tool, thankfully the font and dialogue box isn't to bad for OCR reading. Thanks for the suggestions!

  2. So I've been trying to run a few EROGOS games (namely the Love Fetish series)

    And thought that I'd use textractor or ITH to hook and extract the Japanese text from the game.

     

    Textractor is unable to get a hold on the particular thread with the actual Japanese text, and while ITH

    manages to hook the thread just fine, the said thread also included an infuriating blinking arrow symbol that 

    appears every half-second at the bottom of the dialogue box. Without any way to prevent this symbol from

    being hooked as part of the text, It constantly pushes the actual dialogue upwards, making the translated text impossible to read.

     

    I'm not tech-savy with coding or program debugging in the slightest, so my attempts at somehow resolving this issue

    have proven useless. I'm actually considering doing a full on translation of the in-game text files themselves, but I know

    that it's a feat easier said than done. If anyone has suggestions to something that could fix this issue, I'd be overjoyed.

     

     

  3. It's a very old game from haoh, and like alot of older games is full of choices and route paths that really don't make sense.

    I gave it a few goes but only managed to reach 1 ending, and even now I'm not really sure how I got there. I see a low possibility of it happening but still,

    if anyone can manage to find or make a walkthrough for this game, I would greatly appreciate it

  4. 25 minutes ago, marcus-beta said:

    Not sure because I don't touch in this engine for a good time, but as Far I remember this game have a external encrpytion key that are placed in a certain directory of the game.
    Maybe your problem is how you moved the extracted directory and the arc_conv failed to find that key?
    With that said, it was my guess, it is unlikely that I would get it right without seeing what is going on but it is worth the try.

    Also, put the directory path inside ""

    A few tries with the directory did the trick, the new arc files works!

    Sadly I can't get the changes I want to implement (restoring the cg mode the devs broke on release), might have to try fishing around for games the original game files for this one.

    Anyhow, thanks a lot for your help!!

  5. On 5/20/2020 at 6:28 AM, HMfan said:

    If they're qlie engine .pack files, arc_conv worked for me. Download https://github.com/amayra/arc_conv, build (build.bat), and from command prompt do

    
    arc_conv.exe --pack qlie <path to data folder> <output filename>

     

     

     

    For some inexplicable reason I seemed to have missed your post, I'm trying your method right now but for some reason I'm failing to produce a archive.

    The command i'm using is (copypasted from the prompt)

    F:\New Game\MagicalPrince\hacks\arc>arc_conv.exe --pack qlie F:\New Game\MagicalPrince\hacks\arc\data0 data0

    (the folder containing arc_conv is 'arc', and the files to be packed are in a folder named 'data0' placed within 'arc'.) of course the goal is to create data0.pack, but no so far running the codes don't seem to create anything. Am I doing something wrong?

  6. 1 hour ago, uyjulian said:

    You may want to also change "defaultShadowColor" and "defaultEdgeColor" in "Config.tjs".

     

    Also, check the "color" argument of tag "font" in the KAG script.

    Okay never mind my last post, I just reinstalled the game from scratch to completely remove any possibility of lingering values.

    Without running the game, I modified the Config.tjs parameters from earlier to 0xffffff and recompressed > ran the game.

    The text is still in black, which just leaves me confused. I think I may be missing something here, but I can't imagine what.

  7. 30 minutes ago, uyjulian said:

    You may want to also change "defaultShadowColor" and "defaultEdgeColor" in "Config.tjs".

     

    Also, check the "color" argument of tag "font" in the KAG script.

    the defaultShadowcolor/Edgecolors were changed early on, but again doesn't seem to register when I repack the archives. 

    At this point I'm suspecting that the game is running with the previous settings,

    I found this written near the defaultChColor scripts: 

    // この設定はシステム変数に記録されて、次回起動時に引き継がれるので、
    // userFace の設定を変更し、適用したい場合はシステム変数ファイル
    // ?????sc.* の "chdefaultFace" => の行を削除してください。

    basically it mentions needing to delete a line regarding chdefaultFace to change fonts,

    but the location of the said line is unreadable.

  8. 19 minutes ago, uyjulian said:

    You need to restart the game from the beginning, as the current text color is saved in the savefile.

     

    "drawText" is a member of "Layer" class. "Layer" class may be extended by other classes.

    Tried it again in this order: edited the Config.tjs scripts, recompressed the scripts into a xp3 archive. cleared the savedata folder in the base game,

    inserted the new data.xp3 into the game folder and ran the game. As of now the text seems to remain unchanged. 

    I'm changing all 0x000000 parameters to 0xffffff just to be safe, and from what I can tell it's applying to the text in system messages but not

    the actual dialogue.

  9. 26 minutes ago, uyjulian said:

    Look for "defaultChColor" in "Config.tjs"

     

    If you can't find that, backtrace the 4th argument of Layer.drawText

    I can find defaultChColor, defaultShadowColor and defaultEdgeColor set to 0x000000 in Config.tjs. I changed all three to 0xffffff just in case, but the message display doesn't seem to change

    once I put the modified scripts into the game. As for Layer.drawText, I can't seem to find it anywhere.

  10. To specify, I'm working with a kirikiri game that has it's codes stored in tjs files. I found that the text overlay is a bit unfit for reading, so I decided to modify the texture

    and change the color of the normal dialogue text accordingly. Only problem is, I can't seem to identify the codes that determine the text color.

    In the game all normal dialogue is printed in black, while the dialogue during 'full screen text box' parts are in white; my goal would be to make

    the normal dialogue color be printed in white as well.

     

    I'm assuming the font files themselves can't be modified to a specific color (tft files btw), so my current method is to browse through

    the script looking for '0x', as 0xffffff or 0x000000 seems like a reasonable bet, but by the looks of it this doesn't seem to be the answer either.

     

    Would greatly appreciate any pointers, the translation work is almost over but this is proving far more challenging than I would have thought.

     

     

  11. Hello, I'm trying to play a game called 'Magical Prince', a game that was buggy on release and criticized for it. Apparently the folks in Japan found ways to make the game more playable, and one of them was to edit the game data files directly. However, upon opening the game files I found that the files in question are stored in .pack archives, and while I can decompress them without issue I can't seem to find a way to repack them into working archives. Does anyone know any ways for repacking, or perhaps editing through .pack archives? 

  12. 20 hours ago, adamstan said:

    I just checked - PSP version is voiced too, ISO can be downloaded from various ROM hosting sites (and physical version can be bought cheaply on ebay), and it runs fine in PPSSPP. It seems to even be hookable using CheatEngine with HookAnyText plugin, but will require some tweaking.

    Also - PSP version uses "traditional" ADV format instead of NVL.

    BTW thanks for mentioning this VN - I didn't know it, but it seems interesting, and art looks very nice.

    As for +18 versions - all PC versions are unvoiced, and AFAIK DVDPG version of any VN is absolute nightmare to play.

    Apparently it's one of the 'classics' of VNs, and was fairly popular in its prime. I got my hands on the ISO for the PSP version and am trying to see if I can get it hooked to a decent

    text extractor, or even better, crack open the archives. Pity the DVDPG version is more or less extinct, they even made animated cutscenes for that thing and never added them 

    to PC renewal editions.

  13. For those unfamiliar, I'm referring to https://vndb.org/v913#main

    its a very old game, dating back from 2002 so I doubt a lot of people have played it.

    Now I'm trying to start up, and I realized that there are no voices for any of the characters.

    The original game had no voices, but vndb lists VAs, so I'm assuming that one of the later versions had voices added to them.

    However, the only info I could find on the matter is that there is a DVDPG version from 2008 with voices, and no other mentions on the subject.

     

    If anyone happens to have played a voiced pc copy of the game , please let me know.

    I'm really looking forward to this game, but lack of voice acting is kind of a major killer for me.

  14. 39 minutes ago, uyjulian said:

    Try using wildcards

     

    .¥noa32c.exe /p /d /raw *.eri out.noa

    It... it works! Without that extra directory, the file finally works with the game!

    I can't thank you enough for all the help you've given me.. These obscure archive extensions have been giving me so many headaches, and I'm a complete novice at this stuff; there's no doubt that I'd have given up completely on this whole project if it hadn't been for your assistance throughout this thread.

    Now at long last, I can get a move on with my localization. If I ever get to finish my project through all the other stuff going on, I'll definitely remember to include a special thanks to you ;)

  15. 5 hours ago, uyjulian said:

    Try putting the ERI image files on the root level and specifying them on the command line (instead of "E:¥yosuga¥edit", try placing image files in the same directory as noa32c.exe and specifying "image1.eri" "image2.eri")

    Tip: you can copy and paste using RIGHT CLICK (CTRL-C and CTRL-V do not work)

    List file method may also work.

    The contents of the archive amounts to 449 eri files,  so I'm trying the 'list file' method instead.

    What keeps happening though is that the archiver compresses the list text file itself, instead of reading it. 

    the commands I've attempted is .\noa32c.exe /p /d /raw /l "E:\yosuga\print.txt" "E:\yosuga\data1.noa"

    and .\noa32c.exe /p /d /raw "/l E:\yosuga\print.txt" "E:\yosuga\data1.noa".

    currently the eri files are in the same directory as the noa32c.exe, and the list file looks like this:

    IC9eVAY.png

     

  16. 9 hours ago, uyjulian said:

    Check the file extensions. If they are hidden, show them.

    The file extensions both before and after compressing seem to be the same eri format,  I checked inside the created archive as well.

    What I did find however was that the compression also compresses the folder in which the images were held, in this case the 'original' folder.

    So instead of the eri files being directly inside the archive, there's now a subdirectory \originals\(files) inside the noa. 

  17. 40 minutes ago, uyjulian said:

    Put a space between the arguments "E:\yosuga\edit" and "E:\yosuga\data1.noa"

    Good news, the commands are working and making uncompressed noa archives. Thanks so much for your help!

    Bad news, the files still don't register in-game, It can't read the images inside the archive.

    the completed noa file is now (in theory) identical to the original in terms of size and content, no idea why they still aren't compatible.

    Right now I'm trying to attempt a complete recompressing from eri file level and see if it works.

  18. Okay, I changed the file name of the directory itself to 'yosuga' for safe measure, and used quotations for the directories to kill all spaces possible.

    my command now looks like : .\noa32c.exe /p /d /raw "E:\yosuga\edit""E:\yosuga\data1.noa"

    However, I'm seeing a message Telling me the "input file name wasn't specified" ....?

     

    btw, if I try the file-list type command, it instead gives me a "output file name wasn't specified"

     

     

  19. On 6/20/2019 at 1:32 PM, uyjulian said:

    Can GARbro extract the archives? If so, source code is available, and the file format seems simple enough, so you may be able to write a packer from GARbro's extraction code: https://github.com/morkt/GARbro/blob/e384ec2ef7542fa3e8a5489a98b5ea127cd7e1a2/ArcFormats/Ipac/ArcIPAC.cs

    That's something I would really like to do, but I'm a complete novice when it comes to coding as in 'doesn't even know the basics' kind of novice.

    I've actually taken to looking up source codes for packers on github to try and make sense of the scripts, but so far I'm at a complete loss for how to implement

    the source for this particular format into a individual packer.

  20. 19 hours ago, uyjulian said:

    .¥noa32c.exe /p /d /raw C:¥path¥to¥input¥file¥or¥directory C:¥path¥to¥archive¥file.noa

     

    Alternatively, if you have a list file formatted like the following:

     

    
    
     

     

    you can also do .¥noa32c.exe /p /d /raw /l C:¥path¥to¥list¥file.txt C:¥path¥to¥archive¥file.noa

     

    By the way, paths can be formatted as absolute (S:¥uch¥as¥this) or relative to the current directory (.¥like¥this).

    I've been having a go at it for a few hours, but though I do get the indication that the exe was triggered in some way (a brief flash of a prompt box)

    Nothing else is happening or created as a result.

    The directories for the  original source archive // noa32c // source files(to be packed) // output destination are 

    E: \ yosuga no sora \ original \ data 1. noa // E: \ yosuga no sora \ noa 32 // E: \ yosuga no sora \ edit // e: \ yosuga no sora \ data 1. noa reflectively.

    The attempted commands are

    . \ noa32c / p / d / raw / I E: \ yosuga no sora \ data1.nal E: \ yosuga no sora \ data1.noa (compression)

    . ¥ Noa32c / XE: ¥ Yosuga No Sora ¥ Original ¥ Data1.Noa E: ¥ Yosuga No Sora (Decompression)

     

    PS: I also tried it with a file list (created via dir /b>print.txt) but in this case I got a message reading 

    "could not open print.txt" 

  21.  

    On 6/20/2019 at 1:26 PM, uyjulian said:

    Did you open a cmd window (Press the key combination: Windows-R, type in "cmd", then hit the enter key)?

    Did you change directory to one containing noa32c.exe (command: "cd C:¥path¥to¥directory¥"), then run noa32c.exe in the correct directory (command: ".¥noa32c.exe <arguments>")? (Tip: You can drag and drop files and folders from Windows Explorer to the console window to automatically type in the path in the console window)

    Oh, I was under the impression that the .¥noa32c.exe would run a separate prompt for noa32. Seems like that wasn't the case tho.  
    Since I'm repacking an archive I guess the options I need are / p and / raw  ?

    If you don't mind, could you give me a example of what the <arguments> input would look like?

  22. 7 hours ago, uyjulian said:

    Here's the documentation of noa32c/noa32w:

     

     

    Oh, never new that other version had all those additional options to it. What I'm assuming as the issue right now is that 

    my GUI version of noa32 is compressing files during archive creation by default, but there's no option to disable that particular function.

    I think the / raw option might be what I'm looking for, only I'm not entirely sure as to how it works out in the CLI version of the program

    Edit: I'm trying to run noa32c using cmd, but every time I attempt to /start noa32c.exe a blank prompt appears for a split second before opting out.

    Im a complete rookie when it comes to CLI types, does anyone have some pointers?

  23. So I'm trying to repack PAK files that I took apart using Crass. The game is  堕淫フォーカス~パック~, from Heat-Soft / Eroro /2009

    The only 2 real tools i've found with potential chances are ACpack32 and Filepack32,  but I can't seem to get ACpack to work from some reason and Filepack32 is as far as I can tell,
    extinct from the internet (all links are rapidshare = dead) .

    The other tool I've tried is createSRPak, but the files made though it are unreadable by the game.

     

    I posted a similar question on the Data Extraction thread, and as of now the only leads i've got are the Crass code Nanashi3 got me:

    #include <windows.h>
    #include <tchar.h>
    #include <crass_types.h>
    #include <acui.h>
    #include <cui.h>
    #include <package.h>
    #include <resource.h>
    #include <cui_error.h>
    #include <utility.h>
    #include <stdio.h>
    
    /* 接口数据结构: 表示cui插件的一般信息 */
    struct acui_information IPAC_cui_information = {
    	NULL,					/* copyright */
    	NULL,					/* system */
    	_T(".PAK .WST"),		/* package */
    	_T("1.0.3"),			/* revision */
    	_T("痴汉公贼"),			/* author */
    	_T("2009-3-29 23:09"),	/* date */
    	NULL,					/* notion */
    	ACUI_ATTRIBUTE_LEVEL_UNSTABLE
    };
    
    /* 所有的封包特定的数据结构都要放在这个#pragma段里 */
    
    #pragma pack (1)
    typedef struct {
    	s8 magic[4];		/* "IPAC" */
    	u16 index_entries;
    	u16 unknown;
    } PAK_header_t;
    
    typedef struct {
    	s8 name[32];
    	u32 unknown;
    	u32 offset;
    	u32 length;
    } PAK_entry_t;
    
    typedef struct {
    	s8 magic[4];		/* "IEL1" */
    	u32 length;
    } iel1_header_t;
    
    /*
    20 bytes header
    1024 bytes palette
    width * height * 3 dib data
    width * height alpha
    */
    typedef struct {
    	s8 magic[4];		/* "IES2" */
    	u32 unknown;		/* "IES2" */
    	u32 width;
    	u32 height;
    	u32 bits_count;
    	u32 reserved[3];
    } ies2_header_t;
    
    struct key {
    	s32 low;
    	s32 high;
    };
    
    typedef struct {
    	s8 magic[4];		/* "WST2" */
    	u32 reserved[2];
    	u16 adpcm_fmt_parameter[14];
    } wst_header_t;
    #pragma pack ()
    
    static void *my_malloc(DWORD len)
    {
    	return malloc(len);
    }
    
    static inline unsigned char getbit_le(unsigned char byte, unsigned int pos)
    {
    	return !!(byte & (1 << pos));
    }
    
    static DWORD lzss_decompress(unsigned char *uncompr, DWORD uncomprlen, 
    							unsigned char *compr, DWORD comprlen)
    {
    	unsigned int act_uncomprlen = 0;
    	/* compr中的当前字节中的下一个扫描位的位置 */
    	unsigned int curbit = 0;
    	/* compr中的当前扫描字节 */
    	unsigned int curbyte = 0;
    	unsigned int nCurWindowByte = 0xfee;
    	unsigned int win_size = 4096;
    	BYTE win[4096];
    	
    	memset(win, ' ', nCurWindowByte);
    	while (1) {
    		/* 如果为0, 表示接下来的1个字节原样输出 */
    		BYTE flag;
    
    		if (curbyte >= comprlen)
    			break;
    
    		flag = compr[curbyte++];
    		for (curbit = 0; curbit < 8; curbit++) {
    			if (getbit_le(flag, curbit)) {
    				unsigned char data;
    	
    				if (curbyte >= comprlen)
    					goto out;
    
    				if (act_uncomprlen >= uncomprlen)
    					goto out;
    
    				data = compr[curbyte++];
    				uncompr[act_uncomprlen++] = data;
    				/* 输出的1字节放入滑动窗口 */
    				win[nCurWindowByte++] = data;
    				nCurWindowByte &= win_size - 1;
    			} else {
    				unsigned int copy_bytes, win_offset;
    				unsigned int i;
    
    				if (curbyte >= comprlen)
    					goto out;
    
    				win_offset = compr[curbyte++];
    
    				if (curbyte >= comprlen)
    					goto out;
    				copy_bytes = compr[curbyte++];
    				win_offset |= (copy_bytes >> 4) << 8;
    				copy_bytes &= 0x0f;
    				copy_bytes += 3;
    
    				for (i = 0; i < copy_bytes; i++) {	
    					unsigned char data;
    
    					if (act_uncomprlen >= uncomprlen)
    						goto out;
    
    					data = win[(win_offset + i) & (win_size - 1)];
    					uncompr[act_uncomprlen++] = data;		
    					/* 输出的1字节放入滑动窗口 */
    					win[nCurWindowByte++] = data;
    					nCurWindowByte &= win_size - 1;	
    				}
    			}
    		}
    	}
    out:
    	return act_uncomprlen;
    }
    
    static int ipac_decompress_iel1(iel1_header_t *iel1, DWORD iel1_len, 
    						BYTE **ret_buf, DWORD *ret_len)
    {
    	BYTE *uncompr, *compr;
    	DWORD uncomprLen, comprLen, actlen;
    
    	uncomprLen = iel1->length;
    	uncompr = (BYTE *)malloc(uncomprLen);
    	if (!uncompr)
    		return -1;
    
    	compr = (BYTE *)(iel1 + 1);
    	comprLen = iel1_len - sizeof(*iel1);
    	actlen = lzss_decompress(uncompr, uncomprLen, compr, comprLen);
    	if (actlen != uncomprLen) {
    		free(uncompr);
    		return -1;
    	}
    	*ret_buf = uncompr;
    	*ret_len = actlen;
    
    	return 0;
    }
    
    /********************* WST *********************/
    
    /* 封包匹配回调函数 */
    static int IPAC_WST_match(struct package *pkg)
    {
    	s8 magic[4];
    
    	if (pkg->pio->open(pkg, IO_READONLY))
    		return -CUI_EOPEN;
    
    	if (pkg->pio->read(pkg, magic, sizeof(magic))) {
    		pkg->pio->close(pkg);
    		return -CUI_EREAD;
    	}
    
    	if (memcmp(magic, "WST2", 4)) {
    		pkg->pio->close(pkg);
    		return -CUI_EMATCH;	
    	}
    
    	return 0;	
    }
    
    /* 封包资源提取函数 */
    static int IPAC_WST_extract_resource(struct package *pkg,
    									 struct package_resource *pkg_res)
    {
    	BYTE *wst_buf;
    	u32 wst_buf_len;
    
    	if (pkg->pio->seek(pkg, 0, IO_SEEK_SET))
    		return -CUI_ESEEK;
    
    	if (pkg->pio->length_of(pkg, &wst_buf_len))
    		return -CUI_ELEN;
    
    	wst_buf = (BYTE *)malloc(wst_buf_len);
    	if (!wst_buf)
    		return -CUI_EMEM;
    
    	if (pkg->pio->read(pkg, wst_buf, wst_buf_len)) {
    		free(wst_buf);
    		return -CUI_EREAD;
    	}
    
    	pkg_res->raw_data = wst_buf;
    	pkg_res->raw_data_length = wst_buf_len;
    
    	return 0;
    }
    
    /* 资源保存函数 */
    static int IPAC_WST_save_resource(struct resource *res, 
    								  struct package_resource *pkg_res)
    {
    	WAVEFORMATEX wav_header;
    	DWORD riff_chunk_len, fmt_chunk_len, data_chunk_len;
    	char *riff = "RIFF";
    	char *id = "WAVE"; 
    	char *fmt_chunk_id = "fmt ";
    	char *data_chunk_id = "data";
    	char *hack_info = "Hacked By 痴汉公贼";
    	WORD adpcm_para[16];
    	BYTE *data_chunk; 
    	wst_header_t *wst2;
    	BYTE *wst_buf = (BYTE *)pkg_res->raw_data;
    	DWORD wst_buf_len = pkg_res->raw_data_length;
    	
    	if (res->rio->create(res))
    		return -CUI_ECREATE;
    
    	wst2 = (wst_header_t *)wst_buf;
    	/* 这个应该是还原为ADCM以后的结果 */
    	/* 00441E00  01 00 02 00 44 AC 00 00 10 B1 02 00 04 00 10 00  ....D?..?..... */
    	wav_header.wFormatTag = 2;	/* ADPCM */
    	wav_header.nChannels = 2;
    	wav_header.nSamplesPerSec = 0xac44;	
    	wav_header.nAvgBytesPerSec = 0xac44;	/* ADPCM是4:1压缩,因此ac44的4倍就是0x2b110了 */
    	wav_header.nBlockAlign = 0x800;
    	wav_header.wBitsPerSample = 4;
    	wav_header.cbSize = 32;
    
    	adpcm_para[0] = 0x07f4;
    	adpcm_para[1] = 0x0007;
    
    	memcpy(&adpcm_para[2], wst2->adpcm_fmt_parameter, 
    		sizeof(wst2->adpcm_fmt_parameter));
    	data_chunk = (BYTE *)(wst2 + 1);
    
    	data_chunk_len = wst_buf_len - sizeof(*wst2);
    	data_chunk_len &= ~(wav_header.nBlockAlign - 1);
    	fmt_chunk_len = 16 + 2 + wav_header.cbSize;
    	riff_chunk_len = 4 + (8 + fmt_chunk_len) + (8 + data_chunk_len);
    
    	if (res->rio->write(res, (char *)riff, 4)) {
    		res->rio->close(res);
    		return -CUI_EWRITE;
    	}
    
    	if (res->rio->write(res, &riff_chunk_len, 4)) {
    		res->rio->close(res);
    		return -CUI_EWRITE;
    	}
    			
    	if (res->rio->write(res, id, 4)) {
    		res->rio->close(res);
    		return -CUI_EWRITE;
    	}		
    			
    	if (res->rio->write(res, fmt_chunk_id, 4)) {
    		res->rio->close(res);
    		return -CUI_EWRITE;
    	}
    
    	if (res->rio->write(res, &fmt_chunk_len, 4)) {
    		res->rio->close(res);
    		return -CUI_EWRITE;
    	}
    			
    	if (res->rio->write(res, &wav_header, sizeof(wav_header))) {
    		res->rio->close(res);
    		return -CUI_EWRITE;
    	}			
    
    	if (res->rio->write(res, adpcm_para, sizeof(adpcm_para))) {
    		res->rio->close(res);
    		return -CUI_EWRITE;
    	}	
    
    	if (res->rio->write(res, data_chunk_id, 4)) {
    		res->rio->close(res);
    		return -CUI_EWRITE;
    	}
    				
    	if (res->rio->write(res, &data_chunk_len, 4)) {
    		res->rio->close(res);
    		return -CUI_EWRITE;
    	}
    
    	if (res->rio->write(res, data_chunk, data_chunk_len)) {
    		res->rio->close(res);
    		return -CUI_EWRITE;
    	}
    			
    	if (res->rio->write(res, hack_info, strlen(hack_info))) {
    		res->rio->close(res);
    		return -CUI_EWRITE;
    	}
    
    	res->rio->close(res);
    	
    	return 0;
    }
    
    /* 封包资源释放函数 */
    static void IPAC_WST_release_resource(struct package *pkg, 
    									  struct package_resource *pkg_res)
    {
    	if (pkg_res->raw_data) {
    		free(pkg_res->raw_data);
    		pkg_res->raw_data = NULL;
    	}
    }
    
    /* 封包卸载函数 */
    static void IPAC_WST_release(struct package *pkg, 
    							 struct package_directory *pkg_dir)
    {
    	pkg->pio->close(pkg);
    }
    
    /* 封包处理回调函数集合 */
    static cui_ext_operation IPAC_WST_operation = {
    	IPAC_WST_match,				/* match */
    	NULL,						/* extract_directory */
    	NULL,						/* parse_resource_info */
    	IPAC_WST_extract_resource,	/* extract_resource */
    	IPAC_WST_save_resource,		/* save_resource */
    	IPAC_WST_release_resource,	/* release_resource */
    	IPAC_WST_release			/* release */
    };
    
    /********************* PAK *********************/
    
    /* 封包匹配回调函数 */
    static int IPAC_PAK_match(struct package *pkg)
    {
    	s8 magic[4];
    
    	if (pkg->pio->open(pkg, IO_READONLY))
    		return -CUI_EOPEN;
    
    	if (pkg->pio->read(pkg, magic, sizeof(magic))) {
    		pkg->pio->close(pkg);
    		return -CUI_EREAD;
    	}
    
    	if (memcmp(magic, "IPAC", 4)) {
    		pkg->pio->close(pkg);
    		return -CUI_EMATCH;	
    	}
    
    	return 0;	
    }
    
    /* 封包索引目录提取函数 */
    static int IPAC_PAK_extract_directory(struct package *pkg,
    									  struct package_directory *pkg_dir)
    {
    	PAK_header_t PAK_header;
    	PAK_entry_t *index_buffer;
    	unsigned int index_buffer_length;	
    
    	if (pkg->pio->seek(pkg, 0, IO_SEEK_SET))
    		return -CUI_ESEEK;
    
    	if (pkg->pio->read(pkg, &PAK_header, sizeof(PAK_header)))
    		return -CUI_EREAD;
    
    	pkg_dir->index_entries = PAK_header.index_entries;
    	index_buffer_length = pkg_dir->index_entries * sizeof(PAK_entry_t);
    	index_buffer = (PAK_entry_t *)malloc(index_buffer_length);
    	if (!index_buffer)
    		return -CUI_EMEM;
    
    	if (pkg->pio->read(pkg, index_buffer, index_buffer_length)) {
    		free(index_buffer);
    		return -CUI_EREAD;
    	}
    
    	pkg_dir->directory = index_buffer;
    	pkg_dir->directory_length = index_buffer_length;
    	pkg_dir->index_entry_length = sizeof(PAK_entry_t);
    
    	return 0;
    }
    
    /* 封包索引项解析函数 */
    static int IPAC_PAK_parse_resource_info(struct package *pkg,
    										struct package_resource *pkg_res)
    {
    	PAK_entry_t *PAK_entry;
    
    	PAK_entry = (PAK_entry_t *)pkg_res->actual_index_entry;
    	strcpy(pkg_res->name, PAK_entry->name);
    	pkg_res->name_length = -1;			/* -1表示名称以NULL结尾 */
    	pkg_res->raw_data_length = PAK_entry->length;
    	pkg_res->actual_data_length = 0;	/* 数据都是明文 */
    	pkg_res->offset = PAK_entry->offset;
    
    	return 0;
    }
    
    /* 封包资源提取函数 */
    static int IPAC_PAK_extract_resource(struct package *pkg,
    									 struct package_resource *pkg_res)
    {
    	BYTE *compr, *uncompr, *actbuf;
    	DWORD uncomprlen, comprlen, actlen;
    
    	comprlen = pkg_res->raw_data_length;
    	compr = (BYTE *)malloc(comprlen);
    	if (!compr)
    		return -CUI_EMEM;
    
    	if (pkg->pio->readvec(pkg, compr, comprlen,	pkg_res->offset, IO_SEEK_SET)) {
    		free(compr);
    		return -CUI_EREADVEC;
    	}
    
    	if (pkg_res->flags & PKG_RES_FLAG_RAW) {
    		pkg_res->raw_data = compr;
    		return 0;
    	}
    
    	if (!memcmp(compr, "IEL1", 4)) {
    		if (ipac_decompress_iel1((iel1_header_t *)compr, comprlen, &uncompr, &uncomprlen)) {
    			free(compr);
    			return -CUI_EUNCOMPR;
    		}
    		free(compr);
    		compr = NULL;
    		actbuf = uncompr;
    		actlen = uncomprlen;
    	} else {
    		uncompr = NULL;
    		uncomprlen = 0;
    		actbuf = compr;
    		actlen = comprlen;
    	}
    
    	if (!memcmp(actbuf, "IES2", 4)) {
    		ies2_header_t *ies2 = (ies2_header_t *)actbuf;
    		BYTE *save_buf;
    		DWORD save_len;
    
    		if (ies2->bits_count == 24) {
    			BYTE *rgba;
    
    			actlen = ies2->width * ies2->height * 4;
    			rgba = (BYTE *)malloc(actlen);
    			if (!rgba) {
    				free(actbuf);
    				free(compr);
    				return -CUI_EMEM;
    			}
    
    			BYTE *rgb = actbuf + 0x420;
    			BYTE *p_alpha = rgb + ies2->width * ies2->height * 3;
    			BYTE *p_rgba = rgba;
    			for (unsigned int y = 0; y < ies2->height; y++) {
    				for (unsigned int x = 0; x < ies2->width; x++) {
    					BYTE alpha = *p_alpha++;					
    					p_rgba[0] = (rgb[0] * alpha + 0xff * ~alpha) / 255;
    					p_rgba[1] = (rgb[1] * alpha + 0xff * ~alpha) / 255;
    					p_rgba[2] = (rgb[2] * alpha + 0xff * ~alpha) / 255;	
    					p_rgba[3] = alpha;	
    					rgb += 3;
    					p_rgba += 4;
    				}
    			}
    
    			if (MyBuildBMPFile(rgba, actlen, NULL, 0, ies2->width,
    					0 - ies2->height, 32, &save_buf, &save_len, my_malloc)) {
    				free(rgba);
    				free(actbuf);
    				free(compr);
    				return -CUI_EMEM;				
    			}
    			free(rgba);
    		} else {
    			if (MyBuildBMPFile(actbuf + 0x420, actlen - 0x420, (BYTE *)(ies2 + 1), 0x400, ies2->width,
    					0 - ies2->height, ies2->bits_count, &save_buf, &save_len, my_malloc)) {
    				free(actbuf);
    				free(compr);
    				return -CUI_EMEM;				
    			}
    		}
    		free(actbuf);
    		uncompr = save_buf;
    		uncomprlen = save_len;
    		pkg_res->replace_extension = _T(".IES2.bmp");
    		pkg_res->flags |= PKG_RES_FLAG_REEXT;
    //	} else if (!lstrcmpi(pkg->extension, _T(".IES"))) {
    	} else if (strstr(pkg_res->name, ".IES")) {
    		BYTE *save_buf;
    		DWORD save_len;
    
    #if 0
    //		if (MyBuildBMPFile(actbuf + 0x420, actlen - 0x420, actbuf + 0x20, 0x400, *(DWORD *)actbuf,
    		if (MyBuildBMPFile(actbuf + 0x414, actlen - 0x414, NULL, 0, *(DWORD *)actbuf,
    				0 - *(DWORD *)(actbuf + 4), *(DWORD *)(actbuf + 8), &save_buf, &save_len, my_malloc)) {
    			free(actbuf);
    			return -CUI_EMEM;			
    		}
    #else
    		if (!memcmp(actbuf, "BM", 2)) {
    			pkg_res->raw_data = compr;
    			pkg_res->raw_data_length = comprlen;
    			pkg_res->actual_data = actbuf;
    			pkg_res->actual_data_length = actlen;
    			return 0;
    		} else if (*(DWORD *)(actbuf + 8) == 24) {
    			DWORD width = *(DWORD *)actbuf;
    			DWORD height = *(DWORD *)(actbuf + 4);
    			BYTE *rgba;
    
    			actlen = width * height * 4;
    			rgba = (BYTE *)malloc(actlen);
    			if (!rgba) {
    				free(actbuf);
    				free(compr);
    				return -CUI_EMEM;
    			}
    
    			BYTE *rgb = actbuf + 0x414;
    			BYTE *p_alpha = rgb + width * height * 3;
    			BYTE *p_rgba = rgba;
    			for (unsigned int y = 0; y < height; y++) {
    				for (unsigned int x = 0; x < width; x++) {
    					BYTE alpha = *p_alpha++;					
    					p_rgba[0] = (rgb[0] * alpha + 0xff * ~alpha) / 255;
    					p_rgba[1] = (rgb[1] * alpha + 0xff * ~alpha) / 255;
    					p_rgba[2] = (rgb[2] * alpha + 0xff * ~alpha) / 255;	
    					p_rgba[3] = alpha;	
    					rgb += 3;
    					p_rgba += 4;
    				}
    			}
    
    			if (MyBuildBMPFile(rgba, actlen, NULL, 0, width,
    					0 - height, 32, &save_buf, &save_len, my_malloc)) {
    				free(rgba);
    				free(actbuf);
    				free(compr);
    				return -CUI_EMEM;				
    			}
    			free(rgba);
    		} else {
    			if (MyBuildBMPFile(actbuf + 0x414, actlen - 0x414, NULL, 0, *(DWORD *)actbuf,
    					0 - *(DWORD *)(actbuf + 4), *(DWORD *)(actbuf + 8), &save_buf, &save_len, my_malloc)) {
    				free(actbuf);
    				free(compr);
    				return -CUI_EMEM;			
    			}
    		}
    #endif
    		free(actbuf);
    		uncompr = save_buf;
    		uncomprlen = save_len;
    		pkg_res->replace_extension = _T(".IES.bmp");
    		pkg_res->flags |= PKG_RES_FLAG_REEXT;
    	}
    
    	pkg_res->raw_data = compr;
    	pkg_res->raw_data_length = comprlen;
    	pkg_res->actual_data = uncompr;
    	pkg_res->actual_data_length = uncomprlen;
    
    	return 0;
    }
    
    /* 资源保存函数 */
    static int IPAC_PAK_save_resource(struct resource *res, 
    								  struct package_resource *pkg_res)
    {
    	if (res->rio->create(res))
    		return -CUI_ECREATE;
    
    	if (pkg_res->actual_data && pkg_res->actual_data_length) {
    		if (res->rio->write(res, pkg_res->actual_data, pkg_res->actual_data_length)) {
    			res->rio->close(res);
    			return -CUI_EWRITE;
    		}
    	} else if (pkg_res->raw_data && pkg_res->raw_data_length) {
    		if (res->rio->write(res, pkg_res->raw_data, pkg_res->raw_data_length)) {
    			res->rio->close(res);
    			return -CUI_EWRITE;
    		}
    	}
    
    	res->rio->close(res);
    
    	return 0;
    }
    
    /* 封包资源释放函数 */
    static void IPAC_PAK_release_resource(struct package *pkg, 
    									  struct package_resource *pkg_res)
    {
    	if (pkg_res->actual_data) {
    		free(pkg_res->actual_data);
    		pkg_res->actual_data = NULL;
    	}
    	if (pkg_res->raw_data) {
    		free(pkg_res->raw_data);
    		pkg_res->raw_data = NULL;
    	}
    }
    
    /* 封包卸载函数 */
    static void IPAC_PAK_release(struct package *pkg, 
    							 struct package_directory *pkg_dir)
    {
    	if (pkg_dir->directory) {
    		free(pkg_dir->directory);
    		pkg_dir->directory = NULL;
    	}
    
    	pkg->pio->close(pkg);
    }
    
    /* 封包处理回调函数集合 */
    static cui_ext_operation IPAC_PAK_operation = {
    	IPAC_PAK_match,					/* match */
    	IPAC_PAK_extract_directory,		/* extract_directory */
    	IPAC_PAK_parse_resource_info,	/* parse_resource_info */
    	IPAC_PAK_extract_resource,		/* extract_resource */
    	IPAC_PAK_save_resource,			/* save_resource */
    	IPAC_PAK_release_resource,		/* release_resource */
    	IPAC_PAK_release				/* release */
    };
    
    /* 接口函数: 向cui_core注册支持的封包类型 */
    int CALLBACK IPAC_register_cui(struct cui_register_callback *callback)
    {
    	/* 注册cui插件支持的扩展名、资源放入扩展名、处理回调函数和封包属性 */
    	if (callback->add_extension(callback->cui, _T(".PAK"), NULL, 
    		NULL, &IPAC_PAK_operation, CUI_EXT_FLAG_PKG | CUI_EXT_FLAG_DIR))
    			return -1;
    
    	if (callback->add_extension(callback->cui, _T(".WST"), _T(".wav"), 
    		NULL, &IPAC_WST_operation, CUI_EXT_FLAG_PKG))
    			return -1;	
    
    	return 0;
    }

     

    For starters, If anyone happens to have a copy of Filepack32.exe please re-upload it to someplace.

    Edit: I got adpack32 to work, and it doesn't support this specific type of PAK. I'm really lost now.

    If anyone has suggestions or tips I would appreciate it greatly, these PAK and Noa archives have been driving me crazy for a few days now.

×
×
  • Create New...