HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2014
1228
にゃんちゃん昨日の実験結果4解決


にゃんちゃん

リンク

2014/12/28(Sun) 13:10:01|NO.66681

別スレで失礼します。
http://hsp.tv/play/pforum.php?mode=all&num=66673
で回答をいただいたあと、実験してみた結果を報告します。
結論から言うと、ファイルの追加は無理でした。
ファイルチャンクは問題なく追加できて、追加前のファイルたちも読めたのですが、追加したファイルがどうしても読めませんでした。
どうやら、ファイルチャンクに個別に書いてある4バイトの暗号化キーが曲者のようで、おそらくDPMファイル全体で整合性が取れるように、各ファイルについて生成されているんだと思います。このキーの値はDPMを作るたびに変わるようです。
追加したファイルは、この暗号化キーの整合性がとれないみたいで、まったく読めませんでした。
プログラムで作ったファイルを解析して、オフセットとかファイルサイズがバグってないかどうかも確認しましたが、どうやらだめなようです。まさか、その解析の間にバグらせた…ってことはないと信じたいです。
う〜ん、やっぱり独自フォーマットでしょうか?でも、なんにもしなくても勝手に読み込んでくれるDPMの機能は便利だし、自分で暗号化を組むと読み込みが重くなりそうだし…
なにか思いつくこととかありますか?もしよければご意見をお聞かせください。



この記事に返信する


にゃんちゃん

リンク

2014/12/28(Sun) 13:43:09|NO.66682

なんか、暗号化バイナリを書き込む部分がバグってるような気がしてきたので、スクリプトを張ってみます。
なにかお気づきの点があればご指摘お願いします。
書きかけなのでかなり汚いです。ごめんなさい。

infile="a.dpm"//操作するファイル名 addFile="b.dpm"//追加するアーカイブ名 //ステップ1:ヘッダ情報を解析してみる //ヘッダを読み込み header="" bload infile,header,16 //DPM宣言のチェック if strmid(header,0,4)!"DPMX"{ dialog "DPMファイルじゃない",,"エラー" end } dataChunkOffset=lpeek(header,4)//データチャンクの開始位置 totalFiles=lpeek(header,8)//中身の全ファイル数 //最後の4バイトはなにもないので終わり sdim header,0//読んだのでもういらない //ステップ2:ファイル情報チャンクを解析してみる //ファイル情報チャンク全体の読み込み sdim chunk,32*totalFiles+1 bload infile,chunk,32*totalFiles,16 pointer=0//現在のファイルポインタ sdim filenames,20,totalFiles//ファイル名 dim filesizes,totalFiles//ファイルサイズ dim fileoffsets,totalFiles//データチャンクからの位置 dim filekeys,totalfiles repeat totalFiles getstr filenames(cnt),chunk,pointer filekeys(cnt)=lpeek(chunk,pointer+20) filesizes(cnt)=lpeek(chunk,pointer+28) fileoffsets(cnt)=lpeek(chunk,pointer+24) pointer+=32 loop //次に、追加するDPMファイルの情報を読む //ヘッダを読み込み header="" bload addFile,header,16 //DPM宣言のチェック if strmid(header,0,4)!"DPMX"{ dialog "DPMファイルじゃない",,"エラー" end } dataChunkOffset2=lpeek(header,4)//データチャンクの開始位置 totalFiles2=lpeek(header,8)//中身の全ファイル数 sdim header,0 //ファイル情報チャンク全体の読み込み sdim chunk2,32*totalFiles2+1 bload addFile,chunk2,32*totalFiles2,16 pointer=0//現在のファイルポインタ sdim filenames2,20,totalFiles2//ファイル名 dim filesizes2,totalFiles2//ファイルサイズ dim fileoffsets2,totalFiles2//データチャンクからの位置 dim filekeys2,totalfiles2 repeat totalFiles2 getstr filenames2(cnt),chunk2,pointer filekeys2(cnt)=lpeek(chunk2,pointer+20) filesizes2(cnt)=lpeek(chunk2,pointer+28) fileoffsets2(cnt)=lpeek(chunk2,pointer+24) pointer+=32 loop //これで全データの解析終了 //ここまでは正常動作 //新しいヘッダおよびファイル情報チャンクの作成 finalFiles=totalFiles+totalFiles2//合計のファイル数 sdim header,17+(32*finalFiles) header="DPMX"//最初のおまじない offset=16+(32*finalFiles)//最終的なオフセット lpoke header,4,offset lpoke header,8,finalFiles //ヘッダ完成 //続いて、追加するファイルのオフセット値を書き換え exist inFile s=strsize newoffset=s-offset+32//追加する最初のファイルの位置 pointer=24 fileCount=0 repeat totalFiles2//書き換え開始 tmp=newoffset//開始位置をセット if fileCount:{//開始位置からずらさないとだめな時 repeat fileCount tmp+=fileoffsets(cnt) loop } lpoke chunk2,pointer,tmp//変更したオフセットを書き込み pointer+=32 fileCount++ loop //ファイル情報チャンクを書いていく //まずは追加前のチャンクを全部展開する pointer=16 repeat 32*totalFiles poke header,pointer,peek(chunk,cnt) pointer++ loop //次に、追加したチャンクを展開する repeat 32*totalFiles2 poke header,pointer,peek(chunk2,cnt) pointer++ loop //ファイルチャンクができた //とりあえず保存する bsave "test.dpm",header //次は、データをどんどん書いていく //1MBずつ書く //まずは追加前のほうから pointer=dataChunkOffset//読むほうのポインタ pointer2=offset//書くほうのポインタ exist inFile//全体のサイズ size=strsize repeat//データがなくなるまで繰り返す remaining_bites=size-pointer if remaining_bites=0:break if remaining_bites>1024000:{ read=1024000 }else{ read=remaining_bites } sdim tmp,read+1 bload inFile,tmp,read,pointer bsave "test.dpm",tmp,read,pointer2 pointer+=read pointer2+=read loop //追加した部分 pointer2=newoffset pointer=dataChunkOffset2 exist addFile//全体のサイズ size=strsize repeat//データがなくなるまで繰り返す remaining_bites=size-pointer if remaining_bites=0:break if remaining_bites>1024000:{ read=1024000 }else{ read=size-pointer } sdim tmp,read+1 bload inFile,tmp,read,pointer bsave "test.dpm",tmp,read,pointer2 pointer+=read pointer2+=read loop dialog "done" end



Flat

リンク

2014/12/28(Sun) 17:39:58|NO.66684


src_dpm = "src.dpm" // 入力 add_dpm = "add.dpm" // 追加 dst_dpm = "dst.dpm" // 出力 // 入力分の情報取得 exist src_dpm src_size = strsize if src_size < 0 { dialog "入力分DPMが読み込めません", 1 end } sdim src_data, src_size bload src_dpm, src_data // 情報取得 src_hsize = lpeek(src_data, 4) - 16 src_fnum = lpeek(src_data, 8) src_dsize = src_size - src_hsize - 16 // 追加分の情報取得 exist add_dpm add_size = strsize if add_size < 0 { dialog "追加分DPMが読み込めません", 1 end } sdim add_data, add_size bload add_dpm, add_data // 情報取得 add_hsize = lpeek(add_data, 4) - 16 add_fnum = lpeek(add_data, 8) add_dsize = add_size - add_hsize - 16 // 出力ファイル作成 dst_hsize = src_hsize + add_hsize dst_fnum = src_fnum + add_fnum dst_dsize = src_dsize + add_dsize dst_size = 16 + dst_hsize + dst_dsize // ヘッダ作成 sdim dst_data, dst_size lpoke dst_data, 0, 0x584D5044 lpoke dst_data, 4, 16 + dst_hsize lpoke dst_data, 8, dst_fnum lpoke dst_data, 12, 0x00000000 // チャンク連結 offset = 16 memcpy dst_data, src_data, src_hsize, offset, 16 : offset += src_hsize memcpy dst_data, add_data, add_hsize, offset, 16 : offset += add_hsize memcpy dst_data, src_data, src_dsize, offset, 16 + src_hsize : offset += src_dsize memcpy dst_data, add_data, add_dsize, offset, 16 + add_hsize : offset += add_dsize // 追加分の各ファイルのデータオフセット修正 repeat add_fnum offset = 16 + src_hsize + 32 * cnt + 24 lpoke dst_data, offset, lpeek(dst_data, offset) + src_dsize loop // 書き出し bsave dst_dpm, dst_data
こちらで少し書いてみました。
エラーチェックなどは殆どしていませんので実用には耐えないと
思いますが、プログラム作成の参考になれば幸いです。
一応3.22で正常に動作することを確認しました。



にゃんちゃん

リンク

2014/12/28(Sun) 19:56:18|NO.66688

ほ ほんとだ、動いてますね。どこがいけなかったんだろう…
提示いただいたスクリプトにエラーチェック入れたり、DPMが大きくなったときのためのメモリ節約機能を入れたりして、システムに組み込んでみたいと思います。
バイナリ操作はまだ数度しかやっていなかったので、スクリプトの中身も勉強になりました。ありがとうございます。



にゃんちゃん

リンク

2014/12/28(Sun) 22:00:28|NO.66690

できました。
Flatさんのソースを参考にしながら、自分自身勉強したかったので、全部書き直しました。前のソースは、DPM解析の実験段階から使いまわしてたので、コードもそれなりにスマートに成りました。
とりあえず、使いやすいようにモジュールにしました。それから、アーカイブファイル全体を一気に読み込まなくなったので、使用メモリがものすごく減りました。
報告と、ほかの皆様へのご参考をかねて張っておきます。

#module dpmRebuildor //DPMリビルドモジュール #deffunc dpm_rebuild str in, str add, str out /* P1:オリジナルアーカイブ P2:追加アーカイブ P3:出力先アーカイブ 戻り値 1:成功 -1:パラメータ欠落 -2:オリジナルアーカイブへのアクセス失敗 -3:追加アーカイブへのアクセス失敗 ※オリジナルと追加用アーカイブは、必ず同じ暗号化キーで暗号化されていなければなりません。 */ if in="" or add="" or out="":return -1 //オリジナルアーカイブのヘッダを読み取り sdim header,17 exist in in_size=strsize if in_size<=0:return -2 bload in,header,16 if strmid(header,0,4)!"DPMX":return 0 in_offset=lpeek(header,4) in_fnum=lpeek(header,8) in_datasize=in_size-in_offset //あとで使うので、ファイルチャンクを読み込んでおく sdim in_chunk,(32*in_fnum)+1 bload in,in_chunk,32*in_fnum,16 //追加アーカイブのヘッダを読み取り sdim header,17 exist add add_size=strsize if add_size<=0:return -3 bload add,header,16 add_offset=lpeek(header,4) add_fnum=lpeek(header,8) add_datasize=add_size-add_offset sdim add_chunk,(32*add_fnum)+1 bload add,add_chunk,32*add_fnum,16 //ファイルオフセットの修正 pointer=24 repeat add_fnum lpoke add_chunk,pointer,lpeek(add_chunk,pointer)+in_datasize pointer+=32 loop //出力ファイル作成 sdim dstb,17+(32*in_fnum)+(32*add_fnum) dstb="DPMX" out_offset=16+(32*in_fnum)+(32*add_fnum) lpoke dstb,4,16+(32*in_fnum)+(32*add_fnum) lpoke dstb,8,in_fnum+add_fnum memcpy dstb,in_chunk,32*in_fnum,16,0 memcpy dstb,add_chunk,32*add_fnum,16+(32*in_fnum),0 bsave out,dstb sdim dstb,0 //データチャンクのバイナリを、1MBずつ拾って書き込む rp=in_offset//読み込みポインタ wp=out_offset//書き込みポインタ repeat remaining=in_size-rp if remaining=0:break if remaining>1024000:{ read=1024000 }else{ read=remaining } sdim d,read+1 bload in,d,read,rp bsave out,d,read,wp rp+=read:wp+=read loop sdim d,0 rp=add_offset wp=out_offset+in_datasize repeat remaining=add_size-rp if remaining=0:break if remaining>1024000:{ read=1024000 }else{ read=remaining } sdim d,read+1 bload add,d,read,rp bsave out,d,read,wp rp+=read:wp+=read loop sdim d,0 //リビルド終了 return 1 #global



ONION software Copyright 1997-2021(c) All rights reserved.