バージョン管理を始めてみる。

主に仕事プログラム(エクセルマクロ)での、
保守とかバージョンアップとか、
移動中スマホDropboxからソースが見れないとか諸々あって、
ついでに言うとフォルダバージョン管理に嫌気が差して来たので、
Git と SourceTree を導入。

わかばちゃんと学ぶGit使い方入門って本読んで、
やっと有用性を知れたところ。

食わず嫌いも大概にせえよと。

robocopy コマンドで簡易バックアップの仕組みを用意する

先週末にメインで使っていたPCが大破。
微妙なマシンは幾らか有していた為、
そのうちのスティックPCで暫しの間過ごす事に。

データ関連は外付け USB HDD への保存を基本としていたので
移行作業自体は接続の変更だけで終了したのだが、
タスク登録していたバックアップバッチはシステムドライブ上に在り
直ぐ取り出す事も侭ならず、仕方ないので書き直すことにした。

書き直すとは言っても、実際のところ今までのバッチが
融通聞かない代物だったので、リファインの切っ掛けとしては
丁度良かった気もする。

想定する利用シーンに基づき、2 つの実行ウィザードと
1 つの実行バッチを追加。
前に書いたものよりかは大分マシなものになったと思う。

実際のスクリプトは以下。
俺俺感ぱないけど、何かの参考になれば幸いである。


(1)バッチ HDD バックアップ
設定ファイルに記述されたドライブに対してバックアップ処理を実行。

BatchHDDBackup.bat

@echo off
set cfg_name=%~n0
set cfg_ext=.ini
set cfg_file=%cfg_name%%cfg_ext%

if not exist "%cfg_file%" (
  echo コンフィグファイル %cfg_file% が見つかりません。
  
  echo ; %cfg_name% configuration>%cfg_file%
  echo [directory]>>%cfg_file%
  echo src=>>%cfg_file%
  echo dst=>>%cfg_file%
  
  echo コンフィグファイル %cfg_file% を作成しました。
  echo;
  echo 'src=' 以降にバックアップ元ドライブまたはフォルダを、
  echo 'dst=' 以降にバックアップ先ドライブまたはフォルダを、
  echo フルパスで指定してください。
  echo;
  echo なお、パスの指定に前後「"」または末尾「\」を含めないでください。
  echo 上記記号が混入してると正しく動作しません。
  echo;
  echo 例:)
  echo src=Z:
  echo dst=Y:
  echo;
  
  exit /b
)
rem コンフィグファイル %cfg_file% は既に存在します。

rem バックアップ元ドライブ
for /f "eol=; tokens=1* delims==" %%a in ('find "src" %cfg_file%') do (set src=%%b)
rem バックアップ先ドライブ
for /f "eol=; tokens=1* delims==" %%a in ('find "dst" %cfg_file%') do (set dst=%%b)

call HDDBackup.bat "%src%" "%dst%"
exit /b


BatchHDDBackup.ini

; BatchHDDBackup configuration
[directory]
src=Z:
dst=Y:

タスクスケジューラに登録して定期実行することを想定。
壊れた PC で主に利用していた動作。


(2)カレント HDD バックアップ
カレントドライブを元、選択したドライブを先としてバックアップ処理を実行。

CurrentHDDBackup.bat

@echo off
set src=%~d0
echo カレントドライブ %src% をバックアップします。
vol %src%
echo;

set dst=0
set /p dst="バックアップ先ドライブを入力してください . . . "

rem 指定されたドライブが見つかりません。
set is_exist=0
for /f "usebackq tokens=*" %%i in (`vol %dst% ^| find "ラベル" /C`) do (set is_exist=%%i)
if %is_exist%==0 goto END

vol %dst%
echo;

set yesno=n
set /p yesno="バックアップを開始しますか?(y/n) . . . "

if not "%yesno:y=y%"=="y" goto END

call HDDBackup.bat "%src%" "%dst%"

echo;
echo バックアップが終了しました。
pause
exit /b

:END
echo;
echo バックアップを中止しました。
pause
exit /b

今回一番欲しかったもの。別 PC にドライブを移した際、
即時使えるものを求めていた。
こいつがメイン、バックアップの両方に入っていれば
仮に一方が壊れた場合でも、新調したドライブへのリストアが容易に行えるって寸法。


(3)セレクト HDD バックアップ
始めに選択したドライブを元、後に選択したドライブを先としてバックアップ処理を実行。

SelectHDDBackup.bat

@echo off
echo 選択したドライブをバックアップします。
echo;

set src=0
set /p src="バックアップ元ドライブを入力してください . . . "

rem 指定されたドライブが見つかりません。
set is_exist=0
for /f "usebackq tokens=*" %%i in (`vol %src% ^| find "ラベル" /C`) do (set is_exist=%%i)
if %is_exist%==0 goto END

vol %src%
echo;

set dst=0
set /p dst="バックアップ先ドライブを入力してください . . . "

rem 指定されたドライブが見つかりません。
set is_exist=0
for /f "usebackq tokens=*" %%i in (`vol %dst% ^| find "ラベル" /C`) do (set is_exist=%%i)
if %is_exist%==0 goto END

vol %dst%
echo;

set yesno=n
set /p yesno="バックアップを開始しますか?(y/n) . . . "

if not "%yesno:y=y%"=="y" goto END

call HDDBackup.bat "%src%" "%dst%"

echo;
echo バックアップが終了しました。
pause
exit /b

:END
echo;
echo バックアップを中止しました。
pause
exit /b

カレントバックアップのついでに書いたもの。
過去何回かメインデータの方を誤って削除して、
その度にリストアで不便を伴っていたのも事実なので、
有るに越したことはないと思う。


(4)HDD バックアップ
処理本体。robocopy コマンドでバックアップ処理を実行。

HDDBackup.bat

@echo off
rem バックアップ元ドライブ
if "%~1"=="" goto END
set src=%~1

rem バックアップ先ドライブ
if "%~2"=="" goto END
set dst=%~2

set root_dir=Regekatsu
set sub_dir=Backup
set log_dir=log
set save_dir=%SystemDrive%\%root_dir%\%sub_dir%\%log_dir%
md "%save_dir%"

set dt=%date%
set tm=%time%
set dt=%dt:~0,4%-%dt:~5,2%-%dt:~8,2%
set tm=%tm:~0,2%-%tm:~3,2%-%tm:~6,2%
set tm=%tm: =0%
set log_dttm=%dt%_%tm%
set log_prefix=Backup_
set log_ext=.log
set log_file="%save_dir%\%log_prefix%%log_dttm%%log_ext%"

setlocal
cd \

robocopy "%src%" "%dst%" /MIR /R:0 /W:0 /LOG:"%log_file%" /NP /NDL /TEE

endlocal
exit /b

:END
echo usage: %~nx0% バックアップ元ドライブ バックアップ先ドライブ
exit /b


実行ログの保存先。これは決め打ち。

%SystemDrive%\Regekatsu\Backup\log

デスクトップPCが壊れたり。

しぶとく使っていたASUSマザーの自作PC
先月末でお亡くなりになった。

A8N-VM CSMなんて12年前の製品を
随分長いこと使っていたものだと我ながら感心する。

愛着とかそういうのでは無く、
安い買い物じゃないという辺りが継続利用の根本であり、
壊れるまで使い倒した原因とも言える。

そして目下の問題は、先々を考えなかった故の、
新しいマシンを手配するマネーが無いという現状だ。

スティックPCとかWinタブとか、
メイン機として微妙なラインナップはそこそこ有るので、
当面の急場は凌げそうだけども。

作業効率とかは著しく低下しそうだ。

kksn_ripper.py でキラキラスターナイト パーフェクトブック(同人誌版)と 8BIT MUSIC POWER サウンドブックのROMイメージ抽出

表題の通り、以下書籍の付録CD-ROMに収録されている
VirtuaNES組み込み実行ファイルからROMイメージ抽出するためのもの。
同様のROMイメージが既に同梱されているから、そもそも抜き出す必要は無いんだけどね。

尚、抽出ツールは別途 id:eagle0wl さんの所から入手しているものとする。

キラキラスターナイトDXパーフェクトブックを買った&ROMイメージ抽出した
http://eagle0wl.hatenadiary.jp/entry/2017/05/01/045856

この Python ソースによれば、どうやらバイナリを切り出し後、
LZSS アルゴリズムの展開を経て ROM イメージを吐き出していることが解る。
VirtuaNES組み込み作品では、ミスタースプラッシュ!だけが無圧縮だったようだ…。


・キラキラスターナイト パーフェクトブック (同人誌) 付録 CD-ROM に収録の、
StarNight.exe から StarNight.nes を抽出出来るようにする。

kksn_ripper.py

22行目に下記1行を追加

rip_status_table.append({'md5_hash': u'c2f4ea91d22996019741a553e350c791', 'offset': 0x0006A294, 'size': 0x00027B7E}) # StarNight.exe


・8BIT MUSIC POWER サウンドブック 付録ディスクに収録の、
8BIT MUSIC POWER.exe から 8BIT MUSIC POWER.nes を抽出出来るようにする。

kksn_ripper.py

22行目に下記1行を追加

rip_status_table.append({'md5_hash': u'3fdfb465b8de155208e4cf4c86001b6b', 'offset': 0x00069074, 'size': 0x000401E2}) # 8BIT MUSIC POWER.exe

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

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

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

お仕事スクリプトで、VBScriptのみによるLZH圧縮という
要望が出てきたので調査、対応してみた。
PCにはMS OfficeとLHUT32というアーカイバが入っている前提。

VBVBAだと割かし実装例が出て来るのだけど、
やはりというか、Declareステートメントの無いVBS環境で
わざわざ動かそうってチャレンジャーは見当たらなかった。
解凍だけならVista以降OS標準で行けるんだが。

利用するDLLはUNLHA32.DLLで用いるのはUnlhaという関数。

UNLHA32.DLL

int WINAPI Unlha(const HWND _hwnd, LPCSTR _szCmdLine,
        LPSTR _szOutput, const DWORD _dwSize)

この関数を、他サイトで見たVBAの実装例を参考に、
作成したラッパー関数が以下。

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

VBSからのDLL呼び出しにはExcel CALL関数を利用。
他にSFC miniやDynacallを使ったDLL利用例も見たが
追加インストール無しって条件だと、
これ以外で選択の余地は無かった。

Sub Test()
    If ExecUnlha("a c:\work\test.lzh c:\work\test.txt") = False Then
        MsgBox "ExecUnlha error!"
    End If
End Sub

ちょっと悩んだのは引数タイプのところ。
第3引数で使われるバッファ用バイト配列の指定方法だが、
結論としては"JJCFJ"とすることで、実行時エラー無くLZH圧縮を行うことが出来た。

どうやらCALL関数にて参照先の変更を伴う変数を指定する場合、
データ型をFまたはGと指定し、CALL文上では0とすることで、
予め用意されている256バイト領域が割り当てられるようだった。

解り辛い…!というのがこの引数タイプの感想。
そもそもVBS縛りってのが茨の道な気がしないでもないが。

敢てExecuteExcel4Macroで頑張ってみたいなら
下記リンク先を読めば理解が深まるかも知れない。


CALL 関数と REGISTER 関数の使い方 - Office サポート
https://support.office.com/ja-jp/article/CALL-%E9%96%A2%E6%95%B0%E3%81%A8-REGISTER-%E9%96%A2%E6%95%B0%E3%81%AE%E4%BD%BF%E3%81%84%E6%96%B9-06fa83c1-2869-4a89-b665-7e63d188307f

VBScriptAPI 呼び出し ( ソフトウェア ) - 特になし - Yahoo!ブログ
https://blogs.yahoo.co.jp/nobuyuki_tsukasa/5364628.html

VBScript内でdll(参照渡しの引数含む)を利用したいと考えています... - Yahoo!知恵袋
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1387232963

CUBIC STYLEさん新作GBAのお手伝いとか。

もう今週末からコミックマーケット92なんだけども。
CUBIC STYLEさんで頒布予定のGBA新作で少しだけお手伝いをした。

cubic-style.jp

コーディングじゃなくデバッグ要員として。
エミュや実機検証はタクトさん本人が
開発と並行で随時していたので、
自分は主にレトロフリークでの動作検証をば。

粗方のバグや不具合も取れたという事で、
既にプレス業者に入稿済みだそうな。

この「巫女ぱら」という作品自体は
初出2005年の結構前に出されたタイトルであり、
今回そのリファイン版と言うべきものではあるが。

フルボイス化が成されたり、画面効果が増強されたり、
細かい作り込みや、パッケージが一新された等、
かなり本気で取り組まれている様子。

もし気になるようであれば当日サークルスペースに足を運んで、
見て貰えると宜しいかも知れない。

コミックマーケット92
1日目(金曜日) 東地区 す-42b
CUBIC STYLE

また、別枠ではあるが巫女ぱらのボイス集が
音声を担当された夢前黎様より DLSite.com にて
同日販売開始される模様。
こちらも併せてチェックするとより良いかと。

『巫女ぱら』ボイス集(CV:夢前黎) - Re:I

それと手前味噌で申し訳ないが。
巫女ぱら繋がりということで。。

先日 Pebble 用ウォッチフェイスをジェネレータで作ってみたので、
持ってる人は気が向いたときにでも使ってくれると嬉しいかも。

※ダウンロードはこちらから

Googleドライブにある画像の直リンクをクリップボードにコピーする

前回の、Googleドライブにある画像の直リンク取得だが、
使用回数重ねるうちに思ったのは、いちいちダイアログからコピーするのが
億劫だってこと。

修正自体はリザルト先を入力ダイアログからクリップボード
変えるだけだし一先ず直してみる。
とは言え、これで使い易くなるのかどうかピンと来ないんだけども…。

尚、VBSでクリップボードへのコピーはここを参考にした。

clipコマンドを利用してクリップボードに文字列をコピーするVBScript | 初心者備忘録

動作はclipコマンドを使い実現しているので、
扱う文字列にコマンドプロンプトのエスケープ文字「 "|<>&」が
入り込まないことが約束されている場合のみ取り入れると良さ気。

仮にエスケープ文字を含む文字列をクリップボードにコピーしたいなら、
InternetExplorerオブジェクトを使ったこちらの解説が役立つだろう
(ソース見ると分かるが、力技なアプローチ。)。

クリップボードに文字列をコピーする | 初心者備忘録


●操作手順

1.Googleドライブにある画像を右クリック
2.「共有可能なリンクを取得」から表示されるリンクを選択してCtrl+Cでコピー
3.VBSを実行して直リンクをクリップボードへセット
4.クリップボードにコピーされた直リンクを貼り付ける等して使用


GoogleDriveCreatePermalink.vbs

Option Explicit

Const TITLE = "Googleドライブ画像、直リンク生成"
Const VERSION = "Ver1.10"
Const RELEASE = #2017/04/30#
Const AUTHOR = "REGEKATSU"

'元URL
Const SEARCH_TEXT = "https://drive.google.com/open?id="
'加工URL
Const REPLACE_TEXT = "https://drive.google.com/uc?id="
'完了メッセージ表示時間(秒)
Const WAIT_TIME = 5

Dim clipText
Dim putText

'クリップボードのテキストデータを確認する
clipText = GetClipboardText()

'クリップボードが空なら終了する
If IsNull(clipText) Then
    WScript.Echo "貼り付けるデータがありません。" & vbCrLf & _
        "とりあえず、何かコピーしてください。。。"
    WScript.Quit
    
'クリップボードに共有リンクが含まれていなければ終了する
ElseIf InStr(clipText, SEARCH_TEXT) <= 0 Then
    WScript.Echo "貼り付けるデータが正しくありません。" & vbCrLf & _
        "共有可能なリンクを取得からコピーしてください。。。"
    WScript.Quit
    
End If

'Googleドライブ内画像の共有可能なリンクから直リンクを生成する
putText = Replace(clipText, SEARCH_TEXT, REPLACE_TEXT)

'クリップボードへテキストデータをセットする
SetClipboardText putText

'完了メッセージを一定時間表示する
CreateObject("WScript.Shell").Run _
    "cmd /c echo " & TITLE & " " & VERSION & " & " & _
    "echo 共有可能なリンクから直リンクを生成しました。 & " & _
    "echo 直リンク: " & putText & " & " & _
    "echo; & " & _
    "echo ※この画面は " & WAIT_TIME & " 秒後に閉じます... & " & _
    "ping -n " & WAIT_TIME & " localhost > nul", 1

WScript.Quit


'サブルーチン

'クリップボードのテキストデータを取得する。なければNullを返す。
Function GetClipboardText()
    Dim objHTML
    Set objHTML = CreateObject("htmlfile")
    GetClipboardText = Trim(objHTML.ParentWindow.ClipboardData.GetData("text"))
    Set objHTML = Nothing
End Function

'クリップボードへテキストデータをセットする。
Sub SetClipboardText(ByVal str)
    Dim cmd
    cmd = "cmd /c ""echo " & str & "| clip"""
    CreateObject("WScript.Shell").Run cmd, 0, True
End Sub