ファイル名に含まれる使用できない文字列を変換する。

VBS用に書いていたんだけど、
汎用性を持たせようと作り込み始めた辺りから段々と複雑化していって、
まんまと沼に嵌ってしまったので。
元々実現したかった部分のみ抽出して平坦に書き直してみた。

・やりたかったこと

・制御文字(&H0~&H1F)の半角空白化
・連続する半角空白は単一にまとめる
・前後の半角空白は削除
・使用不可文字(\ / : * ? " < > |)は全角化
・末尾半角ドットは全角化
・ファイル名が予約語なら全角化

予約語の処理までは不要かなーとも思ったが
備えあれば患いなしってことでこちらも対応。
StrConv がある VBA はラク出来て良いね。

なお、置換処理に RegExp オブジェクトを使ってないのは
1度の置換に2行の記述を必要とし、見辛くなってしまうから。

' ファイル名を正規化する
' 制御文字(&H0~&H1F)は半角空白に、連続する半角空白は単一にまとめ、ファイル名前後の半角空白は削除、
' ファイル使用不可文字(\ / : * ? " < > |)は全角変換する。
' 更に、ファイル名が予約語なら全角に、末尾半角ドットなら全角に変換する
Public Function FixedFileName(fileName As String) As String
    Dim tempName As String
    tempName = fileName
    
    ' 制御文字(&H0~&H1F)を半角空白に変換
    Dim index As Long
    For index = &H0 To &H1F
        tempName = Replace(tempName, Chr(index), " ")
    Next
    
    ' 連続した半角空白を一つにする
    Do While InStr(tempName, "  ") > 0
        tempName = Replace(tempName, "  ", " ")
    Loop
    
    ' 前後の半角空白を削除
    tempName = Trim(tempName)
    
    ' ファイル使用不可文字を全角に変換
    '  \ / : * ? " < > |
    tempName = Replace(tempName, "\", "¥") '円マーク
    tempName = Replace(tempName, ":", ":") 'コロン
    tempName = Replace(tempName, "*", "*") 'アスタリスク
    tempName = Replace(tempName, "?", "?") 'クエスチョンマーク
    tempName = Replace(tempName, """", Chr(-1449)) 'ダブルコーテーション
    tempName = Replace(tempName, "<", "<") '小なり
    tempName = Replace(tempName, ">", ">") '大なり
    tempName = Replace(tempName, "|", "|") 'ハット
    
    ' ファイル名が予約語なら全角に変換
    Dim RE As Object, reMatch As Object
    Set RE = CreateObject("VBScript.RegExp")
    RE.Pattern = "^(CON|PRN|AUX|NUL|COM[0-9]|LPT[0-9]|CLOCK\$)(\.|$)" ' 検索パターンを設定
    RE.IgnoreCase = True ' 大文字と小文字を区別しない
    RE.Global = True ' 文字列全体を検索する
    
    Set reMatch = RE.Execute(tempName)
    If reMatch.Count > 0 Then
        ' 予約語はアルファベットのみ全角に変換
        Dim tempMatch As String
        tempMatch = Replace(Replace(reMatch(0).Value, ".", ""), "$", "")
        tempName = Replace(tempName, tempMatch, StrConv(tempMatch, vbWide))
    End If
    Set reMatch = Nothing
    Set RE = Nothing
    
    ' 末尾半角ドットを全角に変換
    Dim tempLen As Long
    tempLen = Len(tempName)
    If tempLen > 0 Then
        If Right(tempName, 1) = "." Then
            If tempLen = 1 Then tempName = "."
            If tempLen >= 2 Then tempName = Left(tempName, tempLen - 1) & "."
        End If
    End If
    
    FixedFileName = tempName
End Function

参考
ファイル名に使用できない文字列が含まれていないか調べる - .NET Tips (VB.NET,C#...)
https://dobon.net/vb/dotnet/file/invalidpathchars.html

Naming Files, Paths, and Namespaces
https://social.msdn.microsoft.com/Search/ja-jp/?Query=Naming%20Files%2C%20Paths%2C%20and%20Namespaces

エクセルでお小遣い帳つけ始めた。

何度目かの支出管理、所謂お小遣い帳をつけ始めた。

※余り深く考えず、とりあえず帳簿を付けるところから。。
f:id:dumbo001:20180218152239p:plain

昨年メインPCが壊れてから随分経つが、
考え無しに日々消費を重ねていると
いつまでもお金が貯まらずPC導入に至らないので(涙)。

で、ひと月ほど登録を続けてみて感じた事は、
やっているソレ自体が依然から取り組んでいる蔵書管理や、
IT資産・物品管理と大差無いというかほぼ似たような作業であり、
この二度手間はどうにかしたいものだと思った。

まだしばらくは手打ちで頑張るほか無いけども、
煩雑な作業が長続きしないのは分かり切っているので、
少しずつでもマクロ化していって運用コストを抑えて行きたい。

ZIP32J.DLLをVBSから利用してファイルをZIP圧縮する。

以前エントリで VBS から LZH 圧縮するサンプルを提示したが、その ZIP 圧縮版である。

今回も総合アーカイバプロジェクトから導入の
ZIP32J.DLL というライブラリを用いた方法となる。

実のところ、DLL を用いない OS 標準機能での ZIP 圧縮方法もあるにはあるのだが、
圧縮実行後にウエイトを設けないと失敗することがあるらしい(非同期圧縮じゃない?)のと、
パスワード付き ZIP を作れない仕様だったため、選択からは外した。

利用する Win32API 関数はこちら。

ZIP32J.DLL

int WINAPI Zip(const HWND hWnd,LPCSTR szCmdLine,LPSTR szOutput,
		const DWORD dwSize);

見て解るとおり、UNLHA32.DLL の Unlha 関数に酷似しているので、
コード自体は前に書いたものを少し弄るだけで対応出来た。

ラッパー関数

' Zip関数(ZIP32J.DLL)を実行する。
' 操作に成功したらTrueを、そうでなければFalseを返す
Function ExecZip(szCmdLine)
    Const DW_SIZE = 256 ' 出力バッファサイズ
    Dim command
    
    ' ZIP32J.DLL 呼び出しコマンドを生成する
    command = "CALL(""Zip32j"", ""Zip"", ""JJCFJ"", 0, " & """" & szCmdLine & """" & ", 0, " & DW_SIZE & ")"
    
    ' zip32j を呼び出す
    If CreateObject("Excel.Application").ExecuteExcel4Macro(command) = 0 Then
        ExecZip = True
    Else
        ExecZip = False
    End If
End Function

これもまた ExecuteExcel4Macro 関数経由で実行。
実際の呼び出しは以下の通り。

Sub Test()
    If ExecZip("-j -u """"c:\work\test.zip"""" """"c:\work\test.txt""""") = False Then
        MsgBox "ExecZip error!"
    End If
End Sub

ExecZip 関数に渡したコマンドは、
指定ファイルを同名で ZIP 圧縮、但しファイルパスを含めない、
といったものである。
(test.zip の中には test.txt のみ入っている。)

より高度な圧縮を行いたい場合、以下の API 説明を参考にすると良いだろう。


ZIP32J.DLL ZIP系API一覧とその説明 ...
http://openlab.jp/tsuneo/soft/zip32j/zip32j/SDK/API_ZIP.TXT

ZIP32J.DLL Zip() APIのコマンド説明 ...
http://openlab.jp/tsuneo/soft/zip32j/zip32j/SDK/CMD_ZIP.TXT

ヤルハラのおもちアドバンス。

昨年末に作っていたゲームの最終調整を終えたので、
以下の URL にて公開した。

・ヤルハラのおもちアドバンス

http://regekatsu.seesaa.net/article/455926759.html

f:id:dumbo001:20180101220725p:plain
f:id:dumbo001:20180101220746p:plain

GBA の勘所がようやく分かって来て、
本当なら続けてまた何か作りたいところだが
月初から暫くの間、仕事プログラムと向き合わなければならないので、
一旦趣味の開発は休むことにしようと思う。

kksn_ripper.py で8BIT MUSIC POWER ファイナル&アンコールをごにょごにょする。

f:id:dumbo001:20171226214454j:plain:w640

例によって VirtuaNES 組み込み実行ファイルから ROM をごにょごにょする方法。

今回もベースツールは id:eagle0wl さんのものを用いる。

以下リンクより入手されたし。

http://eagle0wl.hatenadiary.jp/entry/2017/05/01/045856


・8BIT MUSIC POWER FINAL.exe から 8BIT MUSIC POWER FINAL.nes をごにょごにょ出来るようにする。

22行目に下記1行を追加

rip_status_table.append({'md5_hash': u'031b7afa1fcc8ec0b2469ff88e043ef5', 'offset': 0x00069084, 'size': 0x00046BE0}) # 8BIT MUSIC POWER FINAL.exe


23行目のNESヘッダ定義を下記の通り修正

commoniNESHeader = '4E45531A102042000000000000000000'.decode('hex')

↓

commoniNESHeader = '4E45531A202040000000000000000000'.decode('hex')

※カートリッジ版と CRC が違う。吸い出しミスでなければバージョン違い?


・8BIT MUSIC POWER ENCORE.exe から 8BIT MUSIC POWER ENCORE.nes をごにょごにょ出来るようにする。

22行目に下記1行を追加

rip_status_table.append({'md5_hash': u'e16444892866a35f2c75fee2ac541991', 'offset': 0x00069084, 'size': 0x0002AD60}) # 8BIT MUSIC POWER ENCORE.exe


23行目のNESヘッダ定義を下記の通り修正

commoniNESHeader = '4E45531A102042000000000000000000'.decode('hex')

↓

commoniNESHeader = '4E45531A102041000000000000000000'.decode('hex')


追記。
大元のツールでも対応されたみたいなので、
上記修正を行わずとも抽出出来るようになりました。

今からコミケ合わせでGBAゲームを作ってみる(9)

電源投入の度に部品出現パターンが同じになってしまう所と、
ハイスコアの記録において、SRAM読み書きを用いて対処。

・ヤルハラのおもちアドバンス
f:id:dumbo001:20171223194515p:plain

これで求める要件は一通り満たしたので、
後は元旦のバイナリ公開に向けて準備するだけ。

ソースコードは、、
GBA Develop Wiki さんのサンプルプログラムから
ライブラリをかなり利用させて貰っていて
半分くらい自分の書いたコードじゃないから厳しいかも…。


参考文献:
NO.114 2048
http://akkera102.sakura.ne.jp/gbadev/index.php?NO.114%202048
後日談
http://akkera102.hatenablog.com/entry/2016/02/13/190713

今からコミケ合わせでGBAゲームを作ってみる(8)

BGタイルマップによるフォント、背景画像を表示するところまで出来上がり。
これでゲームとしての体裁は整った感じ。

ヤルハラのおもちアドバンス(1)
f:id:dumbo001:20171220143854j:plain:w360

ヤルハラのおもちアドバンス(1)
f:id:dumbo001:20171220144406j:plain:w360

後はパーツの出現における電源パターン回避と、ハイスコアの記録かなぁ。
RTCの無いGBA環境で、さてどうしたものだろうか。。

参考文献:
Tutorial.10 タイルモード(1)
http://akkera102.sakura.ne.jp/gbadev/index.php?tutorial.10
Tutorial.11 タイルモード(2)
http://akkera102.sakura.ne.jp/gbadev/index.php?tutorial.11