From 35866cfb84ecb9657798a219f0572c97d9424c39 Mon Sep 17 00:00:00 2001 From: Xavier Rey-Robert Date: Thu, 3 May 2018 15:47:57 +0200 Subject: [PATCH] first commit --- bin/raspberrypi/rascsi.tar.gz | Bin 0 -> 376194 bytes bin/x68k/RASDRV.SYS | Bin 0 -> 6860 bytes bin/x68k/RASETHER.SYS | Bin 0 -> 14306 bytes doc/converter.txt | 158 + doc/fullspec.png | Bin 0 -> 74881 bytes doc/initiator.png | Bin 0 -> 77047 bytes doc/pinassign.png | Bin 0 -> 343153 bytes doc/rascsi.txt | 315 + doc/target.png | Bin 0 -> 74077 bytes doc/x68k.txt | 109 + src/raspberrypi/Makefile | 51 + src/raspberrypi/cfilesystem.cpp | 4228 ++++++++++ src/raspberrypi/cfilesystem.h | 1157 +++ src/raspberrypi/cqueue.h | 68 + src/raspberrypi/ctapdriver.cpp | 209 + src/raspberrypi/ctapdriver.h | 53 + src/raspberrypi/disk.cpp | 9160 ++++++++++++++++++++++ src/raspberrypi/disk.h | 1108 +++ src/raspberrypi/fileio.cpp | 367 + src/raspberrypi/fileio.h | 83 + src/raspberrypi/filepath.cpp | 273 + src/raspberrypi/filepath.h | 81 + src/raspberrypi/gpiobus.cpp | 1192 +++ src/raspberrypi/gpiobus.h | 479 ++ src/raspberrypi/kernelmodule/Makefile | 9 + src/raspberrypi/kernelmodule/rascsidrv.c | 1122 +++ src/raspberrypi/log.h | 31 + src/raspberrypi/os.h | 145 + src/raspberrypi/rascsi.cpp | 758 ++ src/raspberrypi/rasctl.cpp | 247 + src/raspberrypi/rasdump.cpp | 1006 +++ src/raspberrypi/scsi.cpp | 58 + src/raspberrypi/scsi.h | 128 + src/raspberrypi/xm6.h | 49 + src/x68k/RASDRV/BRIDGE.C | 2414 ++++++ src/x68k/RASDRV/BRIDGE.H | 256 + src/x68k/RASDRV/Makefile | 17 + src/x68k/RASDRV/RASDRV.S | 193 + src/x68k/RASDRV/RASDRV.TXT | 29 + src/x68k/RASETHER/Makefile | 33 + src/x68k/RASETHER/RASETHER.DOC | 42 + src/x68k/RASETHER/asmsub.s | 22 + src/x68k/RASETHER/main.c | 282 + src/x68k/RASETHER/main.h | 81 + src/x68k/RASETHER/re.s | 574 ++ src/x68k/RASETHER/scsictl.c | 537 ++ src/x68k/RASETHER/scsictl.h | 40 + 47 files changed, 27164 insertions(+) create mode 100644 bin/raspberrypi/rascsi.tar.gz create mode 100644 bin/x68k/RASDRV.SYS create mode 100644 bin/x68k/RASETHER.SYS create mode 100644 doc/converter.txt create mode 100644 doc/fullspec.png create mode 100644 doc/initiator.png create mode 100644 doc/pinassign.png create mode 100644 doc/rascsi.txt create mode 100644 doc/target.png create mode 100644 doc/x68k.txt create mode 100644 src/raspberrypi/Makefile create mode 100644 src/raspberrypi/cfilesystem.cpp create mode 100644 src/raspberrypi/cfilesystem.h create mode 100644 src/raspberrypi/cqueue.h create mode 100644 src/raspberrypi/ctapdriver.cpp create mode 100644 src/raspberrypi/ctapdriver.h create mode 100644 src/raspberrypi/disk.cpp create mode 100644 src/raspberrypi/disk.h create mode 100644 src/raspberrypi/fileio.cpp create mode 100644 src/raspberrypi/fileio.h create mode 100644 src/raspberrypi/filepath.cpp create mode 100644 src/raspberrypi/filepath.h create mode 100644 src/raspberrypi/gpiobus.cpp create mode 100644 src/raspberrypi/gpiobus.h create mode 100644 src/raspberrypi/kernelmodule/Makefile create mode 100644 src/raspberrypi/kernelmodule/rascsidrv.c create mode 100644 src/raspberrypi/log.h create mode 100644 src/raspberrypi/os.h create mode 100644 src/raspberrypi/rascsi.cpp create mode 100644 src/raspberrypi/rasctl.cpp create mode 100644 src/raspberrypi/rasdump.cpp create mode 100644 src/raspberrypi/scsi.cpp create mode 100644 src/raspberrypi/scsi.h create mode 100644 src/raspberrypi/xm6.h create mode 100644 src/x68k/RASDRV/BRIDGE.C create mode 100644 src/x68k/RASDRV/BRIDGE.H create mode 100644 src/x68k/RASDRV/Makefile create mode 100644 src/x68k/RASDRV/RASDRV.S create mode 100644 src/x68k/RASDRV/RASDRV.TXT create mode 100644 src/x68k/RASETHER/Makefile create mode 100644 src/x68k/RASETHER/RASETHER.DOC create mode 100644 src/x68k/RASETHER/asmsub.s create mode 100644 src/x68k/RASETHER/main.c create mode 100644 src/x68k/RASETHER/main.h create mode 100644 src/x68k/RASETHER/re.s create mode 100644 src/x68k/RASETHER/scsictl.c create mode 100644 src/x68k/RASETHER/scsictl.h diff --git a/bin/raspberrypi/rascsi.tar.gz b/bin/raspberrypi/rascsi.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..61b0b19ef6b8c812ecb83911ecfa6a3c3625245d GIT binary patch literal 376194 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
;LpnpJ4*`Y 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 literal 0 HcmV?d00001 diff --git a/bin/x68k/RASETHER.SYS b/bin/x68k/RASETHER.SYS new file mode 100644 index 0000000000000000000000000000000000000000..9e5fd2dedaae5d3fb6aa12abb86a1de5a0f46032 GIT binary patch literal 14306 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 Izx(h10+Q#gS^xk5 literal 0 HcmV?d00001 diff --git a/doc/converter.txt b/doc/converter.txt new file mode 100644 index 00000000..b9b2fe42 --- /dev/null +++ b/doc/converter.txt @@ -0,0 +1,158 @@ +------------------------------------------------------------------------------ + + SCSI Target Emulator RaSCSI (*^..^*) + version 1.33 for Raspberry Pi + + Powered by XM6 TypeG Technology. + Copyright (C) 2016-2018 GIMONS + +------------------------------------------------------------------------------ + +□変換基板の必要性について + SCSIはTTLレベルで5Vを220Ωと330Ωで分圧(パッシブターミネータの場合)する + ことで各信号線に3V弱の電圧がかかった状態が定常状態(信号的にはネゲート)に + なっています。 + + イニシエータ側もしくはターゲット側が信号をアサートする(=0V)にしようと + すると両端のターミネータから合わせて5000÷220×2=45mAの電流が流れることに + なります(X68000のSCSIコントローラであるMB89352のデータシートを見ればシンク + 電流としてIol48mAとなっています)。 + + RPIのGPIOはこのような大きなシンク電流は吸収できません。電気的に安全な接続 + を行うためには汎用ロジックIC等で変換基板を作る必要があります。汎用ロジック + ICで48mAものシンク電流に耐えるのは74LS06とか07といったオープンコレクタで + ハイパワータイプのものを使用します。 + + 作者は74HC541×3,74HC126×1,74HC04×1で基本的なSCSIの方向制御を行い更に + 74LS07×3を使ってバスをドライブする回路を組んでみたところ問題なく動作する + ことを確認しました。 + + 他にも74LS641の派生版である74LS641-1を使用すると回路はシンプルに構成できる + でしょう。ノーマル品と違ってシンク電流が48mA対応なので74LS07を使用する必要 + はありません。しかし入手性はそれほど良くありません。 + +□変換基板の回路図案 + 同じフォルダに回路図案を入れています。 + + ・target.png + SCSIのターゲットモードを使用するための変換基板回路図です。基本機能である + HDDやMOのエミュレーションを行うのであればこの回路図相当の物を作れば良い + でしょう。使用するGPIOピンも最も少ない構成になります。 + + ピンアサインを変更しなければRaSCSIのstandardディレクトリに含まれる + バイナリを使用することが可能です。 + + ・initiator.png + SCSIのターゲットモードに加えイニシエータモードを使用するための変換基板 + 回路図です。基本機能に加えてRPIがイニシエータとなって物理HDDにコマンド + を発行することが可能になります。モードの制御に追加で一つGPIOピンを消費 + します。このイニシエータモードを使用したサンプルプログラムとしてrasdump + を用意しました。実HDDやMOからイメージファイルにダンプすることができます。 + オプションでリストア機能も使用できます。 + + ピンアサインのカスタマイズでPIN_INDに標準では7を設定してコンパイルする + 必要があります。ピンアサインのカスタマイズを参照してください。 + + ・fullspec.png + SCSIのターゲットモード、イニシエータモードに加えてSCSIの通信をモニター + することができる変換基板回路図です。SCSIプロトコロルを解析する等の特殊 + 要件がある場合はこの回路が最適です。全ての74LS641-1の方向制御をRaSCSI + から行いますのでGPIOピンを三つ余分に使用してしまいます。SCSIの開発に + 興味があればこの回路を組んでみてはどうでしょうか。特徴としてGPIOピン + を余分に使用する代わりに上のイニシエータモードが使用できる基板と比較 + して74LS86が必要にならないため基板がシンプルになるという恩恵があります。 + + ピンアサインのカスタマイズで、PIN_TAD,PIN_IND,PIN_DTDにそれぞれ標準 + では6,7,8を設定してコンパイルする必要があります。ピンアサインの + カスタマイズを参照してください。 + +□既存のものを手に入れる方法 + 最近では主にTwitter界隈を通じてRaSCSI用の変換基板を作成していただいて + いる方々がいらっしゃいます。 + + また秋葉原で委託販売されてます。 + + 家電のKENCHAN 同人ハード(キット)のページ等です。 + http://www.kadenken.com/shopbrand/ct76/" + + 現在のところ市販されているものとして + + ・BELさん開発のあいぼむ版 + ・tomcatさん開発のGAMERnium版 + + があります。 + +□ピンアサインのカスタマイズ + GPIOの信号制御論理やピンアサインはgpiobus.hとrascsidrv.cに定義があります。 + 定義が分かれているのはrascsidrv.cだけGPLなので敢えて分離しています。 + 御察し下さい。 + + カスタマイズ例としてgpiobus.hとrascsidrv.cに下記の二つの変換基板用定義例を + 用意しました。配布物の中にはコンパイル済みバイナリも含まれています。 + + ・BELさん開発のあいぼむ版 + ・tomcatさん開発のGAMERnium版 + +□カスタマイズ方法 + ・RaSCSI起動時のメッセージです。 + CONNECT_DESC + + ・信号制御モードを選択します。 + SIGNAL_CONTROL_MODE + + 0:SCSI論理仕様 + 直結またはHPに公開した74LS641-1等を使用する変換基板 + アーサート:0V + ネゲート :オープンコレクタ出力(バスから切り離す) + + 1:負論理仕様(負論理->SCSI論理への変換基板を使用する場合) + 現時点でこの仕様による変換基板は存在しません + アーサート:0V -> (CONVERT) -> 0V + ネゲート :3.3V -> (CONVERT) -> オープンコレクタ出力 + + 2:正論理仕様(正論理->SCSI論理への変換基板を使用する場合) + RaSCSI Adapter Rev.C @132sync等 + + アーサート:3.3V -> (CONVERT) -> 0V + ネゲート :0V -> (CONVERT) -> オープンコレクタ出力 + + ・制御信号ピンアサイン + PIN_ACT:SCSIコマンドを処理中の状態を示す信号のピン番号。 + PIN_ENB:起動から終了の間の有効信号を示す信号のピン番号。 + PIN_TAD:ターゲット信号(BSY,IO,CD,MSG,REG)の入出力方向を示す信号のピン番号。 + PIN_IND:イニシーエータ信号(SEL,ATN,RST,ACK)の入出力方向を示す信号のピン番号。 + PIN_DTD:データ信号(DT0...DT7,DP)の入出力方向を示す信号のピン番号。 + + ・制御信号出力論理 + 0V:FALSE 3.3V:TRUEで指定します。 + + ACT_ON:PIN_ACT信号の論理です。 + ENB_ON:PIN_ENB信号の論理です。 + TAD_IN:PIN_TAD入力方向時の論理です。 + IND_IN:PIN_ENB入力方向時の論理です。 + DTD_IN:PIN_ENB入力方向時の論理です。 + + ・SCSI信号ピンアサイン + PIN_DT0〜PIN_SEL:それぞれSCSI信号のピン番号です。 + +□コンパイル方法 + + ・実行ファイル(rascsi,rasctl) + gpiobus.hを修正 + make clean + make + + ・カーネルドライバ(rascsidrv.ko) + @OS最新化(必要あれば) + sudo apt-get update + sudo apt-get upgrade + sudo reboot + + Aカーネルヘッダー取得(必要あれば) + sudo apt-get install raspberrypi-kernel-headers + + Bコンパイル + cd kernelmodule + rascsidrv.cの修正 + make +[EOF] diff --git a/doc/fullspec.png b/doc/fullspec.png new file mode 100644 index 0000000000000000000000000000000000000000..47692e59339abc77349c9338063b20a80d75de7a GIT binary patch literal 74881 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Ⓢ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�AgEvMgwc2EMU;2n7AU6 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:czsm1TSwERR|@>SjkEl_IrCqOkf50jwp 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
!5rwj>_j>_g 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ïHWqI7S(aod-HH$%@P(ehvuMbv9xWseHq$` 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%0A>I$3m)Pki{I* zV=!yk7=l~G%LNpc@rxvfl;3*o3hX2W*rcIR%Bqqb-BtyjZ%yk_kln3x8m$H|?VqCQ>>fHTC4g!Ou5|<}NFfZip zBM1<|adC0v-|^}^nPXATS*ARM1OHH)Ddf3LO(bi}YI3AHTnQV(y1E=w;`*$-+>G=m zjy=gR?lGPq*-9I%h@&@O^{_&gY@4zTpM}B zgk&11mwSOg`T5@j4JML3JoY$RpIAD$_E#y=7byNAi*7*8))0XcucqRXk2T47lO=nL zqwGwVXVy`Ze0ULoXTJxVd)=AG#;vc{Ag3YgkbtutkWboRIST{(ORMX0*(gSgnHa-{ zKMtCYPYg~9#A-wW>LfMdenFEEVKJWJcwgga=p z0YhOr1Br3`N3p6a@=jjxnU1%|fZ91p>LDjkyqgP8BaY7{PrA@}gY7fKD_?q81eff4 z!VDpPiEtTLjV=}FzmAP`Gnc`Zyn0zC{5IruJsZzplDQSzFbKT)q*OL%5)&`Tg*gMn zo(3wE_|gg3J|<}Y2rHNNm4GZV@Nhf=$*78&=@LXrYRHa}C8clI_u4C}?aEl#VYY>n z=%IagB$F5&Bq5>9)g2A+u-<6{QnRwa2A@+_3kbqE+3o^T8Bq`)f>uR8e-_1U!i3+- zp(-rgoG_5jH6>|SdE$0-90SLkpw|+vro6dOg%hRiU(+d1S7&cu9=qb6-W~*(GHWX{ z2iI4=Q&k=^>BdFVBiv~aCKisi^8j0`a13PsZ*&pJ{|BL5yhok+Ee&~sN?Xvu<0js7avzs-zf9YxY2kxYhy*UkGE^f1M z7sm6+lKsuvzt19`3d=gI?@#%ALwvv@R_k%<_dl?RKQG|)Gi`syKRe-V2MmR3kYxf# zy69C+uxzFLN!raP380W$?qdlGutcB#FzQPJS=?X<=^QRpAA3HA9C z(U31am;c)vC%gWpQc?A7CipX06DckAo1i-({C<~Qnwer5NBxpMQc6Ag^vT3laIcId z>P=j2IW_SHBW&9biib?A>P)0zUH#oGGH!yoZ~Z_c2#`gh2UodZJ*dHzu)tVLk`M=-)%UwCMH0!u(ggn6t#q-4crV&ZA$@6>92VhNHac7nf|JTQjfg z-kCod8wsO;pe4XdQRM#0voHsx`}Z?}GC{EM;>N|$C>ME*w@dE}`XRL}s*=0zRndT|!1 zfhNSpWZd(&iAEtkgw$RvtZgt2jaVGg=AB<)L^NF6*2Y<|vbg#B*g*uERcU4fZFc-= zb9q@wV_5s-7ej3dH7ejLDZDA{Kx|N!5Z~oI zZw(j<(i4N+Pl4|s$eXCi&v=RY4>8KgSG>^xJ28)-dL~Kpjv*qQNT~c(hjAxSE?|$! zdL#z#KJDQCPAK?NaFKOa<0FbWNbOpdB!w&};r-nY&78ox%b|g}` z4NF4U34h_`_Dekr&SZMAy+mYTnxt@;gtVm5HKN??SHbkAFg+2TSPJx#AQIW<}*CC@s;` z5ixo{ps)N6C;`1?hPb@Ie2X7E!1o_&(cf1AgOz@5>cT2Z#Rk13pUm-_ngwW`F-4m3Yfgnc=X65Hm<}kNO#3Y)W=!yX_Y&x5}>c6lK{st zzthV-!c&P97S=^Se+e+lc@CHf6RK%5sVW$-zI2@Ycs%6rbYddADDnwG#zKcf{QPeb zO+CQbZqn5laGdY?ui?23o--AG&cd1^EUnGNFp=Hwg{1ifmRRL(-&|VcpWH#TI-XJx zN&b9KjP?0R!ehv$CDc`19MUeD0o4jekG3*PF9s!1qKFxPy$Je3&0nqba_h*wPsAEA zaq$;6H*>$T@Zm2RL#Mv=7Tf8Xq6-h1Zikw57;;5Cp3q=(JI)e4SkxIe#rX<30%Ns{17O(s_*3o{tmfTL%%3`^u z`t4r)jiWJoV2p=JgF^NeCqP9(eeEQYaTUn8l3OPrtujmgqqGsS+%XU+G4 zQy&A;hXLoL6ZZ3=sS4jlM1(m;3bB2KzgJ#NVR#Mdulazfz8NG$L3YKBIr1v}B)6&o z8FK=zdC4n{?iQEGyI9^SIYHCsWjb%|H*A#F5VyVTKcA_L@!T`;n7#P9d{Rb!$O`O& zVa9Tgjb|&XtIs>ahz8bDtUml*I82s(b$xj@NsP^1e@36TT4e8C&pQ8IO@mWj@2PY4 z!KuqbGe-@%?Tsag#cEM?2JXDq_J;0u8`Ft=s zkqt6s0GJZMjqH;(Z3|j7As(U4pRa9meKZeCYC!9v-=_JR4OGcO~`f@|klsK0Rch+ZOqC9MbsN;ia;c660OF z!YSoHgxhTp(ll9ZY9{dOVgi$nn0L znwK#RSvYZLnM((Mz$!fYgD7!<=xxwL5nLR?VK780dtI`7=)nTmBVp{6Hso~~wKl>J zO?taVpV)y2V*d1It)*3Mw8Q{WNzl+p_4lxXFSt+L-?8wpMzlbiS?{)?ETGt&0MQ6k zg#ra+5y1>ozIcpS)eL4Lvkea-1tnu5_Tq@BB&(34Y;A`7#7vc`= zs?7D9{zKI64objcl}5Qc3~f0?P^6y~q*6Fm=Ho`Z%3~67+J=uH*i%E7$&rzf^9zem ze&l@E*}Jz)D#L}()TY2+{%^;Pi;s_wAO!IaYk{M910e7#8M3;(g>zpA!qrbI{`3!u zoCqJ@_|*cPDgkkW(a?OZSY}o$p`6(M8Qb)>2Na^1Z^~9M8@+OBi!2fb38>*&0k;6- zYn*%OKS9kcdDRq)|G}1+envAv?9eN?@`ZxpWBAqi8+j8Y{CnHPn=V=oy3k^}-CfuA zMOJ|+`Pj zfRRQeLqn>^|MdfqW$Bl|Gu+~@1qc%vtqNZ10r0GkIiwVxZ`EQ+eG74{8xLJSr>nRk zGj4o;vv3{Wr5gtZs~5?%UL2YIVMiY_}vqO`q~Pb%lOuO-M;ZbhtB#0!c#us=VVRxBLug4ULAF0Kp=0g8 zOqepzb!4QcClC9i#V|-d?&W+x9ClyB+Kg%}XWyr@&>fKLSBW3OrL#&lY*ER7AS@B?`@F z(uteKb`Se5Xg6LRuk-a3w(D62P$q4!MM=9mL%LgC`z$=>wP4ZUyQL+2OwOAC@j6aI z)HcQ9w^Fm`>nl&8_19BnGSm{Y6VDY^pXaR=VViyv3ZyX@IV+PiT{ZDLKVnmjrH{(7 z=w>tTeFRql!$$){#CO-%X+~P*IzvHm;;s@V3w7CaS#*<=4E8tuC4)DrE1Wxa+Q6>EQ5i4(nik)$xJnP;<<{x04sw?XuXHm z<*5c3-;-v9J`<`uaV6x>lZ=vVWLBBg#PhZB8@x?7{;d)ttmhdqHgsp4)tYK zSLq@EFr04M>OurY4sDB6Elnuv&BEwaaQFa_8PH^@=76~{L{~KiM znuJ5jii(gu(EA3lZKaW4rD14Z2N7^;#AY|>YTUAi1DSu2e3cIvdp43jI==AKw6%{-E3TPtqC7cUq1SC#kOYQdgih98lxBp4)r*>)a4&%qt1y)g37uAPQ_7r%vMVu;yl6kW1%kp;VN#9pG?A zL!H4F*E)xnLV;klO7>si-V;IU{kwk}Wq8I$y@K7GwJ349CA=&+1t zN@TQ$xq~$*`OU_5VJf%L~%448Vmn2=AXGyx>!9+?`3&EE4CE zIjxTa4@v(J1+=v+TE8Ecjb~s%k_&mj@j$I=rSj)iQbm6veOmXbEP+b-2eGco?%9-c z`2T`qA6AiN#YuOIc#_O*3zT!GaqkQfewgILh7>?A_x(Xi8dDb_;M+kraUo?l?KkjE zKXm%yXXitRstvfN{*dllu9HcJJhT}o~npy6SP$#najXb6ZsSUwxmx)0;<>H#~Rs?1~)PGk_V{}Zq zE8|1cNPPGtG8_PI4(}@~Jl*NZd8=0DKP+0*XZo;2V0#$^1?jn54>;Lz`Ot^Rq zVhj|^8o~sTG49_yyP4dm2Ri@l(HhFBw9Mu?0YBy=ty-ON{T|37+dbe$uM-DM?4ydo z>3rvd2M>ZHA`lmeqve+$)#7e*b~DeP&UoTrc}X;R-$X_ZfFz9j{V9CLyWQ=t56s>% z){6bvuo+3*WDb01b0Yg_VJU`Qtx51=0Oucg0DO|>J?p(BJNg&s%}1ALQqx1tmmdpQ z&3Hw#vTXi&PUz3BH6@wa{xb?wTndwJvR~Y`C9*T}pPHdZ?~b5fSZenqXY?ZgwRX8V z9EiX?B9agj^NA6jANn58*$f&fY&QcgHxW^L9i2}ZmvW9Ha%j;`{$!GfqfwR6R@Ubs zgYhJeG5mqhc{o?G)^BqMMPMpAS%$lFOII}etGqU0s)Xbh;5A@Fx`u}w~;vgB&kO}ftFfQVI zN6C>>$O>Z=k+As+?&%M}5+|GI@T*O6#Y!xm^Plge_ER-Xc9Yh>zB!pKpDeT}I~-Yp z5-?awi};(hVF`|rg{xiOW2QM6%1p2K?ooKr^T5i7Ba6 z7M^x`jg-MQ&Xl2LtNRegcS(!4`+)^4CA1+0|J1bp{qVV)##e3~<0r2*aB7`@T}l)! zG~wJ2d7Ja)3lS}?0Z7}&M7zuN_8nU67U$i?qa;$<_a6aIvLcX0+B)|wHxO@7wh3l= zN*rFwtC&!7hqM?xoyytaIGI_!0=wb95wcI27s2I9PF`Lp#Kq|79;7axI)yk-GC=yB z)+0x5FHzC27HdNan@3KBt$fzOe|;v3XyY~}9Sr35KGbM8M}PS}HkMzhzj~q@Qd#ZrzB_uf%zJ1+E?5C?Te&2yHU;x&Q0LD+?N>-id9@(T2^2-B?fCJUm{Y0=$IcQ zWHuqGXgg8xoDJZ4+pvDuz)JvY;DoixUfHzin@`a%S#UJiy{Ab2RD{`6rn8H zC4Bb`0VgCl3<~9Ee)obSC-)Yi2KN)qOd-bUSuu;AQU595eUev=w|2Hf>k=&zbm#ya-3nPF*eR|gJIfU8)$!^h zj_l$R1z>6vF5nWBD&)jA6zED&+ZXjn891>rxKr}8Aqbr2mVy=CA4av0^bIxTt8rD} z!E&7PewXduFRZND1#J1Ed7BE##J;l_!sV_$*b>L0YzP z|ISM~yHV#-d=JmGM?W5gyW(P#>K@jNle+j~K=I|jB#LYmnT_Ew$R3OC?NwJ+Q>&Z> zf#OB_wDh+gG@RM4Sesx?J%;m{^EbZyq0Asf6=qah^vI|%=Hdi&I+X~{miDJG zmiwN_*Oa5I6Lmofjf7K0-&X6P~zE=aP9>YF-V$6LG zBcWTu(RPv&uTO33Q>CssKBp0pWs*9!Wb++o3+3=?|FIBei3wST{gX49-!VUA0|xj; zs1+5VVAJSzYA8#z)_2ke$yx~Z4Ps%1)LPkKnJRo>LlB51s#ey=++iq6Lgy|pQ-!&f z3Fv^w8l>IKja>Bt80juk+??J%cAGE_fTha^lOA{&Ta;>+Japhk>@fIT3ZU z4?%xHNz`ttd4$Hp_T4=T^=Os#yl<%wN=Q|;-bXG@c}@9x$uG}*&+ScF z7r>j7`1!?kM(=GPz0sVq6Dx!vPw#;L%sus55CG#tmIDv zJRVRi-OSw)fsx?KC`PNH%wRjQ((IZqvEWHx=cj($SQ-IEf`jWPdAA>L!O!K1CI#ls zVPAj0QbKyPQ7|zljgS>GGAatx^|oy$n&xK$SiThHVUR-raZ&B2SpBO}+4OHMKT~Z{ zWp?vT z5R!p^Da}vvgu8not=di?z?f*Nzu*e z$e%qZ^yKIj*uX_?h^?_mS#vPWm3E^RM96@au(+YMrS@r1iS}1}<*j!Z$h-Kp^49_p zN5l>ip?p*gS1O&A(VwOKE=|yu4gPQSNP`b9xEc_Uk37Duqim{00)NRW1E_9~5%yJl1)5oRfMH7gfl_4rV~ZefC%I1I~U^ zU!HH2@ %{sL%fzi5C@K>V@+@EiO(*=?TLQNFPwj&o#LVv!pvuM_;)y_hjDI#W} zEnr&X-$}jy6=JiYm)w$0RvxLQVwzJ4`336921n zuT`AQ-)qEA-2Cf&rdUN;k)Ybv*`qeNvXGX+B-(uKbKEF7dHj1R6!}^nR<4hhi8Xc? z@k$jPjRMz0Ip#&UOV{lrEb+bXp@W2P0@(NkpQ^;i;pD=2NS7QU5PYys+*CH%USxTY z6&zDcO6`cJP0grJ`bR`8{`LDDo`IMZuq{~sg$xXJENxqbvfjV$9ZC(m0M|pqaxHAF zdrwHnwxc+>sV(~Fi}f2FU}Kd+0#@hB&;}(^F>wgKQeu2+V)Rs7NUuPgyk8&xX_zXu zdm3j3H!ME+Ex1-t0LPvd08g))`?$c0c%j?sDW}MkSRM&3Od@-AqUqB$FDw-kh zMV{Fd%a_jy4xjJJ-&bLxGyLl8=GnQQWD6d)$ofEk!tD2mub{qsaw48(w)l&xj)84> zOA6zi!Y$4I9#0Qh|DUc~60x!ArH#v#>oq6!|3V&rl%VLB-c^?URM0oVQj#CKKu{RI z{1DirJY{ZLLMeKhG?HFl5Z zcR!%*pO@fq81n+bz8hsnL!<%?8Ne~M{6?L2Fqw)L24_{b#s z{=|dm4+4}O-O*1D$O!p6}@pDsU9q zPpCkEV}fBfz*N*B}?>Aeemoji9_?n#Z-`83On)%p8wdpnJ`!2%PM)2P(7 zz3tfLI9UxNZ6wU2$MG$WX=H5h_uScTzPM`Lkyoc`c+Lq;o?2wg;Ff%)}!C zudZeE$%}Sc+P;nVAXeGY!{wmkgs>lY0^s5Lg4yGwYJmZsL-2SU)%!<&AXS7oshXqC zXAKv^U;i^swv#t_sk>0`k&aoo;0#ei4PDYvHHhd@v(=>p<;1Z~NrmyrNkqQ)P;@hr zNUWr!p*=G3{g)gB7T!ViY(--20=<`bCT`}(G+67nxZ3RdViZ?D7wJ46vr*?)UEi^m zrstBm9=+kYT3=N>$=3-3t~MPQWJHqUHB?0ZSadLfxzp56ri3eFN5KU*E{tFRtSyQtGNM50|Hlo)<_ z?VYW9JJmF>%@7Rh;V&LD^=}You`ur{oq<>kFacSlaK(=vAVJcJ(6pHc?e4xZw}^)Z zOOrCuVn~8G+foRn{p=CF_6Fod^--#5g?aHqMuxcFPWezyTvkzbGS>385y5cm>gj0VZm40#COAx>VGtB#ki|wNp zL}k*((My{z0L~JKF_^T?hK-FWmI*qMIhycw@yXr5EP7DNHlcD>gITdZK0G6bm-hVn zQOF`{)nowIRNqAo*}+B`hM>yt#P5YWHhiM+k*dpJe} z6BFYT*iJb#Vi!~HS>o7&cYW;KBSP6%lD!BI1=Ttf)Yze|Tm)zM8x#BO==S7GlPS+j z{#T5WnC5VT-RoFhc*4Q%X!zte-)e0HhFizoTyFjA&@Z{0YuaL9{%~Frj(>@DD-V%d zcx#DKV)p}gliQG*8Ua==5i~%|ZuUXapQ5iYYQ+75u0*ab&IsN%xihD1@&wkwXQGR2 z^*~~~C@Hz5T`BtYN);YD28IQC@H*He=4*k&y;7J3yNv6XuH=|vj@;ai_*#2XnDh9c z9lXWUW#igEc(D=QX#!h3wi0iwpv#w`6dIPCubJQOe-UGLWcP!kwXxxf^p#?h7Epk_ z0@*D1RHeT_R6(8h!EKPg4a<2H!6@~rY4@U$4qH6^)3X0|cAa=?`oNF9rtSWlGi~jO zck8=L@Z=o-nbVwA&A~LadlMLnF2PChM+Dc_K*k2^!;+=b~dxB0_ zQ_Ci#WY%RSwWY_bo7qoFZ02?5F5$kKvi&W=b1OD$^*|(@6tbfmrRL=hp8e)%Fjvr@ ztcZgkGmOy2^(KhTkitGsuVoZZUtwU5}4XKv!b& zU)*B7^OLYy_jlWJDl2O{Y}&Bc@A^>#JI*SH} zf57MVf0cWI!H0Gj>TcQE<+ zh(-K>zljO!Z4a`OR`RopzYsiu5$$gM7)@c30`ljTaZzJ&^Y~8p4C;>FIdp zGbN?aKl5w)S@%*gn7SOP1gER#x8 z6S=t3slu{=a$6m|1+-xLC({hh4q_Us;OE38{?7DzcY;gJHo(@J(6Ca5_Z9eBv>!fc z;wqfYydZ;}@cJ!*G%kDcTeGPIH&uf)+9YUaww z3USUBf|T_Lv)Jt!Q^#9#>9xE~?Fsx!ISnF?bbEJoRv7)XsSDjtITmBw)gg0lF z+%6)lB22LgI$GMX3z=)t(XV$E++HZ{W)Adw^S-i&5AzV|C9E zV{W0wBEgP-|L+_1;rnW;4@E03h*+}vapi;=?q!J2_Mn z*Jki9Nu1!X8``pxv)@hztvx4lBlOoN1AKj4;@>gE+6r|qJ)g!guAh!BWS&zTAKb8M zn&~{g8jE%sq=YVV$9!(qq=Go#r-bajAJ?z86%xGo-9D5+DB{3q19Am`aX}k@lZwOY zZ~n9$2^J_ZZEDRd8OolA%xcRXP;|}YDa41gHOTW#9R%R*B zZFpRdMO=btn~$kGCC2FFB2${S>p}D^;V|dgp5sC$7>X$1_+GVgwyJfJ(h}HkeffmU zdN}N+Rde?PV(~a#c-B?Q2?sM9{IkZ`3~BDtv^+YG%Ts!OIZ6uzOl*Pg;8zD8ueIaF zLh+Z>ce38dDqWZ_rnb>Yza+U-^fMnW4=dzONm^3vhO-KfQJV(DF78GzZ9B%QM5!&> zkNQrPJCQzrd$q*r9K((lHm76=Uo@?d$u7EwS5hhQ>!W`>)!#RH zB+z;O8T>SsSQc@S0n)!q4J_yJz ze6HCjXyN7*`s5QT9E0}X>pRo0_7+KYFn(Qaw9wI>)Gy$-ss8LbJ)SOnuC1Pi{{;e< znDODR7(lxBW_KSInpDhNg?~+hvCPkr-{s~TClnNfx58UMj81$q#o$d6N1Voe1zbtG z2hM_9Fh=^R65v<*zdBw=%BJb z|6WlM(UMwAayrACX~Kf#$3HlPjU75IgU94fRA+j;v;CXC2L#%BGmf{|W0L|;t})&M3sMTCNzKk`a9nF!dP!x>~ekb|C%zgE>w zT#kl#g%?`x1Ab8=?YX<#57%;snyxpbYpngvjLI)0flJlP0G~o;6OASUAnZOIK!+@%e6hq7k&QxVZaWjJS$+A}Y5K z&}@5fGV@sa6+Fvb#wRbb+D@&ykReSm$;!dbPDax2#(mVF>*D0o4XX3s+wu@TrR!^D zdcO*%$N|UM*YOE>Ce+9+_8pU4MmcT83_+bY)@EEY#Drj*xB>bsxrrYW#>9x;!zu;5 z21ugQ`N;y>WXsBHLmR`%;VY5?dpQviL@yA_lB5w0Y3xqZ;$V)n+~GvA^VV6L*<$2r zG}jBFA!YsNG!)g8BTrPJGWb-sXO(%zd{DGE6b-`sPg!}p3BSP`?n5KZ($0Rf$OMOP z+IT{r2fKL+IcEXQ?tZA zK)lWhL_k%!wC6P0eqA@qH9oLLOcx3X3C~%;va0v>hIs0{-@#PL6Y`cyr8G|(dMmq8C}z8 zP<**O0y1xO%E-AV?zM$8oAt!WUBWyab(g^j%?rw3CkuaQ@>+NQT*IfPqyhY6As?8+KG}26x>P^Y{Dz{01sgLetU`Eez(+)YTj&XRw=<1JQt`OuB z9M1@RcLclR;Iw(TYfB7lCDx7n?lddQi0hgg|?-n zsfrvY9Hn`XKqd=X1Aw}!; zzCgh+!~Iwhnkc<{osn9FW%kQ2dGxCp$gKyly?Y-M(vluL6RdEnO!!fYIwz*lym!HV zPa?w-Ggw@d{U!hG2H?40IhDu;oUo-7((cn**;!fw3qW%z?`u17ugO)w* zR|w+QA|~DJ4fcdX#o9_!P}IZ>gfuj^?VV5Ywlf(zIT7XVKiHm%K8<{kjgK+FKdiR; zE@BeUWOHAb@yXM`-vsw`^*+V}Uf&vyA~*rjS}KvYv9U4pK={bS1o+e)5mkYM55U)# z{uIy4e4>e#>t1VUVXf0*cQeX)g6YYPNyd@m&987a zc8)UlzXzots8snw1y=Y#qfsmHx}Hgr9P6&D=PScB4s!hJq_(y;-gy~(t`V{0Q7sdn zZ?oC)273;dxf?R5q2b1%4+Q8eKzmmSM#99cET~}K%6i4`^UFpvRg#!Vwxp~^#F}H| zI>?knb)S{wynQwck6Mh|%X^xoHV`@Ckfs1Mk$rog1ILz-bmOo}a6(4E=sXg88vf26 z^-PvWi)A{>`0nR#*i7rlR2#lqWPiF(XW4_aA(}#M#Oj2w z>LWxNk$W{)Ov=0!^P{j}asKCn%d?)8UL(;EkvC~6Vt9qMMJh~?-6qO@8Vp_xLtmO% z{)^kJGMq4435h@Bfh3QGE?9W(QfM~h2?Dyq*I zsCY6$BF_oH?_PIBtDa*7pea;A(R#SwcVu@1TLd3n^QANq^>5pRc2dN`BDT~vjKOB3 zOlShM3=}Pi`)zCt*~SXdud}%~M44g1F+tJF?B~T?%RFZR1_Q0rY`6c^=T#0VW%yqW zNvpj&G@fAucpQU&Xypn4m%mfYeqn=Pr++@inVyT<^jP`OgWLeOa3<7GJ9~5UpeHME zT~K`fAXkEc_?~IgY5R`_cT2 z{Cjg7pU}>Z6f;e8i?+9)4CudqO^xN9HoFt%6M4bJLpY~lm>A=eXpxcQ+tI0vdRP)m zBWuM4`WY3oz2UDv#hTxgD@`@naf{lUhVZr2#f78f+B0U8xOnd=tNh(dmcX*`2ZYL; zNeRR^-M(Zo6K@nJflFcg!-1&}c)oZV!H*rF4h~*kj{#2fXoWXd36JXd;A+pbnIY7~ zH$P$UIzNBpaDhngUZtu&xb;{l|EOQ*Lo{~2(%#zm*VPom=E+8DL&>Kn+M z>;JvC2+(N``Oa4>Z?z@;cqrP0$uBF2Ds0}n>Fd+X{rtJN*ao|G`?jKv4k?J|i+JH_23wpyIdF+5qb0Iy2;gHhB7VLyHyKt?Emn6NY?z7_y0YA?wr85 z7wx+io9ms*l7oU+1%gFib_^gc%oggQwk`IVPc@o0c62%HUqtXY_8HtXcE!gOY^s8; z@2ygglPV=lD|to5M?}Nz=i@aT@R4#7Gg&bTkq=@qVL`aFFdmLs!ZFv!E6bVj zPm+US!xW=SOzIR3Y_cOvE|3~^Qr9V-Mfc!;Kc{G>%b$bO*Jg(Mnw72FRcBPgD|-Zo zHA<~T2p%Irrjwm#Z`BSF^rH8`p(8C}fkhX1daDQ!0SyGNZ4cI1Jpagd-cn|jkV#0A zw?5ejpHonZPfZKL#`B9edh-KzwsuPOI9OLWwnF=z{K?BZA<3*+ANdQW%?M#r@^EH8rdSmMoTeM_&HT<-nMi?!RwE6-4@lYI z0|H0Cw%#nRWd(G)1g~DhE?6*4RIv>7`%HbrnWoaoL^Yme!3hcXkjU!Zwe*DdZzEp! zuU6jHPboDsC&>p2X!1F}QDAjf64~l9fz*=Rz6YDKeh9*6#bl7Fv1Ew8lG0n_m$JBJ zK`o-1$Rl%e#mqo4rh?(r=)}j+EjvAzjrpHFF{L)Dbw}VsmpCMe@;E+{x{#h8b+ZMJ zs!Sn=R4Qr^zx|c_!otGtGkeAj?r*k;0^Vo)#>&XZOlSTw3%sJl#l_Wc_7T}YYFR^C zKMS9GK)sHOyzN&;4y?9_ndd7|f1ET744}=v8uGeFtt|dCxmv}_>~Atnt~F2o1{}n! z3OOym)xL$cI9Rx%tf?VOmC}O}5V$kP!MmeLlPu*nF6imzXsQ;dfZF^wgN2f|uWbK& z{+hm@{ZcV=8m2GX9>H&D1_EYUmTKnoJaNk6N~QXtgzdrc@pN%5a3hQEn9j~S%ZnR3 z_{5V`rl12Fxv%P;jwv2-mh-xBUflYPfxw=WIh;J$oNr}%U%!WVbEu%~NAhd@BS`{F zXwGX^iXRl&xg|&(OPpRV^^dg$Q1OSW>JfV?s#Ri%O5*ASHEIu1*%NV&)hWeUgyv}9 zK$-l0YPMC6Lx)XMEHN33M2qV-aBXX$8YrT(ay(SO@uj5W0vCJSAGIQ*R)p;Jy;Ny8 zw&W7CH(m74EWUyEGf5}WbK*V~3JCuoV13fB`p{ACkXf4Ijyp0@9-)Wgo0^&_C+_`! zOuc1TRPFoyy=NG@h6d^GZV>5^vI(i7ML>pb7#e9ox(z_31f&!gx?3rUp*ux7p6&hp z9mn(c;GHiN*mLdkI@emCRYr%PYcMAQah$(r&SDajli%#&+p5!*eC~N)SH#l^8`?`*flqhur% zsNJcD+aiu)iO_n|x4(hdG>#{LVY1H5)s~w($g;6u*?+)`TBiVtZT?1NHW1fH;Gup= zg6&$GhOv+gyI?`xcnrcBJJ{mEQILy}P%7o(Oj&ll@9EHTqzUEhprC)EJh{s@6Q*|F z!XI)~dg@kzg5i`4)33OWn1zI2DOPTHkOzrJoFGevNop|@B2@3F+6%?R8 zf99K@KP!cV=2`C*er_SK#iL+jjG>3#_UbjWCLdVz-x&wS<`|^zr=@cS#zoAg4Ci6nudrea0sXkR7K5CQagGKNS4kenDIWTta zvKIU?CA*v|{-Pl$Vrg z`07#dZM~d6dq0B{y3{CVTFTRYL(yHC^<#KoPZ6%cMNQPQwY61BmXVMrMMUh0cxeUj zKRNQ*aVDc?K&cb17u1x}dMi@yUOK;278ZQ{s@XGl*4w@A?gP)Rzw&=*fBOwN@!S0N z%M1L{Wn8;@9z?@rqY3=*-Z!6Z32qrreElwUZ^7ARWX%N37pe~DDNK`oN>8WR>cNkd z;>wV47$a=C^@L`makbpu03aFVu6gH;N#niipGlJSeo`oP|D@Z$!khN<8XA$Xi@zZK zf(EQ&ZM|)|1(6q-;`zZuu`~|?mm#xhDGRZ7KFy=t4@FU(tO+Ff@-yxv8(Z#Ov5kti z*M80oxwW%F-VrX2XXpMQ%qyA)lnEP zK!`F^DdE@e#R|z!BETv$A-iGbL^cE?L*F#964}|S@kwhL9gevh`b|PqGU}?fSoRJs}0Y! z%+T!@Fec@i#A3l@3M^6k3Alt*PHX<{4Gv+NZiGuE?wUYutmN+r>%S+&MqfSI?N$ag zhem?nYEk4RQ7mjyp-Kwa#$hO`l4Ao@PH0J~v4#fun3#e( zd(sF0%EZkxc1|b)t5GuzGq0vfHdOQ(&mD{*ar*}0QJa}EiujEoOXsQ}{v=cwk6!g0 zVZqj+D+Qw@X&UB0H^zmaQwRi!&8JPev^3oWnyp->9RJL{cd5)|@P8V>lQYMFKTw8V zovPBUWS^w2JxPPLT!=_aVh{hKej^&7n=MO{-ZxZO*pOfw;;_u0^;hr<*V)G}wbal4 z#+Nu0#3m^7b-!NvW7KjT$YF2SHZn!|IV8w%k9;l}`xAf!Ze0jfFD)FoB!`fA^nG2bPPYWjd zZD9e%z_{Hru<(BG?V)-wsT|vDyEF?sVUa=YCon=7)Zjwb#SsLXI%i2=H9~$^Ybsvd zd?%VAG?}4|-Kz*3{o8z|Lern7=OcuwbKbt4wWbwOg6iv&udJ&*-O9=0gHTXpO{Xda zHo+t$IeUg%s}mPf9>f`aI?X1+49P%Zx>-DzoMS+h7_LbZ5sZ?C6$YqL5RDD>U`4K3 zt<*2ls>26J4bTC0!-fMwH|3-e zdeKjhqKD&DpFXF|xynJja)Dw|n3XvEjSS6VlQ@2cKP3RC+KXAyvhTp2W|2Z4wE!gU zN(OQAORByHo{}LcO(fveW6=ppdK6eLL`{Sy@wz~Ie^Yxd#vDtNpk}snzyadJ-$8XF8=|{Enk=22 zu^AclczFAj^%I~*7osR*abW^Xnp5SwP;k0>T2NL{*93ZkBUK9r-f=(_Ty3C&YvDsa{ZiY|@5RE8VP%Uuc1oBSKdVNOG$mWV%QStCqo>K=J5}#W8+36Wf46mi zzeNX*(LwCb(^#Cglj?m%v>vZRecB@zLCE;3{e0J_C-1sYL^5`CU)0 zBVFFM^!JN8u(yC4TJkVlJ&KKs73Xy(9T7V78dsT?v0n^LowhbI$^{ra_8~x-zy*FS zi=x1Cxk63kzV-Vs$RmB)%$@iSK+|U?o0V;Veta#iH6#TWSza1lYDM|%Ed{{bb}aj3 z#G?#K$~@N@b_rJh$i&5rsh(X+kES)aFa?Dv;Chh(Q7Q}3UbY6@-Rf!OTtq}31$xNO z2(jw@UEz%Mp}pf>1@*@Q5Ru)J*&Z>p6DcwfOgi(1JN9%FgKa`I*Wa7dAU^%` za~qm@;FX&x8>_Ua5UfL#e6d}kYVqJFtbcY2NB~baLVWbw-eu(4?0qQ4v3@ie@~Sy7 z(~Gjb0`u0Lxd_8@V_-*@}au9782- zR#@V4WeAj^!D+r8r%S9dKS?cNEtZQn2i)}^0I!t{tC30%9L%{6Hyc}CA_mE<#!U!1 zHiX2FnA8lE$zx)wlG4+|h#()UK7$_ZcsNs=x)m)hzH%+BB>~pLK!%D~S;ph;z>#n3 zo~FGk?`!}a1a@9Rq-h9cT=jayBJ%4Ll9#S45%UjCU){Zy!P?mxY~SFu7V+md`#c{W_<>Wav2>skhpgVB9xHc5RGC=dhK2G)ixvzxOq$nV5?qWCi=}uO8L1TFu z*c+N=Y5-<<4b95Cr;l`|YOHZVNf2TphijyR`!b6X{dvXu*~X?rTN3Jb9FSpcA0Iu! z0#YFD=)mVGXdep)H$9?tK?a0Ouf^!V2*I_dw;#xIzufO?_><|9*D4bvS(9 z&GOC0miKXfM0Y6k5%!~u{)icnq@jz!FAp;9^Qd!G%E4KTOXT~ zUW8sH52{<2_H|OFk_@tJad8(G6iuTN5d<^7R|-i>iREO#SE|13VsZIPDPSy_3dq1& zC9rgXoEdI>vipl8Qe%kBC%(SMq4#B_2s5A=?V`%zs3^+NPRdXV@UmEb{LueHlq`$* z81^Bo=cc>}SvzS7oVbaH6=!pr<_s9&OLVuw^Y$i)(6KZm-K&vL&NkN*MeJMEkfyt| zD4NnKQ-CU^2BK-iU=;ia+HC4$B5`O$`(`xj*kdqDO)et;yTp5#0c3xhBYU)9B zZD^BBkTMMM9NP4qg_(a+&>Fb8igkpcS4#xs!?&ue&n8_ID<{`d9w>HwCgvwo0?`d+ z1hN+l$;)q2Q#rd?h<)7x_&#fkNQ{NZLy%7?LpD7canJ5%xtMDFDf?2&E^ZcYm`#V$ z`SKYL<@oSE%WM|pp4*Lt)c$P5JuIB|fmwpBJI^0JF|?+$kF-!_%%I(_e*D6pUIz!` z>uwL;*VeKPZ>6yUF6FS0oXTFBDnuA*?has&Ym^L-ZfeuJ^!PEh+MjN*?S9y}4m_b{ zlBbTchlufSpC4?Es!GJ3IxOg9JC2eJ3qwT|A_FhQXbt4Q6IdEa1;BZibvSr4JKH#$9_p1DD^?>W+q1YssCo;?4xV0mgXvq+l@y?eE*)E@#NN zd`aAE%{VTR1S@wGFUr%S#<(cew#?QBKavV8UT+g?OHNiW<}zx;ZmnUjxf{~-I+72X zyJ2p}UH?4Ux~4|$r3U$$V16PaE+KNKO%?~U)JH(cARBJ{$G%`u8~@&AX{KZ=U(3_z zr9aqb>%#Ad4vO=GV|M-PSOxfK?@*%Ms*+OE99ruoAYbpkeMUK*!8YT>FRC26JB~=XP-6Yo6waz^|znQzZs2{p) zLd%LPRFP%Q^f(?I%l@c)bssY;i*H(gaQy5k zM+oTGk-L|j-QaXJQr(xIKL8BpD^i^985dMT0&W6$AhmcHDgtu_PW=YZ_3#KdHOKx_xRknX7wqFx%KY`gv}Cc&i$q>m0D;^Eu`seKVBaG zl9mSlFWHF{SO*um`95Wk5G<@uarGFm5D-?qDOAzT6NPxjcb;v1p=SfqDVN$DX0Sm!i>6{gBE`Bs z3l}f>=dHe#=GEToo|N@R2@EL${jet=#;?(@hG1w{%M4L>Xdj>O(u|-SZhht;wApQ0 zj_;-8LsNr3KzIFif*dw!_6mJorPHGr6dtdv-8&HSDN|BH(sPOkp{fcd%_kJll;|3E ziCt*Zi&iHbM2ypOXy9sC_KP2`RPlxt1%;o;zyh+RThpZtDOQ{V_obO{j-YpAgI^Z> zZ5V+KJe`h#Lgvz_&8&NYtO?AC%Jyx4>K1H3XC#KkE;xSxI-c+|_=b1dq5I%`-Os2V zc}KPR|J;(S33aUCv;?Q!AhqdV~~bY6vsue#F5Htx`W^=c8&oW{N6<^ zEdq8CFI&(6 zqE6vrRgJ}^SL^3f=2qd`E6OjE!m#eaJiv!QYA=Ynf59XX1SeYmTiT7(=fpuacw^oilnT_xK*=mq{O9FP!-%=@pK8*>-z7`Bk|Dbz1I?^j-bT^Kh)v%H<^x6 zGw>a>-T`{Pqfh7k_fzAP{mu?pA=4yRhuzE-e;YOkz)Bv0!Jp>eyOix0Q}(VumIOXJ zIc@1?Q8~yIU(9v8RlF_L3X;O9{_WI6`fqpi-z&()&&U5e1pl)g8niSk2jTS2@Zn8fAg#QyzFV|AGI3Ep+d$}&bV z>aZByAE%+ED^gmY=5+PO%_a1{ud!CYwn~I#tC+^q5`J>n-41MHcGfAJ`%qjC3RrRY z469&HSolLtSYvjW;}hF!>Y07FtPRYGU1=DX$_4#)vbMvIT! zj@gcg*9=VHcl{k5snWJ9Nq!N#3(Afnj<&>o9VByjNj;BRF$b&T0fJ-wIKmKMHt_Ni z5s`|FEV{4;baeVfkSANe2$PfFsgnr^{z}<}q@|~@>D&>k65CnOK58n^VXDsjh@b2> zCTjnSd`G5{G{Qb{5tB(F~>G5Ar3@5;MbSyRP*Hfc+TBtXnyXQdfE zfo;=oq5HZRpv}x{Lpd=|iXRjdZi;2SI5}ODG=R>j*#j2NR^n0e@4HiiS?+&YjlAus~FT+HxiJ{K?l;X8rHKOVoB zp=vA@C{Vo&*)%E!rx;_q%iiBK|5oAf?(ek1<4P6cclJFc^8S8b@}2Y_b^f+`lJ6}) z#~KiD7qh+ox*!RFmeH<|>_vfYBFmldM+dC=b=7sKsC0_ZwktRpHw!;)5bG=CNu{z< zk~mJHR_B=Kc%|DP1`fLjG8irkpJW^$6B)1UcC@Cfr%9#Fca&79^_CkjNQo%Rg|LOH z$Cq238?XVm)2zH1&?#zO6%fiI!!pv&Fm!T(0ec``TjMcxqtKHmz$kwgdkyy>DV0t? zh?`W|^)M*ldRJirf4a4k35*%Hmva93ituEjb}@=|tuA60WycN(y^bzgg14a&q=2zihY?22Y6%2MU2kN=i^TU0B;pyAb3}$~^nI<6|r? z@`Q2_2<|t})?85Rc(aTPXXFl#`7E|#MCa=${gT%}U;mVAn+%Yboo1Kg14ES$R9w}` z%1vn?X9OWgvnPyw+kFq8n)| z$Q?x&)GH=78kYKv4(p)wQws8U%Cfc&RBh;8%&gr}4&9qwYg`kEFYnhg6Y}1huLVq) z4HXZ6H}_{c-Im#p`FA(pz(Xls9jJ!p2Il(R1sB`$Cp*(&6`*(Wn<9-FHpT!p{#DDc zqS=%S%&L5N_>^*>s<+Ixd)Msvasv#vQ!8E-jO|&UompEu&BL2$=(Yp<|d+-~`yb~pPe{`2-RUrC(SEAE2)();bu8z-z46B3~-kaB! zcnQa0hAgDz^ImvFuIevq;qFIWR@0Hj8}br#UmXggwWwL7*zfQLrYvIYaIv5H^6>SO zp?l#lop*JOcXxK<;bcpp9S^}9`15->$j@kqgXM`9g&f=c9_)p2s42a(%*C*EEq9rZiZ7oRJ?{fzqf4S&qNy3*&G&q?tI^Y=t*M0ZF4gMvQ}ZX#3bac0Vh z&qqp9=K1b9($9|`d%%ky>~%d*4C*w`27fc;Q3*SmHcmW#)i|a{x1?xoZ7?JC>J=^<#miY`hcI#}HvENOTgTQ%eM_L^uMER+_bGc4hPc z(`S>OW(B|9ntjP6EGGZ|Xw%8;?RG$!`S1PmSHa=Aa7Ktoe0vn>GMFjJ^}3synhJAM zH#;)*-~|2COF~8>Akav&ilomuVm%Dku4j1IhiEFjbw8y#r1*gaSOFOMzIi^^GbL#B zI`}kKZYYpcr#D%7HquC?rYIBSv=>1%+6c;&XH-0(9%&w9%w-) zr;s*(`#UmTzZbRK^1(sSYeEshhIrQ4r43Yyv-Ep6rZT?MZPHV8_l*lPq+DnXoU+1{ z-;2R>$yE$!m#VGaBvFxC)2kl8-ECdF?E_6Nd|JwSPsmL3=-#Q!B?)lgah>TARdK}v zGE+>vtSbvplMV`^aq<^=xg;_+4F_>_s5!jw1`-@6269C-J{@c>c8yfkY|u5}a!_F) zR~oxKPd`J#TFl_pbDacd!6Q6Wv2a#m=`2HdWE6{(P%>JKyzmhj=*akHA(Yef!_vwD z-waEk#IfYtTctWsPbM!+5qQMw@t_AD{TMdBQ&H3?cKnM9VOxM>C~tjGN{n!HjJX$f z30kbErrZ#uCrrXNjOoK^X_%=`DH*c%e6Qxq+4l_z&7<^?5UE)O8K<>_4qkTG<`p6#i|?Up^f0tx_QSx2 zEOfdZiXZv9v?}t>&k>DhHdMb1$N}c|99!S$2fYZ+kt~q>&bzjhw9ccEtq;43td;0Tf%b5FM^^mA@gqdO9ml;21(6XO< z?$i122LA{cZ$h7+pTnFMJkE@m?)sqG+ElJie!Kj8x+GC1)s^E#f^A2u6tv-rXK0+3 zt9J+W%D*gv|01U6H4~p27q7RqQAXNbDC`RQ2bs%Cbjm2C{oU5ATTm!6PnH1my99S$50*uc4$1Sc|TOc!@MDJZ&`dtU}0>uTlAEs?6*6qTZWE0w&TF zfl(Z6Y;O{$p0XxaFZbF~N)Z2IW#v?^oJawQeoCiY4_6Kc$k>mSwCm}URh;O+VVxm~ zu21=Si9#|=Dw?211C>o@%5aSSHg1<&VCJhq)Kr1tnh}>0)-p z9%5*=7fkZCmY!Evt~LENskv{W)gzExhmvgFG6DOB(!>Q`*M(qopySm>0B1!MDF9oYBZt(oYB z)>ei<+;ywgt<|aL^)#0c7}{FJxgVK6>jdsPcd5-bnk9nH!suN{v(GE$1jhN8edeGc z@Qs@DzT-US7lK2{U%@H6R+;sW)v|%M#NUvITkEbj}!*`6w5?lZUawi~0x1L2m(2wF344D|SH7od5BT?|N z42RMAZ?{=NS=j)*?X-R4QTxM(84rM2G%)M2jRRhCO5NvHHQstJGGP+l?LW(}Fkd?X z18XNa_7>gNRQr(sJ%DH3iZ>zGm#52LDw_Q^fB*9u8p(QUCcJ+?$_QN9Ncn92>?A6z zk?>pYDxCWEg>-x3$E!I!kcYP#Ts}^B5O^otK`LWj)6rPGQ;IQLO}vwG&g1o+R|?Dv zE_^6Z=+p9^YMIOi8R6jxcsBs+N zzYR-LI|b~!l*gli`bi1^?8MwU!XR}`#L(qhD<YJzk2jK`H%w-awUmD%tUvx zWdB#>Ujp46NvzE4Dl!V1h?-*#4z5mCHm*p70&bz`VWqcMNc?*&UBQ6@{cL?+Eea29 z6^+`-Wg;YhsJc5!y&B~}SJU{JyfnTBvu_iRAeB#p)P5CJR)k_c(oZ1hu@COg;9uNT ze!-cIbr)p08bI~L!OMFm&B^lFsPoy)BYqUK7|`9Jsigi*I;4Uj#2ZXPh0V244&I{x zwl_YvzxkoRXxU6F9t0mUm+M{oW8T2E)nocg>(%!o@)-WUN4f}Yi0Pn(zH#RnQ#|Nb@fb#gv$2GdD~x%n2C!yW%~;{&?O%ZZA1)&AL8 zSu=kFZ!acW9zJ=}-kk0gyw|s(4+M#^-*sPuh7PF13U#L5F}LWx|B_%AUaV)*BQi^{ zbi&XM29MGM-7gIC87#u5?E}r?z})Y0@H@eez7>BG?QMiXG(Lh(yXqYI{C-@BavaM^LVZK=ikK~W0k*V(J`K1Dt&&54Vcxwg~${KTh!jB+cjA)y(6Qe536au#+yw+|2cq7{z`=y>6t|U zMlld015ngG`t)yHc38Kk;*_P`ENPpYCxQsoVvOm;fK$d<(tiB5QwIKy*6ME8t0h@e z9^vl!HfS7}L;Xvfez5!?A9FMJ{4FIF9B|tJ<_>!-v|?|%13_5s(=m`qGsD$1s)u>~X-8oyS)~rZSBD265e8@$E)9S#}>C+RG*c4t{4qf~F~M zHkW?_NwrVR4g|nS3{*e(t&alM5UXj#GRPC!1oOKQ)-*#)PWSOoC|Bw{LWJ5#6$7IE zz41`7q?oBUfH;~y%rtdS#YL=@TH*KS6U3%1?(~zd z6d{1*gL`vk@4f@|RP|4a_0({!k6d6z|z>RI@X}j@>Px*lkl^u0g4?|M?Gn2_e%&{edTyPG{84=`w z6N(AUknyGD`!bw-`USN0ktlC|RLQxgpN)8}U7&cm&T5jU|WD+ z#~#p8(bgb{(RLFN`5Br09n0z+mT1rs9Ewo^tEUQ@H^ur#3@plR#Zkh^mxAR2-5(qI zYGd$YK*G5>6eP0^ZAk-CC#El6yj0cG%VjYNV=+px%^(K7eReMaO zr^-CJ8hd7F7zO5cJ!0eb7v6sX^Dy5DX@qPJhzSX;IVHi;UZ1sKkLTt#FJH#IeM@;l z^AVen+Jm;GrZls>$-nwwF{mfFi^qg8w#Y7!o0Y4A%IF1VpF^E(L7eDLcx4F-7==nxy2Nfk z4~~?cnYYgrz+pBYWWS#0zYs@T0D0TlYc!ETEf4WL&lKwfFwG08*HTEa!7iuac$? zW17@j&z-knAL-MqH5Xs)Ci0$2 z%q(8AO^oGCQfwk3GZV72JJ?Ek)Y&7d`t=meG+}wM)?{Kc7es`);7B0e?7HCK zybd5}NYv|+eJ9)}6$l!C#}Cmx)PZEDq+pqu&Cy6bzPPOV`n7dq^gUgH1yjo(qm(aw z+RRt$iVCCivSYk`aHr zqZO`+%fc#{43Uv|1gM*F9=}aP)##G;^ili(_f4vG()D-Up$Nkd;j*j~3k3KO16cFP z2F)s1c(6%!mm}PDas3qmjiy39@|YPb!!C5LK62$xa{d zhjwld_W79r9%*eoPa(31r1{AMyki(+bA7X~?AY_qoqE1icunw+1E|aBGhF5A? zbQIye$)E~T3bn*`#_r+MR(XR?PoPX@FM0awDY&>9g>rM?$g}kQCOQmC(;}=@)`!td z!&)2`?{-AWpeF~zcOkDjD@q7!AUOMvm0KK+c+4+Ps1a;vlGMEkN?e zM_wua`!}R0@B)bM_t9Tjxt4}Un>rT13Egndw{tR~5{hBO%SC}ve zDT-ywfYxJH9toJ#kz@v5wokO;XU#N@Aj}HX<10NpzZp@3KCIteGYmI3d9-3qKtjH3 zA9xFFmk0Bipk2uhB|ih(He(L^X#ms(?HW&#B`Ux4&G}y-77HDGbIz?g3ku5M{F8t0 zv@!VV5I6hpcZYEZDNo?O&?%{Pg9E_0N(=yL?ea z55XLgdmuL2YbFqQ%YstVcZuh1Fb)J!^v5Zp*TKO`Sf3<24eMm`*(QBvjO0TSzEpT7CXB zAbgd7Ep+>3H}K=A>6elI!S|&m&x{5erYhVu_|BhJZh%@Nf_$W#Jrj@-5F#-3rlB>- zQb|#&sPl6P^@8df(?Jp77x+5U)=pjogFqksmF}Bo6&OcKU zz1B9Q>xGZNQ*Q|Cvhwz)B}0P`j`}ky8MhjI88{D1D(&+EAM$@D! z-5zg0kny_Uc|1;0SX8c&pq>XYS_7*ddi$#s&_nuC(Rin=KONYSpLW1B>*T1@PAbk% z^TO2;;*!z|ZoG1EQRP5)+^a)Vx!`0Jq z?0N3~FNK}C@P=Je<^KIo?PtzrYinz;{PAgK&KW48(d85!^7KgVM9ChEylE!>G%9|P zg&$-B%#OO*iK1A+t^NEbpG}hJ*oN=&L>5_Iqk5a zgOYi9g-66B3cnY`M1(eP76Mzc9Y&+02_w@L(^Hkc!(qc&(ga^7hC2>KGx4Y!DI~s= z0k~{@#(2zy(xqmlmi^U{33*&0^sU)B9DZMV#R1JIIrdB?>8@dN*BaRKjcDCMtYrLf zUQ|k34t&QJpH%L&?jsrXurkfvBhhYinuHU-gFn@(`UWy!(ZkEdi0wzR;jl zm1LY|AA$r1f-iNi&@qCPX!keD2xi(l07Mz77MFB453d7E0(F7VoN-1jgS8RK(Wvqe zp`XUnU+;e4u~r4+M5c>Ik2tuIE}!N|HMqRWaaaE zH+-;zFw#tu0D0EtkRvSISxBKN`f>n4X?8abL_fhv_a-XIU*TZVghmu^FT_D!UG!PU z3ou^Kfil*7Nq}&>osoO#MD+M+ICED5SWc{7{LsuWK1QzbHXVKHroe~q!;i1a8|ugt znSE#49FwBHjz9G0t52u)2fLGy)H3$g3hI8DSfG>`jA%d+j2jfN>@3xf`ZbQC*Q|v+H~u3;B7kJ_6bFMmoNYF9kv%X~O2la?zf(mclT%B%z z1EUmfmvdCjWnf4>Vx*Eqie6fQn;0wdZ+G~oWs#sG+Oso%^bqJ+mf^ccAPg98Pja7S6w5681yy%U8s%m~N&bqcK)B{>t*3+o#ltjZ*@RiEt z>ojwxZ{%5eMA;jhS?Bo0MFdWH6aK}T9b)mQ)2PLo|0Gu~l;R@|vg(YDAd#u9XEf}g zX#gzv<_7y-qhWuek%dh4x+_H~bMQIYCBZ3ZM!RyQc|nFUVG&aA*6sxm~CvlsMf7aji5WvJnT4l6Nbbb1VOi6hAue%OD>id-tJ63Tee4yTkqe$ zPt;sS*H==)voqiH9elzji4j@XyI@=PCHCkvFflr68Jy%Z>cb(|ym7Fo<{=fdd9lgO zS!%8TiZ}~4AXg0kpbY0Aw)uZ61~3yNornTlU{Np;pxBOs{fh;T#sk{dpsl_=e;-?i zo}%6tiHC~N8q`Ou4pKHyqVw*N&`R^t#HK&!sPDao=Q9kP;6`<0vq}k)w|)(vouN~H zWCn2~7<;#-H`Y{8R0MG6@v^BlXu;)Jc&A8SE7uaC{|VVta%`egOrs&Sa3ABgTtvEK zG5ZXbE_LF2%``|(t{xe@N8QUn#%`E4+`ZU)aWelV#M6_v=Ge`ym0LJrEv#`4C0WYtU>F)u)5&y0;>9bwG<&{7Qt>4d75Nm!hP6tLBd~ z=6*ppf&E;%B&`MIZD(B{^3HMf|U*i_&T9>RdXd^EyXvlY$B=+4-h z+4D_{V$NStq}*_umIfdwlS?w!RenzDzpG%!AxTtzK8<526`i0O)EO@|FWT}wjx`1o z1gn2lSt}luole2FtV;IaAwBgjX$ykJ=Uf(@UCPS-Sk!u6L^ofaVKeYOn0CRoWMF>N zYl-)oG_w4okYDc!>VpR<83R7**SEKL56j^6i!mRNB*`jxpcm~4%nKxxmN1gTPHbG^ zdoH*SLd`Yl^^nfr@WQ{fdj8}@NrlJ8;$L0uzDecmP;tAZ8QSS0CEd3k@49=C;|#Xz zuz=EyPK`6$y2~ z4)cUI=#HW%(Rp#=lFumi4%Y_5-4CQfd5X~%!B=>v`x6Dnk6HB@7ZNlVuEUz76mPDu zKw5}~sS2gUx86e@KGifvRpFEFaPt+Jjpmom&d+4zp0nH&!Xu>CZ*L&ve)I&C{YFrq z`)$k|IMV+TwQ)Xs#=|Gfj#sYXU`9OjmXh`MfK|Y(f#C4uoeloU_cd$8%`mS3v(R(WbC>cCV;r;fuJ8XHQTX5yRWzJhSh&a! z5iv72Hy<7ZhO;DT`qLkvCoLQojeD+lrSY#W7arU`w=8^NVCk?~{l?T{zbnhB={2x7 z@M?G;hRQ$n6b<@k6#RibI)g2j!y+QYi}Pvv6OnY_h3(f0S)>!bmjaxL8^j?|wk>19 zX}5^>0sk{xS8(WOpf1abw%xX8@kcVKSp9&LZ{tFgE7Q@0eRA3x$^|^UoLe~p_c0}< zLZtSFI%*)63>$>s~7^aJ~j>taPon%J*S+lKNH%4q^C>yCA$jiG3QJ0&=-2YSbZg?a} zYd}lM=q-q`fVY(()w)xb6XI;#QF>)gg^o7RXL@=(JiIFU2IZXFe7y&~Kp!9gy7YCJ zQer|GYJO5;5T9f4T)>Lg8CLWtUc#Cm3@vNa;Gp2eFq3$d5{2Bjx}U?x+tu8TD`K?* z@h^2X(3XRR2{h4EZ%oLGlK9>76Ep22)VTT2FFpb`&E>ws|ZBN z{rOWl7QtuH4S$M3Bp>h7pXu+{+yq}{-BDj1`juL5mJ;+l!vpN`o@W}jNCN`uW3AnuD z7^-ggXVC7a#02KCx@%OBP$v-N4q8jWHy{KtvlBB^p{J##1nxhlcLUE?(}#cD;4%lG zT$j5nM+%f_#cc3Egk0n;xTG?>G5z5Nke&&H4O`j6jgntVN`8m|CdS5OD?@&E;sVdJ zemIOjH28cafEF_4ffyR%yOom51eroxuE2O^QTwirb{;WC-n+Etdbn$L`p<$9Q0HAS zU?PiEPgNOg!Pr#(Uw-C?vho|9b%2l^rll3HY0#nz#e~qRP&+5A_IwMgYvE>FZch?t z!N%WI!DCZc?Dr1OPN#Ci?Xny{i7=|Oy*GBD&VnkC5}74besqI8T2xjxBT?W9`lv>S z$y<4BZcJdB$7{ttn?yOJsuC?2QbC-o>imYIl9ky+lyY1aZP`3=;3XP~t1M!s5AK`T zcY!iOdu~Ii8R1vNFE#>F5fvvM;Y5x$z5t^|2<3VyUT+Wj;%^Bdzah)V#sPN{G4P_}faRLa%fOM1?p{?YOg z1$BU{GJTV?56a*BH#{>B3fr5AKCX(W%Vn*f=mKxYcvuH(P4Zt)&y*SX??s8*a!v)W zutdghB#IXwnE%l(e+@~&@bcd}izQlR_ZEmONDIyR!DeIQ_f=h4h@D&S zUIh`mHDmqv-|Uj=(X0IH?@M-|pYQNJntU4dx!;qgqM}vZEuRw231Wo5eAe)FCf3G_ ziT%>&y7Cjh)U=L?mu?y~r-pI03NxzS@6Y@D*AqX$lP;8)=(zV%MCa_xr-1ZaR@S35 zNvV-qPr4$eQ7J`d#?^h_cpue?D;W6jU4^ z2(ZtZEu~^j=|HRastc# z+lAjXwP`Fb($HYU6!Vi8|43)`oDLIw)eeuP)(d3+$65N9zkzqBC}$(SK{FDR`-TSF zqDR|B9Qu4}CsW$LMHN@bTP3r-k>|jAO-F`_YWPZ2nV!$cr90GlGUsdb-GSt>TN_*p z7$~+K`Ko+C<@5jX^wwcfaP9Z+%rJBf4bt5uDcvDyfHXscbc*CKbc0H(gkmBsAUSkO zh|*nxbc58{KJWK;_@9fIeeHe6TA!tCX-)O4Ql91e0vERS#%n{v^q9y<)}=RcX-wOF zcMCS|5_PrB|#r4?qESevR2kv zYdza~K;?@!^F;({B9!TA5zo1qX*V*JK`ZM^U_1I8K?{fmEK~SqsJ#z7YMou|JOT`I zQU)f|zDT4kiG-ja45{AJ7Y8XRc?*&FI=3?a1Kuo88&+%vewSy@ccAY6rh5X%3ofqk zNBpXLZh%ZUffTU%#y}t7Zb!GUoHe*;p-y+gEFX0p>FbpXIqTLu?F}B_JD7We&?Ie& zEo-5Ko-Mxd^gf$_+S?bGhkmOj6bEJ(%K}pkGb@}wxA;UPMoCl6 zbwE7qhRN3l26UxmW!X76qF8!w?eFiqdG6*>0?5dhw5{0&sgTf6Q@fZ)*vP-*J@^z{ za#ck2f?yH@Rtj7Z@3`>YCRm__hG^oir1b7CTYn(!7Yb zNeH~<5Hcp3xNJ&RxTx~5_`}F*7?hrWmNSq8VQiSmRxYUwgL*wnOAKt5c*curX8@@B z7a}m*2>B%y1{0i#?qBdyi_prW326>ob3y5;O?1B~%U+d|4;!;x%zK-m6sog>!)cRp zB;Tgh>=PujfOQKwD2x7E+XPKy=#QFez?BW_935myb+o&;Q_?!fZ{!5xb+kev}zqQ4cF27Ps+q zkJ(a~%&zqlmE4(1xZ);RoB&RXryucTPj)*|tf5}lA*^9YNNHE`(v`GDIhl2+cYc#3 zD2_Qvm?l%3uc`{CZsVH7IEDf95dh#k{=+xSe!9A48@cjUWJNGPaoH)Q+8(tzIR~`O zMF;mS1O!`)4}4xAE^i|q87;VNa56{-QTC6QYTDlAf|d$`8HC^0jR|%zfFS;7KF%Km zW3PzlXu5C0LO4Wyoe}KOJY`?hmcQ}?Zo1d`l+nXqzl!Q!I_4#I+3k&}%yB4_fjGFi$Ky{<= zgh>Q@FNU~%4=kRY4G#Iu4j3rdr*3q1fBz_UvObL@E$Izy%HbUT4{r{NEIB&yew{*k zJ|c~f$8vv3dpotjQy1xrPlDCDIN91hPMq$o0-G_xvpdJb^H$ZWlU0c-?deVK_7O(padf!k=m0xdg)lEC=*3`bDR;%+K#F z3BP_g))cfCr)*LYz)4*?&|dV5U&MP**C%NMkAR9rBra7c3~_mRzH$doRVfWZB1c1; zXQpH@kN5cTpOPZI`mdX}w~>0M*Y_dM)%T|fko7ALcu~c{DmhBlmR96JpAtkQht-Ys zC8>pm+Phxu+RZP*7-WLUHHY#$2iro|M-{QUQ+7d`&3t!L@GqYF?9{eU*L{CN6sRg5 zj151geacYHFV+vyiBE~tp9b*@5qCW~V;-8Dv#V)hBiFX@r33zmM7YpBF8f(QrX@Za z{IT+-14@UF2i41V*7VRQrHZqYM=pQ?@bWe9nvs+UY!`khBxV$pfoT)U$mEvvSHEtS zYzJX(Yx~kGzwIC=)LZQ3%^h8Q5*Dr+R~dk;Kn2tjpLutOhl=aqf4}2<&(lKQF=uGaph{cZMDDL z=7M^QZzA$alXPjK^RP!T0525RK@@Ux){d14w4*l6B+L^i&z8%yCP~tki(9d&l*r)) zi?Mi9V-2R;f_B*x-n~6a_q3s45L#X(rcCtIeNFgf%!A*lZ$4Fg!p0OeHB&ZHHWybP zqEcn{4+cnF1JUMNbAK2J<;JW*}SBm4I@x#7u6mbsAh)7Cu0Q>#t&tiX% zzPG-<3ic{IBL8&j570or&QKhe6ffBE!Q$JLk;FB*oLd8Dhoat&bCXzc;@ue;{6hw0O7~BreVz5XxpdcgND96SH8L{~*yf18F^N^^{b2e5n zn0DyWg78sf<2yNyx17U?kO~@iCUw+@Plb?RT-7KX#L59L$~~QNkR7td%GnW9FhRg; zLlU<(-8QYwJa{ryf+fBQ{|<2*fDHHptb&@^UD|gBbW!L~`n_Jw@$@XIRR1z2Ia|EU z5{ne|{zDPh4V9$a+Yu0HipyaneD8{kft)DJP(-D@XPF#tacc=m?}|%Hm#y*&VtDT! zzyK-|Vr~mUj5D(wSBLIa{xD2WN8eIzZjRw|6A%OeO6aFLhvhq0r{!Ydqy#C9UGYVU zJaYa-SFy*P@y~>fXkD#rR&=vw`ic2P<8d!o~wR^*I2qv zz>ZgrMl)cE#Ja{GRXdl=mlOR?FrY{?uDbe`k^Hp;UXL!hjh?%KnY@51ScZ@VlTg}T zFF9!G_j6(VQSbPa%W|oS{QL?(zv;YNsQ#+p*ygbZiIfx#5xpp714y;y_4l{K`jb~y ze%^BYsHZ*zn@U20QDMlh>-=L?*-icbtU7}qU->tOQI-924ShXdFLwH%sOmNb7?w&F z?|XTPG`uA)eNCOpB;WR0K6s)V_`#e`%>ml9i^t!;(F0PulM_aDmht?#U2?A#9GNhB zc}awxcpYd8S9A>prV9Ehan~`q|Eby=efJxs^tYcrIG&pGYIaUC4R%7cMB}~dDTa`c z!vVgD!Sq`Wt-J>ZKe!s6*wO(~tBfQMs{~2mNXXfNZ`1TR?bIlzINTS0FIZSPBVON@AAV4Y3z}Hy04u7PZs9FL^KHxoyVwg=#DIFt zaD)TO4kpNY^c6*8K&lVNfU-ppjVy%*ro?zvzvmpT(Mlris_w-~YjI*!xZb-(Eu2eC zFRQcith?O#oP6brRm2?~8k?Uh-dfxcl0*X4KzrJ#Hp8=v3-&mci6JROKn+87o_YK5 zaJIj)v9WPX$rc6V+8n={$bFrY8{3HU&dB|=*vuk^qu~B_3j>OjfU%yPQJPVjf$rQ> zNt-9F3S*al_9jOsLcJ9K5)XD&Py_?K_eI^)H!q-PE9s~Edz+~}{D(AQSI15-<)6TE zOnHZg4Y_Hv>@Lz>P9EKVmifG2#Z;Xv=x?r!k?=OrRrT57kfQhglKM+&Z*=P^xVPMPLAYf2 z-0D#0Cahd+DCfJ%yYC;l^j~V}|Gf2z1Syo&e?lim+VaI=n2>q^13W$JZV>A_MBfSB z=*2&<_dm-awXn>5^(yf%*Y9CjF1s4J{S4C%hAp9;s1$_FAyXQ97GL+I3e z+%3j0w5VuN*jq<#CB!PJfud&M*;HF+J1q3Cx=sJsd3LS6c-xX38Db-*=g3gaNev@B zgUct=M}&FyL*C4B{3I$Nmw^Ef84VwaXJz2ncTW@YQgWol-LOf4V`}hDB~-IputO|} z@q)g#zOl?_T*u?U0`}EO1!QTYGpU!Y9P@MTRkrZmpqZ9ny2IakoDfOXAbmbZ!I#k) zd1J`Qn6E$~cS66EZzMTDk^5TxxVK`9yiq3 zo~FaLWP=c~gD=}I8lDu~3@ZSK4uA9c4vEJspXNw(sC1AsMf3H2@rV`co4>^8*bQV< z{A!*O4nEgO#un7nx`K#`b zFut+AgL=-npfK?2JJbVvy)BxMjFEBn;~B7(IlTE`_2Me@HesW$llA5Kdkz`Gmi+M2 z*v`cFm0M;1=cnJlc_Z&x0{|dQi>s?JMc6D0Y$2}BE2b+f@`B~F!7VxbknL}hUdMha zT51UL(KoH6hcS7n^2!yAjh9=ZE{}!AO7ar+AN*B9EJJqRkCg-h)+WJ0Kme)!tN#{q}`-B34Be{<$ou7=d2)0*L{v9@$z~XNkwY|@rQy2YW zQ55bdhq7@r5{8u0>FE4xM-JU9j075|?Vy#_?~V}tUagL!Xt4^LZpV_)8+l!BgkHbC zYTye9x?JhM)zd}bMcemTiWCMW0l_bYWuBPZrGDYt;n0~wpgN+7E*CewOYmd(VS4Ph z6oNA$YDAD}>vw&cK{>*x?ijnvl8+O0p8Nq!z1_`rxZZn5+FJq>vC8citSx);a+iw= z3Uv?Sb=1#!1WbSz>I&5)2~44c&^;!=*;iK9X1ebOrq( zWE|ftw|@A?u>F|>Wb93Hd9?{$^_MRam!VCdz-HMJE`XHUGZy4|SkYuCOFe*$7d4hv zo4AwX4Z5Q^>pUhtB+A>K7*b*Kzh zOUpH1>ghZ)200tV47@qAl{70xJFFYe0_PN3Y8qX_=1!}R^$yJI%M2NI9jm!zM+AY= zVzW^d^6rdy<$~oQEs)z$Vt^`(y}=r%F=Tdv37JwQ4+GSoyLjw~lSqRCipHxudxR^t z2R|cBo=Gv;aj&w-%>mvuUE2$U+WXjc#Tl9eK}hBca-dYfW8+0_Ff3#n(%5$gvU2~R z3w>iT(U-7Lk%OrS0WMVjvj+OsNoDZeDCk6vL)bAh*2HWlk?6g-Y?)$3f|IiL$cwCs zuq$#CGkR8DK_)Y&u)~ol1++5u#c!Tnq}i&cVa9T%8zDG6^Z^hQNP{ z2UW?pl(0)oX9+w;bMkW&8%d~}n9`vQAab79;^-M$fT;pFMqd;^eiXA*>!%{dLVoXx zM#|s4GJ254hH}K=p)m`WD3(7PS&M{}I~)h~Er zKzL16l^s797Y-@2LdYL~7m5;2olL;1Tm?FKx-j!o>?aO>*r<&n696LD(9mG)D$C2G z=l>Emw*Ka~M0?Ta${)Clt-Hc4JRsSbc=Y|vu3ZQPu&C=H6_8kAv2E)Uo`+_+uNn_pfZB`MIhZV z-`M!4uyRyLZiCUHSo=3EVqZ0jG~y!I7lew)#$d6-aD8fnlI)#7is{fAC6yB9ce;OK zFPlE^k3{mDR5_BlZRw`#GWBbq=ha;^Z3ipWX%)N$ik=sdF?4BiKt&i2DG}?5EDFqF z*U*K%Ksd@+L_`EtUq3|w$qbu;CuVq$cB>i-695|M(;O?q2QMO`Q`lgylJHQ13+gGO zgLhNq9)*FKDVuR)3ywKq0CKz#wk7X_CwscvSw0e3ezS0Kb~0i)2LJp5a<;yxclM{h zVe9MpICIPLO!TOhR!T%oDc92-dzQ{F7Jz&+A@b=f8Maf{ywkLYWVNI1n=i8=-Um0g5{gcWX+w@WO(k%P;sl^MwVes2D7^VZX;Z5UFxAo}OY-@J8Iozq$- zTTg)T69myK6kNJ2Eh`LG1kHY_I!GkTMXEY4^sYC5~x62o$v z9?M_Ma?F^=fwT+&6~k3OGB{#tOloxdTj)PPUP{fi_m;!;-ig_Ds^X^1?hhuU;uARh zT#03+>i+ami9Hd+4^p7|$8ZmWZk^XZC1q{0b^KV%$HEgGoylhJrZ|p@p)=lq-5*g z<<#)PwUA*V{qU#J?X({_ zCPv9cWa_K%R+_taz5d=O)6cT#$oZio?Q_i#K*@lFq$C)CPFuxNkN#8BuL<9R;^J0E z$R@pWJIW$AmliWRN~aog;iYU5K+9lqat6ewU`P1RuTLgt z*F_W+8(T%;V!rR{<~DGG9MwJOUpno5XF^#{FGbS1+AnnWTXA)d?Mxx$LrhT-0?fVs zhUd&nHNoqfxG}Z$;%i2bx-X}!gVzbmf{8m5Ztq5+m(kRzffmS=zZD6-?gG#NO##gYZ*8rYF|PA%|&H+wtNNSob5hClrtb3oA(T4s0{l z*BD@bl9!%zY0qJqh-S%FnaFTe$^_*))qOmalkP?=);SR0a(|y_4wYb#rtTT|jw$-3 zBNBdWJ7C(3z|tgDwRp^SR;avpw2!JyrMbkqLa1Cb(o*6{8IVd#%T)f60ADyrI=XsX zlb_IB$$~$>KI59p2WywBLj_b>1Pq!rWR<4rH`{velS*osiAag6*}KVg>E|U#m`fqe zTRq%nTj(1|m@uX2(4IlP_KWF9Oa0V?g3LbWmFE(fHNW6En?~=;~Gc4LZK4YsCTC(5AW{?XdFhAY4 zgQUEtLxMmLqibA@ALTP@tn%n@qK!?jM16iDDJgeUU5t34UKHQTa7N^iK8n@n#@a@v zu|wR9@~3jUn`LigeS(Lc4^2CcWp=Xw23E@c7a3PYcA3wF;@G=c)?xAHwH~ZuVidse zz4)MP9HUk=H%c`gHg+WjD()*>FsyY)SqpMh0Zj& z#{UhHVvx&@GWy(Axmgz`J0j~-}1&KR??09KHM6_OH9 ztZAk}u93_bGqS9S5$>RoB*|R(c87&$hFP1gNK|X?8vdTc?53>M_=yC5qT7;^lPW)xFlu9**E_A6eU3)>Ns^t!ueh)&L zO#wrmuJF!2hkas}mWg4u8xpX(4vfQBm>qo$yuBKYyJ*FCx;<^pmi_x1-Fg$vk&tZH zlov1UL7Eh8;<#}8QK#>4_zDtScI+%1X$&ni&~oleSO^&(B?5A|xb+8SF5A!oHPH|c z&O#n)Lq^qa1O+D}9Z;)1_gM^$AH9f3sT3!YFarE^K&3?OkG{8?JxK-;m^0BJ%Z{Nh|@uK7H2@d~ID8 z%;_*@W6+nk@dAUm>16J^{txct4$dw(bsrijo%-*3)tAIU&e-l`j!x9%gE_dW#eFV; z66uu+S7mkej0`0)$mU~}d;wJ~MibLqHWmyP7Vc`no}mJtE58X&UFrE<9Xda(KG)Cn z@~HgF%lXzx#@iTo`K$!!OqX5A=HQG${2*kn<>tyWv-4|ZrEQhFi_|*cB&|fxYxWnr zFvtdMy>dq%m#9~@Qnpnqj{(Py=_99H!J)xH$HUO>WcqH5&f@gzm`B^QG`cpjp?}$8 zrq2(ZY&U-NnluIyeA}HY>HSshk~qQHv;zXkEMa?}nTqBdM&@pJXN6J-{8Kik2aas@ zjfW{brQ#g+G#%D>MA@p$dL5UXsC4(=GHAf&O&UxUYhm4u)aeOHKcxG87Ymy{#6Xd| z?y2-`xYKcR`xf@HNa%^PTIc?vsv!enD?YmePmL?4ePE38lNledtHhKvim%`!B&v-t z%Q+w^Sp?z~eQ1J{U7BQw%K-@Piw7rWIWqA4X?piU zpE1%95-BnsPYBqFk~_bFwVM-*PBOTbCg|ivAQ94xM3DU#g^xY2)+t)9^&{HP;3#tw zpV6N)JC_{N-DxxMGv1`q1HXoOLK{S@T%Qoz(7lfqA##;3vipSL35V4x06@%HIlX3|4i*ZX zJMIWZD=*UP@7hgL&yS!#$VPR6c?i6(ok5aHT;!T8QWr{x_ zszqlD{S{UBbaDup9^(v>Y~69weZ^-s`hJLu=k?Xi$=_x|APKx*@T3R?-Q8uG&Z7$I zuhIen)8HXO&n?=wwE}YHP=P%sy>j3sNS9^Fb6~`Zyu$eVqdwD+qO}x&b_Q{a3aZNp#onzA11aO}_X=_97|4}rx8zV7{{#ECG_Sw1RJbF<~s z)hj6|EhW~|8`-j+y2{B=0;SlnA@16mhL^u@N1DyI3F|uCjAJV2x_}&z2hj6wb@*8C z5p7LF|I_ykud=LgirqIx*+7cV%io8V(m7A4Q7-smvkiC2X3DG;FAwu?{`HkLb%5}u zuC6X{r~^`?*VaQ8N>g@lkTUllPgT3P4T;av>)z<`dcE}65c zA|qdV1;52HXYZP4SPaYD3y_42>ocZEKK3d%#_BdEoZ-G@`&62qT`nqegQCj&a+oXR z+C?m2$Ba-GSM04Lm(6+os>!#f5^GMs+d?2f+2Q%xP(9p!=4op^*kVNl@?`Gzo40)%^|E)YNS6?2L9uIuB7u zVO9i#e)T6%Fa8i3VXJ}Ln;=q0)!$#D|Jmqo@WPUF8@%pV`<`bSlWkQi#;Pl-7AU$=MM*&(c+z5NQ zu;M}}WsOTjKaIQWMADij8j2T$h4;=9!Lg_O5RF*ehhP6d5R%h>z{Lzj}7(aX%^^$=xnuCze)J3cJD2NE@A~T*1fLNgt!ThS`df2!6 zeAWf02|ran8-B1$EXFR6#|{TjG8yW!{`RTuJdnCbWxM&>l2%%PhJSp}339yCyem%)&T}A9pbC?RsGe^l=>wMpaqG0mx0&crvK+a8f1bgv}dTd^pa5kYbNlDfWP+La@u1dYYhi? z!Ml8YvPZs?z^ei3vds{K(ae?he!tS41V`)tnKgh^b@FLP9N9#r10f$DAA*J^wygQ@ zA5gD}#UEXt?#%LgppW5l8_jcKPJ;_z6&1cF&3nu5?N1ONV8Sl?_e%W1^u5a($DEB# zWhe1bl6hf*Acmt<=FPD$!H$w=dbnQZ`eC+^H&>ofot~dM_cJw}wiiRcKsaG|*y%$53f72pafOv83ZB70nk)fJ++Jj?Fz)N-l)Z!BwwOJ? zq*n@v_U==4dpYK7We@nzusHn$l!y=-%ORZuSpLem{;eMqgPky88%^YLGv^doVn@PRvM!y^es> zgUVgaoT?_XYkgFT@xgEX&X=o)6#>&YZc|qZAYD5aTDOZ45HOXb$Pe|V_?P&8^aF~s zFfHYRb2fjrHZAO3xFQ#m%mi~+b=T_u7c8Z~)Xf1a7w{ARxv=G&LR-k)mBNgoa3XnA z-<*rACdCMJf)D&LVJmXvug?W;{Y4ug!} z2cY{Zg^Q@OcP@{8F`xdawAEYSu=@S`casX+PJn52Zx#N|la-MnPct_}@K;Pt^jaL= z(hKnz+R_KB^M989j{Osy*_(c_!}M~7behs6 zvjS935_e*Hhzv{ft=-y^DE#Rg1X;He-NJ&1btaS~89yc_f-k6V_zs2~plmqH1is(K zfVD70T76v$;ua}@o=-9~f195A9PLiVh{Up{VTV}}$5@xXqK1|W*bk zo^;7MRjh!kIem6^4w!4ECPRuS_<6zrdMhbO+*F=bQ121xz0==T@+_*E321>MiHA0C z3t{H$XkYpV6SS`FtzCFIrrNY(F5+utCOu$J2=SaYfHqR(T>U7Q_QV0trzChjHPk0r z8H8p~G4+WBbPKVm%^FXQcr^?du6S z1wRgE2P20MpUN~{+$HWl=BGn%wD6)6UHR~$_zfQ#McB~{*|{n!P?wrShkc7&blz3l zE5p(wCLV);Zh{w0oa{GwyH*7KK1-}ik0G8hxOVYAm0&G3DAC@eIn%7)CfM#vaX`&S zSI*RO{+AVC8jNz09RKfIW*d<>fbVA|&)c3mZn`?pT$zLNz zkas3;&*VbRMEc(~yA4;`o26Xd#(T&4vw9^*rJh}RF$9osGLyr|TmLPQs&x0ixS)TH zZC1aZ{MA2~|39UCmosA|2jYM%57B!PaKi5OHtRLWA@(niYRIC9N)PGiAjI=%GC3Ll z-k)hPWiv4$AYgI_pD@!Pf(0Ov*5q+S7$e`h7JctxIW9`C`h=CajDqR zN?c&&{7FKm5^RsZokq2W>R_Q)`)k_TJ&9V-&vOWS#R!Do|MCz!AX|N+=+r#yXLg~Y z4i?lk?pATKwXWqZhquwD6hsVT%z3pfsjDCmkrzCFy`U|zhy19#k6_|Om9hR z*&z`ciVsN@Owt2!WtJa4egfA~Poc z^H_&xp$s~q6DC0StCU2mNR&7x)cLN-yqq(f{)ACJZu`8!^!@g)P3pz|GS9_G*^CbY zib?E1;gFoAbP5T-X|Mg@{=pU{DJ~UNf@V-H`@oyU5p=TE2`MRlhr^94)}eWBcecmi zHd{f~>5yf3?@@QXLKekkCTJKxm2`9-+(%m7}u8NXOm8&Thq4utq-38@BYkZie2 zgW8ud;_b(eB<_sy_Xe8>z}S3@s&$ zOW|lUSknJXECHMD(a=I59CRDvQ#Swvq*AMYN&+MYrq3fu6sSY`@YM z5CaWt%y$fc#v)eQ%6AyY1b}DFV6UFN#`G0z6iElHOty8;zXH~od;6_;)IqKNsj!J# zVagV|d14GtH=S%pK5hK_3nMA1TQx22QnKNpe;xlEj>J6DXyyiCuX>q92?DL}$W$Vq zYNhxnKN}{CXO+~VGGQ0{nJIwFfjcbBSc67YXYQHifE&yAl{{% zsLjJ$SbMY6UneT;7z6cdXr-$a1GeWQCCnvluMZq(WuKC3Br(Rn{RxNToVO_slR_^c zXMeFVy_3Xak^ulx%K{mT<%5a{MmS!C12`c;<$bqaZLrtN(iMgUp>6aWu(JWx?YSKk z6o`pUqFW`$2->ZPeX(v<&qF>p{+Wo&Wo#a4Z+I{%6>^|s#H87Wi9XWrw+9sn7a?6M zYyHJV#uR>jjQdl{*lr*yeRymbs|g3VIz9@~IB5ft1k}2%J`kaFC3Q^2RXz z|D^Ds9T~mttivyZ6CazjW$zXgF8?k0@SpVOhAKnZ+J!Y&2hvKM{Qbe=@gEH$c~p_j z&v>}f=dW4g2eHHF5Mdr3WX|Pa!fx{g2}s|xOWoDO-RmD%4%u{sj5_b)y`>4YHsAf< z@u}Aa-sp02z@bY?A=LCSlj9HHnN~~;O>VD>6oz`4sIi;}iL|}BBtxvIK-{7ch5VUc zaw5K((;(N1D&q8sxC;DK1N}sv-ChF5vZ%~Lu9X)K!{(Mucl#>S9=t$Te)>S@myMy* zP9KaTtxyk1qqfYY<2?nQTqF%tL0|;aNY?=}-?u zF0B)7&D9Vw&$c98hMF%dbt&Jpew)Z?NrVQDd@`byuz~$08Q{z&jm}D?Zw!@RWJW-Q zJ;S}~gvu-YQQxAes=pos$4+6v#C@0^LO=&n!e+n}Tg0$Z94va)cSI@p^rKbDVO4rP z%wjtUgsXf{8JfCF$fS^x-RyPC*xfu8zWV-3EF=7ghx&^}a&?m1 zgxQ@+E)z4eTySO_Q7+uh_rwIi_L07=^H=&d)T+sbQ=jIQBj>O<)fvG{CV1c;A| zaRmgK20)?N#v^#GmnX@}%Zo4NITx~a?EFzoa3r+yXO^RY%ZA4z%}1a!u`09p_G2S8 zI^dUw4t4gN;uU+x=bpCFrVbF2^nbYnOM$o76|4y?r-=AP1xZ})eC%PXE2Kl_Lky&S z+!i)g;mX;}Y<6dOsYmR{faus-LGovj0;XbAs$Gt396xZcS$7a>*ld!5x6rgu zB0=I2^9T5RkKrImtCHZEpk=`^LdZ+y@e8qM?OW-zZpq>V$jbXL{Kr>(V;cOaA<~Ue~8D zuI1iCTw5}Yu`FkZfUS8|h#Y}V=Jz)4e5=l;V2KYryd4qppS=!mxw9OD$+@NJgO~~m zO<+;tU<~IF6wKA0Nrcp8iLW@U7QXpNLIU;jD&Y6=eeS(tqVUO;|K6xc>a)JPFPk2! z6$CLkB?v9}?PI@WW6o#KZ!j@Ni^1E1QyIEuIG<|i_M(c58GrtgC@d|6ez}2`b76^W zgW#ZzsMdBLI+Vdn#fVS+U!5DnsK$50P&hu?r;Id4FA{Ei-4Ob|PfC?pN=-DqjkAjcZhvt@$u&R_HFwaYKkZ^bAT3ai+uBFO0p9>_l6`N*%N z(Tv;bX`t1A9EDDxEWtyztJY~H`l#5(Ni1OrrfCR`Mhc{pBO?M~$iggqz$m&1XXHV- zSL20!r9-{iB3fvb;097<-6&zOd}(c#=l8y`l0P_Y!R3BrZhxZF{U_PA{PAdz05{~d zv;)D?^XCinln_!G7=T?3GOdW#*J1hwnbub1^FKy&@98|7ed<@8 z@rh1!F+*9D>EZd^JMFO(v~PPR;4lmR51(9=j4X+7P5lvsi~$N(@$edT*NRh&Qm~Sw z@fT}lk7b6(xtsT%e8E2+&%5_4gf7F6*~_TAUJ1w>faUo=L}ZCP21L6!{rWMT7$0xr zYnM+=84MH*7$D*EK0k1%p$Yu)7Cbr2sSW=*>a()4TAp>Q-0-C5=if+UT{Iq-xtT3IE^;E8J`l>XYx~s>1vv+pKYFfdwH{Q)?lUM}F((#2A!-F^^Gd~2 z%I3n}su*gT~};bmxQpjo(sx z3(8oZ?vgI!LHCSs7H$^aTeoOhJ|Naex>7vZfysPw-NXuH+1c3G4NTZ+2gb;css~Vu^t}midpVY3wvTpP8{f zxf5&<5uYKtLKRHlGa?`Y6;T%XZn){}ifL_yMJUT9F}y;vcb^s>-j|gTwgx`3U1z79 z`Jh~EkN0nKFkh1$fEG3CG+!oO{V6sWJ;h{vy<&!pjYXxD;v5}G+(62UdFw1_4rFpB z>fGh0gsPYN1S_|t@D@BRxS8iWer0(UZ1xpHuPhSE+++0P5|Q$pqO_1}5M3%7uw^1( zQJ3a$8KuH1={^zfbwweAATlq-EN=1|yV)D06eo42xY+!3jwJM-iFnOk9tn zIey6>n`(&LPmXi43d=I|9Xwmv2YxRpl&1+~ZB0ncyVq<>HWb0_I=BFD-JQ(63+M^7 zPooJZDA#M}zr~cER7v{>+MQCaTkrpySoS6NXV(Uj5a|)Ku#ZR1dq8x4NMHzt$4Aj` z-f(_1K2{6T5IA9;ia05y_OsYg+3X~A-jYkLuW=NwmV9$9*XrrS@A|;+`Um#GF*Sp< zKLKH{gr2U-?GkqeAdw*^7SuDwuE)j1XaL{NkI4861v&Xwrupm7X3cwDUvjTEbwNUa zLEh{5q`xj?S^eNR5$o?aO6zH&R|u>#-uTwXk!tUiMh84qRABu$@87+v+}g2@tkKN9 z2JkEHvyk z2fv*L(V?-8Gyi9|0MDSR%;iB5IIJPs!g+n;9)Nt~GdlhwAav6oaY2nY@} zRUT6okw-4ltn^N?>|Zg6hK}Kt%$7s)YD$%Y0>m#P>-I=j*?HI?R@ZXQbdOc;d(ghM zSD&;F`uvtn2jUh7)Gi`U9AtZ3e@$69G2|biM`Hx>(6P9K3KVlULXJiiZOv{BoobIh zfpFzFD}(8qgJzD^h}^!-dNvvXb_6T-E@Q_)kL>$d$%AT@V>0b|MidcU zCA_^4em-?8LFB858uFn?*Wk;jnd5V5uQdco24nZ4?|VZtqnM(v*gRHQiKhyIbe_%r zRIlKe;%>?1KdU$ggO~Kyp{LlTvyBNLz7zx6aG!(9*|Tk-7zv9QhY!cc)uuQT^Ye_8 z?Bo@vO1<)sTFXB;UZ3$WU)_^GJa$ncbdOa-Sj^7EU2z-ODodf<-53hreBu8D`|=r^ zQJ&c6GYPvY8A?x&hy@XdJb1A`(d3DnE0c>CShn=zJI!RB)_(Bn?cnQ(sIw`@bxpWjKUAVKzy&yhs4qG(BDnl#7WAACv=Pj_3iv6VSRpAFMWu*kBxfI9i$uR4> z1Tqw5xes2Y8Pz1K7FB6$_YvLfqbX+B|a~+kbsHoIKQ4SlF&L4NS zc11?qrBE4EZwudX;5w+&_4Mmh@D6`EARji)h=_>52@I24X%xBDpWs_@ab~q8?~lM8 zddUGP#qoL{c}^cR;(!~bn;2P-lU=h; zC*{G=*WaI?aH1){Uk44@TWHlx7y|0gBt7pi1nP8m{zj`dLVy3=gQou*H#e$#7RaVu zkOmRG^?YKT?;96Wn|0AdB(jbBGVNCE2)u>8+rBmOH-W1;p_iN`f_5#oC(1BN?VOcm zCQ&bv1kb0tyk)3vJA2h>C38*ij zDbLRmd{z`v9;i>!r=PK~-SEikObg#ax~7NrRf=A4O<~|P7vN9eJor7tjxpfeBSsmn zC#D&))`bYYoUvRO{9R#dvNk3;ECm9J#%w}S8%IuNPfZ_2Jf)?lZ22+!pdbU-b{&?Wx0$bQr|;j&!u*7=U)&LsL(_leDX@3M5rUrNV;R}sbh zYYVfd){c;7C1{8rh0GMcQX=x|B8%B;^El5$AL3@~s8*w1A52g!o(B_T=bR=+>PcU@ z5FEX}njRj$pIAfqdqm~E(i8vkyTiwDaH|l*TZv2XjQ#E82OmDNW&ToD`B>taSmol% zfDL49coBhSkAyXZa3$I1U^#yX^K z`u^eQ^g5EM>HEpa@typ_y(MpO>9r}MQp@9%?APAfEUi?4Pm*RHOOg`9G>G_N)hgPG z#{r>6oE=NxtmETLd%4Lcj0q~4ln7s))P(nKyrA4^g3ovgMviT ztc3HK@c6CX5tslwLh)%J`_A0AsL|q!g(Z*37i7JFUngcv0iki9j55{9Vv*o~j*-Gs zjtJX3Ty9TZn2X#cDFgnqbXUz>Y)KJG8#*MXx;mM315|)rmf=TbxIJpMSnWZ9gb^hk znhGzZ80qwZ$Xb*AOePQ0*@gO=dP~+pfSO96v)(e#&?k^Ifay-u_Qk0U7j*BFMF0K> z_mjQ31}X1~DwxCj+U38$xD0`r>Hj0@Jlv`N|G57-$HB4p-n+8N-Yc?|ajYC$S;yWS zTecJu6465T9_Ntkm9pa?kxfMA{ptI=@9XvtoO7M)?LA)4@t8LXKHe1`wiP3}!+(~U zo$Y)X6$a=}11C;s+k#3e)@>~$b6Ur_-uR4FMxzK6S7ms6LK#zk?QJc&ImbME+ii~E zG1w{_d@{k)U*?(lrOpyW9163&{V+NFk-w+mRVRJwO*Gjt($SvSh(aLsr5LrsiHC-P zBb~fR3J|_Vpmx#lVWTxP0OO86_w(8mc013$8^Jn%R{VPhiFaC482d7(%XaL7-2nyY z*R|Hea}pB?!7~1=!oswu%PqU8u%)HQ^E5iwlG!nn(mUAi-wQ9qsj8F5jpW%+n34H~ zW!JL7rfMmfCgI9&;Zv;vTZr;g6VUsc+pAUmkCmOY>Rs}Y;l2hrW(@Hsm*C|dQD+k& zOj$8T%C|#Of{o?@V-M%{+A5KCm|hN1x#tsgMoWEoGGMaMmbB}}R#e0ye%O>=kvX(uM!(TyMioGCGm(ptie z0_mrDp3k!|{}h;k7p2!@vU z1|zTTzEKstk#x2@m`u5l4asp~!r51F-xfxfmE0ilgd!z9LtxF%kxr>HwI$6sd8X_w zHFB^dFuoUmh!GtGc6DC9F~os*!y7`QeT_Tr`xAX1mpe`#d@iffEs$%d3?tk3_E_lj zqw)JWhJO4`8PZG(spbvwyg9*)l*hMv@Dvgl*w~s2Sp;XLl>u&DU*msUh?E{n6cT(N zo#Qlx!~>1LdmsZCIGyQlp*qq5&%_$AUt5;Ro_eFzgQAFmU2*NnFmz=?WR*pS zl~8XUCwfRF(of2lNgkkT7{>#tCZoO_q3o5pQ~ieP!sd9E8Oe~01Xsji3ky?~NGPtE zu{+T{?JL4g=tW`dYGSg_x*>~U&MvyLlnI10nY0H8n|s~(ba?!sI^2`1_VZ6pF?%nK&xnSARmTU_rN*i%)JlV@mr_V%+q8 zTuT*HT~S|*KPz^d(KV+f(66B<@9}DlSQNhW?oxCqovY9L_rzt-)@JGh*sz-};THq$ zr?^rJ)PXvmu92sf1)*^BnV_5CYYV%s$Gt;8ySwKQrkbf9cq33fU0nxRCSqdW@o$sp zx@KytuXZX})0{a$z1s+Hfgq;$JxlZ|Se{Z4*fK3+WwxO1L1uMwD z#Iw+1VHjIHynSSmHv8?uQ=gZ)XXgtU#F*Hct`%;?zuPsPn^k}E)uA;4!6_uPo#i6U zVWzmNjG;}4vbY&07GtQkROdRT0nu+-{`&5Ih7+^A?NSFQ?dLpXPX^exr9?H@F%+%E zY^3AK5TW$-8%6RLfBppR%Mps@_SwUa=uuQubje^5_!Pm-Fn|7wm~c3+@bb@J!vJd` zZ9-BUXYhF&Hg*pP@>bB~gNuiZx(y@5AXJal_K8-x#6EMFyjzCzA*aMl9f6#jZ1CFb zOvn4GM1(>?0enXE6oOJ~5|zDSKY5+&7W#f{1=Wa*8t)S8RlzPdqW-Mz1D8#KCS|!L zm{sT#KyA#>gWrlviXDH8xW;2d_lLJ-V$8@^mZT49jCvfL z^eA3btxI8=%#hU;b*gxp5dS3Nw`*ml|MAhQiV7hsyy5pEdI76-VU*wuQn#8*P>{%( zPcF|*5VJG_@T}Tovj2jo7t$*#v5DKyX%3Is##JT;t|H8sM!!zsJk0Q?JQ49c+JU&= zqKlux_PSD27(Otf=dFg+AQ$IR*Rj(};rK0oQ|uo)l3Ip(2t{9h?we=n({4F$C%m_Uu6nP!~vQycG z^MoN$HUV)Iz~ArqQceN^L?%S#-b5?Gp%3Zvpt8b}k0HU^uP5N}10J9;hGm)w@~Tru zCqvD~3KkxtxO@}E3vWymOHH|3S7%ZkNyVKVk0Z9FqTNb7tze83NKorhCHn&FpzZWc zzL#l{6P=&H&AOdN#kQR=e8b{3;XJoe5;@CZjnqB7N~(4D=u^NN7MhPq!R785TC+dz z9=RK5CliAVf+9N;;g}(p49vu(7T6`pu5IMu2pH<>aRMTk!Q*&Dou44FOl1$)O*Gz5 zDZMtIz1=2=?Gntzdx_+Ngt5+!8Oyf$BHf%w&CJaDhlYY&qqTq>r+v076((dOdmbmk z+ANuFd+;ufi)XG7+^lwY8!O)bDY?*^Y43ua8*=mwBoh&uNXIhGYQ{ndCy9PF$ zrfHJ`O~nmstT)itDR%om=Yuls>Y-DC^~CizXujk5o{5hDTW;?$6H~NYS4I5;$vvOb z;@x)Ky1%`cp77ZrW|might4yGzL1}rm{IeZpC6x@i#a@#C%|1CZ)N5el9A}SZ~S6X z&E?GFk3Kr`fA!Ibppd|`q7UStjP!mwD6R3n7CB@k;|A=ylDC??YJKAAds>f9&w!Jl z{JreF3F$l{LUHtYb=ugE*>h2FY*-#&dBYdvE%%nIPu?8yzjb7s0zTN}!6b2Vety2% zcMAED0+*sJ#6rl2K_JuanrEnwlx(Vx&a@*Am|H7PbJs56G*&;r$6zN$*zR5w%X^kH-Dq_UmD7?C8YREnvZU zJzsR_q@_RW=o(>aW1JCPev-Q6J3XDN0;r8ocPoSt(Up9?!F#du!6$_*&EYk~Zwx(l z3HH5(@Gb`3MIE&ksq^w#Kx0c3ff$pnZ|(Ruo5hj>1;*^Qh%H=Y*vXGIrg3G0V}=QxIYQ)H? z@=YLR8c_K+a4yd%6tjnx8@(JQMt1CXlVo_<{whrsfFRFOjE#-aAdQH0F7h^51LeQ@ z+in^%c|Lh-F_x;nNqk52!WFGD21J%mT`3RtfqGf`x=_)86lUynPh6{50V1}PmU8{O@hds5cFBxV6azLJE! zQj8Ob=jIh*l&)$NyDf=MXe9peL(39LCk2+kX=uXPvREB5egJ|_1d{=nzzPbn5uoo3 z!5QN{00^O^2$n{E7y;7gx=QvBP~rV*O?4OrNxAC^C1iic!Wy;T@3P-+lbOewNQd8o zFeylM{y`WJ-*$*V-;Df4 z8SQtfbn)lkn=DcCVo+CCRqYP(Cb5Lr#J!lBa%$2BGa}}IS<`L0ctJ~}6*d?qES17=pJv5lUa`?=!Q973%`>1m~zC8VRNkErpB@6@V=j_7k3dXZD zXz;S`@X(&BgyxC8>z@9&d%qReu~SSyKm$k-9ia5^vM2TSHu~|y$zgq$+H~522GO+g zCB?#$4&)!~w)zsSx3#j*kL@Grv7uk#yL$K=iyprx0UXys)34`?ZM%%1J1EA&@8@vz zzp!?A^Eg3G?1*jp+paIF8}(KA5{f}=D4O$ATy zM$DM;!G})epC;e!SXUTVxCr*gNmQbgVVw{58O}JRm6M(S{mi)YFzghTx{BQp zT-L$iVsTW^sjcbxB|2&z91sR1r1f!bm zef&e>dqN}?CAaVhp*ZjaF$F8!7oP%p5<=jF|EVgAX2=V!C*EnuD!Slw0vzZF8XBS9 z9le8UoQ};d6e(ak!mj12CjliZF(+5dhrW-TrD`Y z2A1ebwfVE$b9!LK!fss)v)>6pyzyAw`>_V6+kyVY&vCiX=JFOMLc>D-K7NWUpT`ws z)V&`Y8$}@1R~-QuC7=;(!h9*pvHE!psQ^*J7mJt17puHl2zib>>Bg^rG96|$s$g`V zZbKV_Bc$sC9YA3mFMoAxrDHeo^uq>*xlL)v2k?dd2#3a^yx~9=#1&3R?#T@(>fS#oxDqFVt#XsqOGf$xL)?t#K+$~ z_m>EM$(^#1laXj5t5ssup_FV4*eT#mhK| zO-bMlI6uTrlO8}FdCy;D+dtM+0VmH^TyuRzzznmZfJU(Vuh{iR(DXWS)*Z6`)nlah z8^WqKxqGXZHQ|eltaDAtkW>A?5R@WoW+rXo3Yj|-`eD`^=O3ZmeqVK9CIHR;?;B{) zgs6|(!tD~cGq@rYYl^cdR7Rw%H!o<_GrO0FA_VX*x@QVY% z=D-G!JXZGHF#3v34NS+`*20kw?**z;H5BYAVYl<4oEL_&`TCQu)@)3yYmBLljt`n}6I!Am-F9 z`p{f?F4$kDZmr}9BcsIdDhhXZ!BcoJqkzCmLek$y*ch=)aUG6>)?vbY9Z`>lssu&lR#fY?@tn#m8I< zJN(xFjEpr0IaP{|6E9O5I~T6AE)7rC&&LM#ypfq47f_fG9xD}7@{f8Lm|<#$QXuB7 zt4XWv#9l&VZ_MQyfP`W{kY)_<8xDP1xpy zP7IDN11Du5(_IOQBz&DXpCW;|qVF%BwR=Sesli`~@T6RI&)}pGM6r?KcHa_GK<(4B z;g~?_*6O-%_|ucnfgb@634+H)pEX|+Lr}Aj<}i6~K4I|k?(D+_L5Z8w(m8yM^8piQ zXgf-5>qi+IB{@{!I{0N9K9G167Fx3Kda~JqA?2D|<0V`@`+5-FIu?4?xwCIkdEuNu;X(>t=8!|z> z5V1v|e6cTG_26Ci01ZpqG;p0Bb$w3Q9==6jPXD8Oa4Mfwp(PA(*+LIwKFf}7ZI!5~ zNaZBm*VKK)EA4fY`WVvrC4NefVPZUh-Ap*G0{>o!2HX4m7slVmlQu&S8(Qz=Kpt2b z$DKa)pHXO5wHr&~$}^0o2gQ(u&8)Fs%t*=L-%8?-{G}oLk@W$M5@7Y+J|8h|C>KG2 zYaC724z2nH_A}pog(_a}xH6oNq&~kT5_A0Y6B5XS-VhWd>Fw<$Rq4r^rYq-ONQJfjg0`V0H?ns}LJ6LPJiY>hWeagdPkO5O<`>I|aBG^%wV74P{; zvs+mz}MkB@{hgkb;8(emba;U(W` z0PoANVDPw0$k6&-i~50kw9xrIIr~ju&qxpX-G>K=4tpuz=^v#?9_-In2N158rK+3^ z%rHD~>ME2oM4|k6dx#oE(yImF(hao<7U;X>9ou+M|Ka7c-1KqTL*RIm4f)l&pP9E=Whenyxy9Fk%0O65yuy zI^#}Mn&aIq9-;pD6Sc}ew_AI(eaDBq(nA%Dtpro^oY0W^&>1#1O~4sGUibs`{VT}&x&B=EQG zK##iTP6X@_v-mUn_w|zCDNmDr{+}Q+T1Fw5^lg4;QxHw)R|(#F!0`|P`e6=gxjSCS zZv&@l*w4hI;mdpk-mX-P9+$s;eLug+dnrAZkYeS>K(b{>nvmZvfhwUdqg^66 z2$qW~cHf(Qn6Yxs|1~l;=Bir0f7Nz#Y>XKkpdW@+0s8;3_f|XCqZiE$cD61#2KG>P zIr56GU2Rtos5w!-%kd3#_WhMCDel5l(j2-#RAaQl7!gEm5uWi!J2+M4B36lubdCGg zD2E))N_8`eI;S!}{YL=`rnyha%z)mg*Evo2t7>NS9HcG+Iav-(+`tx(M1K)PRw)jU zouPmJiX7G*sI%Xo&O64M^*|baTu%>~c|cg@|NSFd??-ah?W5%%Zg7eq$xoky9S<&q zSQo6()-o?pRog%?)b$ge_A8_(Bw4x=^dz!mws}eU@~3MdJY>V;puwRnJ+t2+=}xlE z@>Cb{;(+zcyhg5hw7CU?bELB-?pfJ$yI(5hDnq)-;Jo}3UwKPwVVvzxXPJF>T$6KdI*$T}*9T4X-1)o>3 z&{LJu&8;!iK`5d0&H|h;9na|*Ej-+rlgD71Z%EDR9zpFr31c(!IM8Z;8t(duA6^r2 z5?XKPrZp5#e%sbfTf>6nmh~n)a;x7HFItQ#jSSTEKex16ZOi$>hJGh!=H(EvglW6E zJybW)AOj!j<6piYx1t`3B5fsx_0uq`t=v44ObUVCT8{2Y@*+Vc*~oJ!b}xQw8nrw~ zS0ALbNVFA#dR13fN8>(S)obnDA;p`~I|;+Fqm#>d zMR~?;Vzg3ns;%X3$e*`O1&I*|=Y7jPr*H;R4(5j_|EIS}vO~ZUiO5A#jLC$(&X~@f zKtqB%>7y=NF@?6C11GX@qTgEjHk{o&5nQB)nkYt!EOBK<89Am8(qp~v4Sr`yNz-#p zK;!xdxkZ$cfjkN&KhLQ%9mArk>t`-NxmhtA{83MQqYhCi5U5JuGD04t9$KyR8SAxK!1tO+~!T?lEwlWOQ&X259q z-hrBX+oZJz#3NcFrRaZrRQ=Oz0y|jV2b*X@+ImL5Ki@8;VYMw-R!!(gA@N`>M7p^U z2S8OrLgdUBbcbW?qRvE}X2qX{~99#a>;y2R}#bKW9*>*lPbb2(Y5d61{-?ZR+8p-;H0fpb*;pg8O zf`3iXJ>8xq0QcK|5EtujG*Axy>pY2%DS+OVGDW(S4}r!~=7dUxWRs^vWKrQ{$x|b0zUJ_l(!cPOV{In~_$h3VfLVE!z&qfi+H?7-25nN*vYeFcd@d?r}WO?3s{(^;;3?-XMrLAXuovKnUF zqZHKlK{HeUrfQTQ=OawTv6>d|Cs7?SkNtg@}GRIs-0nS}yQW41%zLt{?d(_E^` z>u1?C&T%&*_l~dmfT?@;W8O7V$FT|vF>j@t)x}W#bS4*2VA1^C=kW6h(@d?m;GdVW zF?a$-#r5xr3DeoI?;GNSx4v7SZck48Y!P4|_D0%lSMco(8-a1fF`v~bGmphis!`Y` zcvYwv28(+i6ajgESfr!7UMhT%C^fEiSIQ>}wiXR6IljkWB~qk)`Ir7{LsRX<_(Vc} z4m|;`u0d)h>{N_i*bcN~STLXpHYkJi|!l+6RmM%Un&q-!o=`j(u95?=bHdnf<5E$$GlS|)| zoJy<}u73MY8dLN^_GfC=P|#5Y+ubE6#rXKB!87*Nj42toUMa%yUfZm`xo($-kD8hBRrvkakv7D?WM4koRPk*Aa5MUbueC&w{#sTN^jNj;%WyO#5Cs`((`!R+kKF05eIKvBBN9i4F)5i9 zM?^#{udgS90GEsX9*TdnBr;$(+S|-bNcmzM)^)-C{j&7*x-UcJ7H*U+j8!4$dxuvu z3UgYPS@!%ph(*X&q5M-3v=}?3Ij&|RLUUfKz5E{DZ~=(|wlvK8ESGYA z2H)>HxEX9i@GmPo!@>m(K%Ydt7y0e%TfeA?=I)#s;$B`Kz{{ctxciJ%K98&rspL;1t%E74nMkDQpF-J$RoAf+rxQb=5!*PK#rDUdoxwCs zc3x_0ElO@X1p6Pmu9FzNAGo-ChAb8to80H>Giq(4s3v`#pjYQPIdzX`-ishADv0+@ zyyM>T4h*vcE6*MGeU;)I18O41^IwJuJmXEj%_JqCg%iT9!$9Jsv}n#F&l_h!RTUS8}&KX&J3*!Mc!qt9QR z>=9@krm?VA*s0_~LOJgj{StKni^^X}e6mK^Xb)oFOB1JYg(VkXO2 z29^fiC8e!p?}hQmivTy7OyJ4;(OL1MV5O@w+H4KH7RPK*%A_W(*_);k4qep_i!$AW zG**z^D;duMW{9r5ZsU23lOcJUXIOfAu}?{PfYOvvw4bU z)H|{*nJWGbe`k=0MXw`-C&U*fiU*$7=YM@NpV4F}5$YK)eNm+hhX~sidI+N&!vvY< ztxT45GYurWq#EA7t?Ye1s0+pQAfD)*18;ifutZk!^5e+UZ`&g1vXM{-%f?oB_X5nO zN>D=kwS(UP0rb}`{|CR+r@sxsIvJQE=YMUHS5s8~XNPTuPu-`Eg&^fGpSxT?$<7w{ zS_=LBHf+NcK<9M$9@qS9DKyo8O2UJ zdc?tb`@dGL|9Ofmi969GA{jlDpp)uNnLv#cIBp5&U}t5m#Qyfx(s@f!;t)@YQI7Q5 z$IYoSZl^Oz)>V6ZizHi&eaaITPf9*e(=VX3c_88layZX$n24frWqvRlOJm$?qKdxdJ8~L%ln0 zZera%J)E=zF@38&y|b~9na`iu@9^_SL94lGe}Me3HBBauhbHu=?C3TseeX4*!{cvd zRG%8|Sk+T(dy*pUACgADWZ*Yq%LsTejXcS^lnp+k{Q&K7?h71#t^#f(9m!+LrT2@i zjjcn9LHkhD{_nA+mCXi2ur4#lW~ll5mY%*f*Kq|ThfnN{R<#=k(#}riwX>%E<&@dm ziVx~~+Jsi}3gZi0P?Uxq%OmFe{*y;UX!lkwo3xI^45Z})F6w)d_FF&n0sZ|Cl~`iC z$8($yYov7u&g84>Pw_DE?uR~AKUqiZc2(EcQrrY)cH2=@o@|A9MNr|+MkaYskpNdl z0|6KoiwBXvekibqnJYvHTogAE8Ehr8SLB~S3k=|aNKOk^w5n8m`5FCbivM6yQrpN{m@ALEa$v9`YMd8M@?x2{A~^E9`TtiA1h*7*T}WpzI51!zYffA~ zS(0c4%448#X5BdaNoMJ-L-FYjlXttlo@!gF!G~Qk^i9)WU)St=63B?rzl!fi(+eRm z5<~xi@Bce=;`ecK*~`#q6$*PQtj=9M^*}>@yy~V5feH@;+|Om8i&GS89Tj7x41-kd zANs(ihv*L;ch1<<(pm=z_2m&Az%!^gC6s}KcUf@w@A#q`e!P8Dj7IAfILtQBj;*UB zdQuY1SjdZkLy_`iq54l*Kq$QpK7!{lbY_eI!d{M(XO7u>L>`^Ur%04wyM4U8T}%0gh@kkxIe$%%Gv2pk z{gq%KmcDZ(^U^==Cidg2=Y0OhAp2DcE=z=_qvaG3)!x@@EX3uICxg%qkou*?baSG( zI=A$>moJCq-5a+C)Ql|X=;`J6{{;4a8d$9ck1E4x<XYK@a*y0?;lv^e)m_t!ie=LYoD?i*13 znJR}Lt#T_UP_Z=8mbTVV8!%XntG`icYAkMj1)(DgaQa$Wl7nli%3Anhl2Q7`=oRwY zqt|7w-J?_N@}aHcQsb`hsi{e)(=v@|RT}=Ev`1cya`H4_{zbzxg0590kQ!zOmYc>m zZPahwIbg=E^M7(j|GTbmBhu2+WKlTqvapcU-`~$=NpyA>a@xzFB!&PNO1-YXcP)nY zZGBnRyLZ2emz!M2Hz#h_{cnFsUzZBCR^78di4qcL#NQ}7SP3Y4AOgcw?b94m(b1&W zrK&YvzVJL-PSO?R*|5j9ij6+d{sbdOZQ>KD zqfe&o>%!X7MH$L(m6^lBKbZgJk6P`$@p03*wioykE3mw$KQqJ+6jPG}`+{R|6ZWJ1 zwA5b-W;jQe$ggbf2g@^I5^>YH?)XLwG|e=ywl7jxL;n4BIZh?Dr1&~*9A=l>ro}X+ zM_U(j9H{0S%6&*oQthO*s|0k3MG%xYmd@5YRWT46dWlr~`NlUC(hOJZARX)taIU0g z0mmwUkboXiuy;y)sGr>NInt6T|1aCVkgkyrNdVURP)iXk#;bc8==oC;&qlE4g-E zz1Dl3pta)#?&mHsoz$8aFtjL`parR@DgjtXcut8HvU2ES(_UD-djASK0`3Lq`3X(H zX8vp3;2kLLO#ZOr&ez*gG_*2QH)NJK-re&pFsA}sv0uJ0%eTspPfhSQS&j1n<mQ$dwx&OC9k*Gj(CEg3t0GpMTbb&tK{}H~QwSfqFIOez{+F3ra)J=Q?Jq z2K!Rk=bus_@O`yrRd(}|$Au>kh^f3I_0Db|m;y55Q= zt8p3WPHfaJQ8m!hWBI!6J!X9Weh=8J$yEFQvl=3|!u+oL0wGh==B^PPW0I6M-WCMR z_L&?I6l{fNHS_5c^rs)P!6ePqLA4-MlFFCJErN;>n`oCwcp5qC(fa!$eziJcU6=Ob zi;UM_IW>FFxNj;^&pO`AQWbM~R4T^g# zUc{&Y6!6tMe=A;vZsYo-z;KT$x`_;W+PLp81)1)BikpUekte_~fjSu!m=!s>nK~tk zToH4}>*$gFl{PLuNhUqtTuDHbw<*Qqr^8u+TvB=p+bEo>-^H*-vOf{!l!1>xOfEmrmp|c_B;{jGu5+Y%5gcP38V(S$TN`Ebd_&n;X^L z79N)$|0Pf1kpmzLGq$jU?le3omFa~+qq|bb1FC=CDsqWYyH?H5TDODhRp{2suL|7R z`~JTBII}~teeP>hl!Elu`Cjjl9sbUR+^6u6WNmwc!7mQkxxBh=U77O)3GSt zexlA3;A%(aE~}D!OvmS*S_~_>>-d2lp;o}7N4Gu@3;%Cyvo6dY*!j0DrEzibBumpf zE39izi4eQ$H)FbvR<(=MisR-NVSdQ;5IoQLlfb(5gb!^>LjcJ`lGiBZa5x%-?c5A> z9c6m_&HbnS=!G~u<>-zZF9*@hWl~JdO%pM&kn<^3<%?(8&s;Rjv~tW)hAB9E-A4dF z9~GeOBgWrN#}mt%x$7FQDd7+oxPKxo07%DCOjARk*855$%gY|5>7`r?L@}2kjs5y? zjPK!DSmXNY7kn!8U*+8-gXG@!UXq&NUSc7u7U%3sd*)6TULocw3-dO;wpRPY_lrhTcW*at0fY*Kt1)Je<_2eJ3GiIrhHMd^2{ z`2libB1}PiU5))b!M1!g1K7Rd6#u3Xtkqe#plkm9*#L^m*q{5r_O??Tg;%doz z;FM}F;*_48eQ|6G5d3fpoFpfMR0}-hLpQJ)ExA2iR4pnrR7l#}x<>*NuycFTI-~Zz z?o;!ptNH!)7ai%!;Vj85p zun+&P4kkVV@66923zmN^%bMLOw1s>GF>?Q7R)B zL`H@v{P-D6+9Q**4*`{Q)y19q5ZQEzM8AycREZINKwC{JRw)tDwPJD9Q6jLX4L;O1 z#^@soFWS3+;F$l#>x=d_hI+r=C&R73HELqOre<_8;Gr~4WuM%m&XRltlcC}_>gjv!WT&rx^f~WFP%3#)3n7j-%AJ=$f$QrS{R6Mhl+7=C z#^&=Od0Q^s`+8j4d!8xVKU9B+ux7-zSuAs7R~I{2W~H@1YdKtf(L$(StJ#^NOOCh1 z-FL$^HRE{1`ZF3L4i66!QWSDQ^8`8#9s}Ag0}KoZkRc%<6SQu%I~A1lY!w{Ua11!* zscpYq4>u%}GQ-)wi+57FPdk#V?T|@RP??sQM;YI%=UN)vbIW6{lg=6*PQj{@eyN?# z`SC`ELG;ziP|(4q;5rj}tZ9-PVHay2b9FIfTLyQK2-R!3(Ojs(lMg{ z+PL!a#na@`zbdbx4)8pNbvN7)R!F2NE0eXg9IeGDoeF=f>}}a(Ccx2!XzAP?iEDW- zwRJf^34Kh5`4@&WiH&|G?cpH=uU8Te)R&&B5bd5#zE|(xSkut8E@}r}mExP;vuqKB zi!fFE9-Rz)!0cw;DmoLz3eYoPLvbd^4MYZSY@58;@WxhpQzpKBlX{)r3uc(( zfBhV(>-Vwfy#(6ab2p^k7?yQJ@>M%M-tgn$A$t2>S5-?3+T`_}0~542mwCc{(%D3+~)^*3`8N zfPj~h%&ceW6OP(k3IZ%pJMS3kT=>WO1cd=hmqvITsf}o1vZ7$$bzT2jZp$P_pQvz(vifJ`k*YRs%$E-qqgp| z^*e7*b%aK&qkHR>R_DGU+B^jz`--1Ff94dCh7u8hMsNC<^)0Z@o4sPE5P65v1L;9P zW?;g?3tqCVLY_kqafUZ<4(yuiaD%p7J#pX#HE-zbTSu=P0dl%EPH{}K$4fkZgV&aa zbTg*4?0jK?_S4aLvf+oke}iS{g^Duta_9Hga`%>xr(4GnQMBO54@9KWMV{|b2;sE{ zU3-C9S}3BnjZo}+`f?B79vE_s{_|5l>yr5M`xTp*1>M{JM2*1o4q26IpL5?zbJ8Va!yNVc&2pw_U#!^#XuW^*+DU}@tF8{BG>~~Cs%&Q zk$m;TcGvN_ZwWamY;J8ce49!Ov(c?N<&c+p1Y7Nsxv5)|NlRVIUSbeM#&h9+uY5dw zu?R(B^fwx?T$a>a1q?c8D$r-pV3f9^qApAzCwLzBp1>59uKN!okFsDeD3Ncf785cc zfT;a+@l8WvEj8i# zgYZwUZ`-9N`)V8JNq>ard)7$ENoe1LP?5$3!L=D^%2XON&$gU~BhLzXVoU(fal0 zbNhj9R@S*X=4sJsM?y%o!Za1pJFqI-;U>M1UHV$D7NX-J4`lt`r@me==)?Z_u{byd zjP^E$7s%OwLO{<CbCZ3{aeXNl`FBU5{qN|OY~&%+|1zc?P((`4`b)H{U^RzkNjyCdfaXHhoo43}&m#@oUIm%BEeIxo1Af$G2wD zc6;ysL=C6_+w+8_Hrzg_WvI^d8xv0DxZwP3vkHsiJo#9N>OV{@d`tdZ6R#i=v?}p1i3(ahW{L0h@!#6-v>cU_TJtZ3=e{%kFyL64L_F~yx5;KQXy+` z{9k-JkB}attCI=jp7(*oLJ^3c9}%n4t!N87I_DS;7;a2?vghph_pUX3%LmB2vM@C> zJHC!G`oH^>Zl4KfYh9+l< z9~IaTjaj0>!n$ZNF`PmB(1K+?e>Ke#75*`%w0J>RZr6Lv4qtkxo-?QCr6S_qXsXYf z683;d0~So}6XWT7F)V%1yCx6vbbt%>auwea5GrRYc59f3M}t*71}V$4Kqjs(a2kfd zOn+zXw9yN0dl9|r0he*b^L1Apca44;Y$xhFF zczPY&GN%-LY%?9N4daoJr&Y7(0%0Ywl_Z4a=8fZ$;)&_eRN#Bck^?Ch5>os9i_n(d zvO@SN%A7*;Nl6jd9=kB8`?y?<<(C_#&ytX4wW2!ASwf<}a|T2w`Dw~adswGEQL;wi zHteT@f=;gRZY)+qvfoexO;aoL-YVVJL87Jau4LceqF7DjQ0eQ6`b+<@>zH{oCzo67 zHl;6dEhxi2eM&k@f3s1E_^@_-$~d~LMOjg{F)5weVY+DKEzj6&_$#usb!!u&Vz8Js zDKzHGqZr)b+#^$eSG3^P77^Nr>*HHSaq-91_4V;y_s_Z{behpx+WRUl{TG5&!Y_2Nv0Y#1oOAC2MAkt?2H5Q5*n-2AR zsok-+BK6N(M2o2>+y}|L%UfF{8X6k^>h{3WG}b45D?WI^(^U-nmnXW-9LSShx(*lJ zWEkWFti6M;pU4JkYfIf6YW5V;8Mt!=MD8g`R#-Lsh-ShKWDBT#xjAmM3d$a!3M;@C zF;c5|46yh6k-x$;_URfNM9;pF6+zK^JD;WHAo_i(H0WGrERvQ)r1K`^J#TrMX9 zP~#+2jB-7V3+5CTgi6w<_r)wQ^%rHvy!~pdSsu?Luf%*I2DzOkC1&&9m8_cA=?BPI zUjFHF7ZAdbSlZ`3VM{u=2~AB|wdalY4$Ks;Ro}^?{~4nbB@o<}AG_{AE*j%f^?_-D z^@u2P0QCiLX)+ba168zIu#BDAro$$sP+=NVxE}Xom{;hgO>{iIQ-w`39ccMS{*}<= z`-Byp;pj$jwZ}(-j_vNbXLvLUgd6$KH8hrhL1t!S&S~n}ip^Tmp~gQz9yt{n-1{vL zYhsR2ZZ~gWusV=c>Vg^`Z`zXf9b`!vR$}BuV8!PtTb7#Zel7xBgmyYL?c~i_$??Sp ziF;jt;oe<7@xUqXqxTuhi7&4J)J;gWm=N4I+4rPT<4JTlqxJpDswy}MNrdmtR#Mz2 zN{{&(@@HvlZ@nscaFqh%mD(EalFaf}1Jmv%cMq)X`owI^@5jdW8F9*V!E3V@HbteaK2k`2mQ&bOa~iI=Z^dPuIg14w|Py z*0&ggUF5sR=a3x3h$5N23_A}?%Zc@_YZ0q+7FMC?=?85pXuGhHEVX~-GVTqa5qIo; zkjgEOFM~-@=Sn^V|4~-`*gHBXBeo;Z=e{r3Nx=){+HbJjpE>o@57=vGULGYL{77|< zDT0C75&BMbqd01Sgr^<1wg;u)AUvf8G9tOye&-lq+t(&3bJ^3!gSl4f9JBJWb%5c- z#&`5!{DV&z^6=r@9UU-)%=gwHnI8Gbkk%z51yfHI9n3XL=*T0-$mEbwK?(Xu<~26# ziDXzJg5@WqFy^?H=h*K9l)Iw@`zUd=$`bMOfh$BK5|+Mg7tiqVTj^^jDI2BjtS5yr zW$`Tto6Hogkf9pikz2#ot+dPH;yA+7ZWUfYQH2AFWcPrhN7xGOkq_|$lp=0i;$xJ+ z1Rp7=J|ogGx#ltDfO#e>xq+{3PlLIJIvUS|%oO>$G`*sN_UU#xU2)SYu7*d}cat~$ zSrN9;RzW-n%L>JXUhMA(1fPt6g;gS2W@}X8Czr0LYfT*cXD>dk==Uj9ww6Wfc`! zCnhG|R#maz12-#+=+PnT=xMvAo*pY^+ZOI<8iA`O9G#XJ{$Z>YkCb$RQau^9R&`t3 zIge-T?Vw#7)Pk%A0meUc@MY8S*reH~C7LLsi;ne^F!fic@iA=*_lX09X#FQ3((NB6 za@qoo2CV4hUT^VQa_9*r9|uMC?-H&x(DC zT|^4vl3-ljD{(sP&y!MXekJJ;xdQC`S_cZLAic-o?LC}+au=Mb1uR(~NCW2>i}I*@d&j@VNc8WU81WF?I!)+=he`)!i=u7x%X84)3z z$GjE0wViag)UP_sf@qW3ePU)J=8hG73*4;Qwop3qyvoGzqP%~Pn4!MC|q7j0+ZXK z;95kvAt+aT%+_;(-&^i_idqz3gny6~U+hFZ(rR0wfN{5tIf z2jBlg(^*DE)xK|gh8eoMyQRB3B}Jq`hHh!;PH9vSX;2X9Zib;jP(ZqeP(Zqoe7Dd4 z_kQ3rEY@Co-}iN$=W!6x6I-t=xEWHQGaecu7b$zb4-!Z_=pUPFQG~a>8ayt%j|d-R-~L#vQLEr2T)Wf7j?ajWp-xG=B4!E0f93fY5&2GJ2Q-1x7FHkHY8g zAJCUP8dsGlRhegDwTpzxFcX(KIx0RjxS$JvMAUF#FGFBJ>+>3*s{Q(f8UD+*@CgsP z0VU;*GY8=_D%gH2x9egf9;=ilU>>2{m-Zp(04Sb^edu-d{N&$xW`Ms1KYVXbcl}EN z91(Wn-g$E~D(wSX++!gzRi^tf1faCi2cdgLvs z*;JW8+n-s9LGDTx`m_*!3y9VdgYVl(&t0ZPJ|Ed;?5h#jfHurvXpcz0YFQd!P{&C2?eV^l*);u< zwUW^HhnIi)WA=8b+Xv6hpMk}hlP{h$Zt ze+VOEfKTJ=n@*v1_i&mhe0e}UBshlO>psrG%?)@%nCI!sd(3YEjD#ZE{v$dvj^-0P zCd@PTzXQ;Ham^#c-rm3#v8CB1KT;N>?S2FgzXt$rFmTKlti-B70q->4$4^3O0#9gp z%^e~YsnL*W9AS|wAZYXnl6oHu@8;_H#1pC5rv4OPZ7|-r|2b#~E$tSSF$F0mEekD| z)JRJ!rUbGeoKC|dBM5{#`YH;!?dKTl%V{51-u#$P9Y)rD2~V>mm?&&EWztCxqiu_1 zn7Uk%o3>cGX3WPHW9xfXs1Y3){}qjGk|tp6-1!AD_Z?@G3Lx_|IeMKRv+C*z18dLefF2uitnCA~ZsX zZ{NK51t!r__rgE-KXaWo4$mIM683$5*IfLygt7_uf}^5B(dm~28Zu$gIdZ-H6@ar% z=u~9+Vha!s)5DG87>)JyqhW45+B=Rez4Omf4I=P1f^2?FkBEEu%K^V(4%9*f@*}(h zK65DHzl>641bSJMq@Jp=Z-#0=cC_~3PE01ASbTB3VJH+zifp%Q3F zGMJM;NYg-(W_UMl2S9xKRTFOem=KdUAB;w6Xg-O(f=q! zZ|3V1etrQPkYN!h^KtFT#MQsf;e9$lAP}8+5&N-J+I8l0kI-|a!Ul;>i^}8P&w5); z-gQ>nWbbJf6W!3StZs{<=HX%V_TO`2e*R>>zOkf7_W8X+Dh5e7SEQ`p9?1@bh5p4O z=WVtbU(Jhu^QIjgna^bWQy9Xd1b9hJA^X4L8{cElNOwZC4}2Z}II4zd68~#)04I-F zs`my)wHMtY$+$qGbp(j2*o?pAwn&cy$ocaNQc7lKE!2obC}MGfQOQV+Iu@cf9+2L4;&ez$aQ{2>I?Ah zM*Hf78Lt~p0-m426@9J4-_#h9{t`m9GB>b6lO7ogLSn#ij}dk{jZkCkoBfn=<-^yTYyp1_ARxT@7G%N-TJ8{e4|r z)I`?A;|rwH6nrgsMnOiiMw_m75GF$rzH0!UNEI?SXek z?!Y?~4_$>y9y5F7p#}9hI=qqUyhIa)gp?=5alImrQJjS(`X0SSZYm#W|17jynpy;M zpcr@l-&OlwF*uX}J@p8WmlCdk($AvCEGt9zX5pzieGX=gy!*VT>$+;~H~e#DSTv{? z!~HtCRf%8=s{m%iQW^&vyC$(sO;9s_kFVH^x+Mzo7a@@7}HF(;zmW&DBh%aj0=!<6Na zD1Ry*mM?4sDSaUVA;o8x@23s0pnj=9Wy&TS@0E1geFMD$4@IoxkGvJIF;V^Sva z2mDb+xyN8(Rbgi2O)%&4vT||2*GI8rw$T?o$4x4HI`QRmF+dao9K)26FcYWKI$K>i z7_dX5eZyKGdK7 zHN6bL(R*!m*lQwg5eQlfzTjOAI3xPel2KgmN)Nx=;0ZoEV0YYel(+Jf4ZaU4EH8#i zm^h)hPs$NH^1+;L7O6C9n?w}SCWt91_2%K;GR`?%m>MqgFC6q{ww>S47;b23qv{yt z_O+E`0Tb!<Jw{uI)#t1dT43*-2Ndl}KbPfLRae>x4%6Kpu*1Sw=Zf3YUj$#T- zTnoEXBH#YOTDLoWKX6n)s5R8;xe0T3AAj(^<-dNy!GV~Y`(O}UI+g#Jum;@VhY0ED zIv!u+{0^bJyj~4`R9KRusF^C*oXXkW8{d;nm^<9_+#9Vs7#GDI9N&=-eHG;G8tBb^ z+n_uC?XMDzuBdd^GUCK1!Y`a$5m11BAWX%HTzjAHguHI=%eR4u;#2CazcLnQhs0fy7PXx~$;JwxetuH@gDS9%&vjXn zA%gZla-vW*$*pe2IO72evyT=Bz*|QC{*6LSEoE$M+Lwi#Lri4Jj}t6PwgX1>sLtX@ zj2=NjD8kG3E!YuE?S9w2eEyQUF-& z=@%I$znpGTp_%EWK=oR{fOY7-VFcMt2Qa>&*%SNysj`&h*F^>g`!P>VwIU_>=;I$j zG#HQ}wvTlZ*#4y@O2S3%yGAvh zLn}?+r8bb3K)Wv-cU{$%Vsy}uvp;l%@jP&AuM52Ym%#_H)T#gLR@;s|0rc1Jpky`-j~d5UqvPM2oF8ssdFHC7}?UswXl8cMol1$Ny@s2iGT?3yUzo zvc0pj1MG5Ra`$J3>7_%&B_)~I*w6sip6%7+UZaCR_@itfBs|VySq=mBJ|x(^*^0lp zq5F3B!#4HUT*!pL0WM0=*_{sj(*67cI()VLpAcq8^S{ew0WyToKn-vHG?&U3mpx29xg8jG+ zUrGr;HLBiynA|4Pq&hl=7?`+-9RYyg-thbTK(C#qK)@f{=vY)H@qT&~Fn)@TPHmGX z!yFXgi3-FNrDH19^0u)}{G4Q4sz5_!RhfL@=wt%m4L)hTh;|mY9S)szn!p0Aj(Q)^ zhcrkrWhLjk1R?rD!AR?>7=XS9T-S(DfM5!wqtguRxKVYiPQy(nL4hnr- z*#qzrXjR%@PFBR|H@dIsT8_+zGHG*=Kn{*xMSbou zWn8I1(f*>a=ST>3>Fb{-(19X8nvBf1+VKRWGyq{=Eo2bg0eJ^TWCuk!Ixu4menln8 z_zwZ_-^m+jTj%#0H%gvw3=D8^7^l!mv26~gr;GdXQkIl_758x@X?FcMa@gXicM{$J z$Nz?=KMx47+Jmw$1;_HF$g#<|8EV>cwS9ScdExG}M$)J^N1J*m{tRnj=Ah8|O|(sc z5EUe>_|6mTUpVxsTTTiR@BpXDi94wHM*<*PU*GK|7$fyZ$W7yOE{qIQui{%U)Cb9>)B{Ix6@FkDhi z0`+WN1g~hXAK9rKyTrld(4mv-NAdF>y!JXez4^2O;%i=HqnSU#qoO1tstNSJ==Amu zU<3I!!7akMf;6v;{iLZ#P%_%*>&CsT5kks#b~(?HG}2cl z3>IPvzT?R6<{SF$1g-VYE)o}~VMl{0go{NNJ;ZA!t1QNoeBS=dC~l6C@*(6r%Rm*1893S%goaD(yiSv89l_cC4Z+j&-ZW%?6&=AhZJVM&v5l+O!brrU(ra2k{Hj9p#V4ZRG-nS*#X_i@W z%XiW!NEP+*ACajAeEYPtFl%cph>X&X^PZBv68ayi>`D|t07zS1q(D%HWoKvC%&npD z5`0>Z1%UYP*KleZ%ShjHD}2rUEd0Wj6>0l5L10AIqvdCKTofw!FB32pB(D&yQF`Uc z_?k{O{(dNxIn0;POVz>ZDqs70>z$PUZ53DRgh@(vg3|RI`B9qRwwifB9Wm-a0Dzp5 zw*cIK;Q%VtiL)6k3nj}i0=UHXe@!1dwHM|@E>X$=f}>pHmB?`2WMl-KmlE0?i&iTv5-T+X9^v$y zuM6UGrmC1&p6o4^7xQcURM(Xpyxb!%okjrh|35(gGf+o+`^G`b+TaJvP>IijMvpgG zYhh>ig~_^d*CeH)rMkG`LC2cwn&|ibBX4JnYhgU2ch8|y+{d3H`9fYvHf6&NbvsI% zT*wPs{RvOcJ~WJZySFIeAmugy3f$qr=50ItyoUbj!k6y6vr9%6GSVyiE$QYH+Ohnc z)0O>W;MrnGzykpNdIkmRD+)r0MuN<+H2g?r6vB5DG1Fr#wg9(?pabw`^)y8BXT_y? z$f78mv@?yZa!Hu}*NMK(k7^>nj3p;P6sa#9b z1>I4t2HZZWCb%{t20fn9yQlkYvp4$A+SpBc^|LA~XzE|AQX%O;Q)P$8#3(5Tq_j}H2)FW3mZF=45DOTUkZ5qrByxq7?va2M=y%z86PQxkCI;HBYolkg{a zQw-?Is$kX-GFypT1LrEhg#3C*sR`NO^pR>Pq|>$;O5Uv2BXe^8Tc@V&Fr87jD{7w0b?yC!xOD z(2L+)*}6pVe9tP%3Fc(hd9V0bmI!Xc@3DUDDRyR7<~-yQHrsFeiOCt(vgyc_QnEe2 zimxSoSn^-X$_POT^*}<$hvNx{qJmC3gE8Le>1m}1k;N3Z+NE~>evWhm$3P9rcdv#T z+^EcAnz3`Av^0vSCbKy!K$$aN7lz+_v=SwfBWi^i(YI5_T=yzOwhb)+*S*`96iCW{ zDm}$`xEScTKDct9)B)w1HNK~Dr*|x?s1-rrtTxiVO=>Kw%}SsF>}%31ZfRK*k-pTY z9;F*B&P!Aj;atwj289*b&U&iP%mMR>{`QZJ=>;Jm zj}3af>V9M``-@f(a=DO3Ju_F%C}%-OWP_PKh}%n{JJ^Vh+$V&Hi}|re*(&r1zRzIY zxWCdq8Rh%gYI(5@TrY-PY9x>oMUyxc_$ZFQlDJkzYlDkv+W1=Z)ZNPu+-zJr{hmaQX|9orwKS7;Vn# z7>MGDej)t}h3=Nr5Z84^&qsl@p+IS=5BfBI?3t*SCs&H<$_yLtY|_&6A{)<@F=9~s zy=Z&RUNeA*Nn4ALaWT#T?<{pRbU?r}B1_PXq;#Aj`TYx&9VlbH*9O1aZ~xEs>_Q;T zZ%^xF5vQm1+>lC_N-(^DST*%cPkHaIW4Ua+8J{Tf!bs|57kEcjgu#ahw1ylCI#bN% z%$@~!p~pI z$AS{5(~~)KvNxA_sMv8vu=8ql6bE5JOIpS)6+JE&LM(TGThQuLMT_cU$RsV8<@!!~ z6r_LtZ8!m>MOa;0jiIkk>mlPxK+UB*`3DFehoa1UZ-OFhr_=Q;fxKiR*7?^2!CaPW znSf>z0Jqt@cwh!l9sz$IaQ@fUj;Ruxoqpl47seT$d@(XH72EVtAflPr%j>5JVdWn* z!f@)vY?Ij*cnK=*fm>OaBIs~WVmEZVk-e$wD(HUIb!jamjA47vfwQ0ZPr<4GK|zf| zjlAyrDhvMjO-xWL`(As{6-%bufhImIVQX)$&A8>2Y*5O>#s?-zxiHl1Y{iqKu+gHL zuK4b2MQXLw6j=BJSLA>};bVM{so8DeHtpD-vDCmSPs@C74uc4~9f9Dt28Hy^Joh0h zt8_VEL?Fv^XG2lExq;q#7ySU$zD5qCew@PRhH*}kup(-(`#coAI7+nuEuaL})31!`Y#2X=Q+kF^cGYRq zq0E{}I3H+LYei}5p@~nRE`V{NrG{Cs9@r58F**9d?_3xDdl#D5hdKDi7jsANPQame z>q5czGjaa6hrZ^Ha&ZYlQl5@}U{SK~i24BL^p7mjY3}%8?m;Z7X9Dhn>aI)gQ|p-Z zVa}Dfetv2!EXoav`tQDUhQ}n55qYElgGpQfsGXIS-8(TsvA8Jdx+r9ETi!GKP`+Yz ztJ%=yQ_E!R1?}3hF(u8$lRybnL8avQrlIguhf3r0Cln5Fs2N(Y>bE2^tgMUUTv3p} zR5WWt_t4OgGI98yY}aI6pDe_F6=HvPkR2g*^s)~K{1u%AQ-1rg-={{u(!|_YljO`Rft^L@>+c|toLQE|Wlc87B#4jp_qljqxLJ>0e z;T4|M?L;LR+a9OOlr)?&1E9{(AWVBc)5x-UWq^m6W>biU>uccX;shiCo2;x0v56yL zTqv;WFI@G*)NqVI03pdjpAipb4(O8ib5qLe1_Z?0@GbViaCfA6p)g)&l$@@A%` zWilAQ3vWE<=lD9TFr*GSd^t-Y@B}4C?7NcNUs>~RbZSwGq}8)B^8GCvcsFOrh7J`Ide+f*9%?t;oKJuSurPNLd`12 zh!13k05oisLg`+4$&P?QCTrRpbbJc0?oE$zn=>ZF!@!2sIom~V>RH^McF7knjMmNV zD0Mz$)HiiEqW)a9QLBa9O4)z6j7~dt%=&1esHvZ~Zlq@RZspIeV{d#Fc-G1#JU|-H zj2Z4bWRHf7eI2=WX)oN;Qv54e$|d53h2_=!xb{8x_+31FEURrTps{9qE#lQE3~r>m zl_huPaLP#M{&1$9MUssZ@Xz)=t19=vks5(~m!c~-UZut)*CzkT$*zRPMoqO#rnwT|Q{ihgTbkT@Yt z2b1tJdirFjD=rWfXCKEq%omN<#OcjCaiWmnrNkUjP-kJ#(ZW?C1AE+*u~3-qtUzi% ze};~x{GoCT-`)(zd`DCp05rN6UZEhLbow;W`K`4^*1!Yl*9bw6dwcjNGjk+;mdFp5 z@WIqA7r$42#nl@Gc!w{OlU>NHgcWLP5O_U`?6xIwu-)R3EGcj9&aPaTi#u8Y$lW&e zM=!PzI{-)E%o2A)c{}CA$c=BjnAO+&jYO3#7C6LN-M``tHJEvEWEZh3>?ldw?(n3M z=x;Nek_M(&3AXeG?|&6lRjKBip&yz%aK9A5&uMn+{}B>Y zXY&YlU2384z&jiQ>S6pLzr~l?Zhg0B@EV(Qdrvl(j#trJPR{r&*L#17a$(8b;3eGT;C zuP$cr( zlNiaqB?LP2=lw^g^KoTpyNK;h>#Oe;#-^d%OwAQ|O7RqtBY%=ZlVBXV(SNSaVm~Oq zWK2v1g}((RXqXZx%5E|S7pN_e z^`q|oqsRM?uDdl`?iZ=RPf+XM=TclGz8lwgTjXPEuDSGzQRZpcTd4~|Ui^NS;-5=Y z`bHM8QeIsi19zA|@gzwFl6W?3$%PS)gVce|@hZEUurLe&%MC(w>3 z8t0iXn<%thyK6YQ|*8N-;&SV1r|4_yhGjSVe|h6P5jbglI- zMOWU1=!2k3*wSjqyy7cAy5%@dAxlInriuS<30dc*hSXxV?)vb$_7=r*zx(4o9(hgv zQ29j+Mj{^LkoLPKtGAhd4wbl>F`X9HxtCmFggZTZjOK0NijaYuQRY^yr0orH zrlJPOKgkUMMA671<+)c-`5ku(G4ulgXxyTeL~jz4zXhl|&N3+FRe{OCS|o}5x?)AIboGYBHSAGmQtwB~5>&&^NEen=_dc87&5!vLv8N*pjZ zrSJ$ooGg<&Q}pcSKGMI%e!)Rl&D~ne+mpH!7Q+Ue;Lka2Ua2AZ;~Q_N->EmBLD*y z%9N;jCFxtaxF%JNr(Z(CHz`7Q<8?3;6-`N)h?R=mtD~%b7Vq=%AX&KBM?iogD*A+& zxb~AR=OR_gMhRC_t4|#kIqxj;2er}3;cd-EVpwSWXB0@s3rsG;p2| zhYqj}gmVE3-iFApZ2~w+=Ozl=ZUEL|3a2(90izq3)f5Z9C&38Jc&|cv)deiE?aO+Aq%P_EOD#HT zt!@psl15bRU!zo;e;oq+E|V|(phKyzSg*sdyB{8Ss^LE1in$s^e^-k0WFJO$X55kW zK1P5vhZ~nvS%&*IB7%+P;Jb0tVP~(3_{+d7h87Zs@*hOUhJ}&g@9pg>sGarn%why* zslL(-=@j&rzCFllfnjbCKZiLSLA3*E0P{U%q{yLm-0a*;1g3=Hj~~tI+PaA9dnvt@ z7s;{Bs?)$2uBhqb`UfU|AOi!x^RDg&g%S-Ep+OK=LHX>cuoEhnCyu!6?V-?obzMw< zWf3MUp>L&wePg@8PGBDNaBZVRLeAIuA)+g6W*a3}HZS(^!H?qb!@>Q%-=y34^@R~; zbj;JVckNL4-RZ-Ue8Xa+pfFc8>;KBl(l=&q7j*;jAnA!)ymWx*EQy+}D9$FDYY_H> zGH=9`@h_2ZyBE#+h_3=b{egIJfcaF&2KZ>#_25v19)*acN%Y!0s6Tyat5TfBw!e35 zmgKo$AAfKw^fRjpY--Xdt|l#tbLwYpP!R88jt=s7VzU2R>_(Q0sxeS};q zI&uy0F0VdZIRroU$(<}X93i9dEr+Q6EER)-NF#h02U8N%l*`y>Yb>Iv`I@Z`7D zkv+r8_^Q9rJYM@n^Y_y;5-J=YUxp{=iHz}RTiIJ-G20}-cpP1bj|umkobCg(YaK0W zv)ieJg{O;@u$3rx6bcN|XIZYN<4Q^>0VX#-+{R{QbgLLzcnYOF_7 zv~duDBnU5HXWEAm9tYfo8)Ok)I0zaeGiZ#z)#T5Q;vPQuDfw(!vfd~T72g2r4-m{T zG1&QYLzP)nf?B7O%QFDr7urY=CjcZsr;_yre)#UtO<;Q^l`yTUZTE^efZffAXv#^@ zGc=1e75&~0PImk5cpxsvL5Y0GjSIZJUnMCFe7>~!VMvAtL`M`>k-ys>if985+KX z*20L5v>U}5rZ1L1M{BeUVU0+YeG44B9cQ-V)(UhSWW89nU!q+q?1fndj@-k?^`A3= z>2y(o;f@$kqT|cV@cQ~4e`RHLWFP*Km_Z=La$a_ z`;v3EJ#S}5{cpRBj#K$o+2`+xfGQ+y8``xP_;?(OcpU70Ji~o>>T$R5#eFlxOHT4- zw>RoGaChol_#|L&%Z;~hqLv>dVn0rU4{zbBbW5^wt{xIxgg?9_K*O5n0YWGE`CQ_3 zKU|+3OGz&DuJ&YtX3=J64Y%rMYnvLZV6R`l4*&8+YFVP%!>5rQ))>J)M{CZ9FD|)M zZ*2{%>Cao+S|!uwysfHIW-HB-zq6X@)jNpIx~?W%EcwC4*P|#Tc+pSZShWUL0VnOB zDY1WmcB+TWYS<$g{Pu+2|KM15lHQCv9A^BC~+dkdt!) z+JIIwJ}gBklCurdka?W9yI! zv1TvT(i(Vw!pUJQ2}#`69=z83s;--;?9)i!>5o?#=4t<$CL##ne_0b0&_oQ+!&p8m zGxKm^zH#!5*G*8+3MOH)?j@unjg8;&P##cwS2F|zBtF6fQfMkDK0B0J4d#B_^4!H> z8{(IgMbWDx1bArsaP8h@RPQ?H?@xe67A-4K>16KVvq0~BwP$~ge#^)|pHl@6-E6{p zk-rjQqb9mhU2dpsq5*%n0XB3jKhBt)tM-G1^UA?@vh6v(A_W(19pFx0rymF$vk zF@|_MtXhEC}wFnHFg((gA4+ zAr}`HU3c~pL9Wi${jh>8qQnf9HgN;b1Ry0%iJY~MUAwH-5pER5-`PI()QSit+Wz`* zsTKBL3+IGn=P)GL{>S{dBd}|#_M?3ZD&=443?PF)nBrdb**JWGN)!Q38wKH&EI7QR zgae`}r=#^AF)p`8UjQ`eYiCuj01i$=AFvl-Of!TZdEXsFcpO!N?jG(7*Mgp@-W*z( zU77~8p^l@5({B$rhb=8gyW(6nUzD)^h%!CIxxBwQyIwt9`sB}d^D}U#<|^d7p?AOVvDRS6cS&8rQsAHBrfcX#b@h(#`#=vWvb15GOAB3MXkY7@A!6 z!6TP)(F+Wg!up^)6rF2q%ZhH}qbh8#JJQqq{V&H@LEQd1N2R#{@%9f|#H^djFjrQb z$r(F?ix$zK4rRpd8JpGV{z;ag0~4Dzed>w+p!H(z*Q^dl-nKPYAcsin{rmf1Zd-#u z*n035DQThO3e}ipJB2rfkHZhvotJP5u2XLTmsJ{W(`E`T?6W%O11jK@AFI98VzZfI zVcg(L&8Ag=CFNj-hTP*5O}Ckdwn0zyJRHOGqCG`@INO`^-@PO?gu0w#e_H1}hPkAa zl$1~e1AvLAkpN~30&zn_P7uhF@sinvJ6*Pv*TsTcbE|Kws_a{Qa;rJ|(x=$#wkH%^ zmrWy46ElJEO@#To1%f;0dZ)EwfS!dhg<|D{)mT*Y4|7OJOP*4^fs$JxnK*dKHZ77^ zsvy=V(jbEH)lN=5SU&Ikzut~YZ99;m2YNf7PR?rN`ocOM)BaiMfhE$(W-3-IJ)MxC zGUXc3f@VCM=EU?5eEvcMIYv1tytTM^yLr}!uWiiw8y)Qb_~4mpi+f7H1WPig$i$%p z;cv-#r`}pOb$2-id3X0LHlv5Q@go-JZe{jexUUY?_UzTZ8PP74WIRa{2< zN}m-n2wI+kWa*-PhYk&@F|hK`VU7r3;G9HN%ZLl945&;IatFX*tG#RbfRv<13Hm&Z?(DV zJP)i%$iJ(2_RzR;zl`^d@vd_{6xX86kq6PlN2~MMenGV{dP~)r(n!;?7bU2WKwN z(rT;{kqmJYlUSvaFSXmlR<2JNK`%R@o}O=No13j-Y5=)d!WytzHB@g0+OC4LtV^zm z!&%QN$1GzvzoZryH`8QX7?iy#SMv3yg^0PeowxqbR>DMdg*?Dr&*VYeucBB|zAynm z0dnPoM5=m_tiQ)Oq+T+{uRiE_^KM1#0giyGB|Tpx-hktHmP>usO3OZSQ2Z`N@vPlCw1 z)XwU18fPpwcW}`B^l#Er&MZMT@TQtFGnW9t386H%89$gE&rNA$Ft~EWQl6m`^B~#5 z<5pEl_V1QK=Z!NvRklvy`7+&$8G2@8=}6k31OfL+7Oh}L;;&AG@yWQ#fzC9lzdr-p zR#&Y+E1J^r+{lG9hj+K%hwfPa0hfrjYM!ug@b+q8Aw??mT3_Ry&Q|tlh$hr|tw?fP z8fbaQ;H`$jYyFy4pKAb7z;7NmTZXPnojCMi$ASS4q4xUlqty^pDZdN`9w`XWmIjuX zpN;kE)>lA4dG-9F3Aqo8LCW(+>;~t46;EzxBIT&4vX;N62N@Y5eGDj5fZ5o?<`A%n zR~gNG7m^eg6T=GOvv|~W=ZqGa_i^-f+$#eH1|Bp7A1Govdw+@h?1MB$bw5Qibi{(P zB0D-uv3|`MKyKP-)C-m)g1h8uRtiF>T|sL#wIBWyeQM=374#H>Qs$`zY{8x0+qVCP zU0>*Hj2Q#JQwp)v`qe;-i&^HMc9yE5G&m&AZoF*w2@8f_D6cR{BL_qM-JjR9h9ViiDGP|-V{;Qzn43F%F}DbkyPQa`c=o7?M#^s37(3k|4OA+#O?dJvfRNFc}_x8kH8_`UOiE zwYGbLxM+RV_1RtE39X4GQV&}8R|PvgoisJR43tFmA)-IYxb?)MPywWs&enV6q5cgg zt~p;)x+~W>)^F)j(dYHd#_T~NwC97zMId#y85a-}(A4Dd_r@gHgzyV;VSU1M9P%PemP2Nn-XxCq~ZQyp&{Q%bM}E} zptEGO&Le=1Y2^(R&K;&N+xQFr5LNQcp84&NGT=p$YC z!?slC*(J4ccPK7RE=^(KXABb)N)*^r^@|q~Y(wvKB4%d{qpC766{EUpLpL>O_+(8ow4Huw+ls2R2Ipv+$BuDmIywHLJygkcs(|)vH&NU6)3Cbdf4b zP?!=kZEJeLoBq#^B-LbHIwltq)55d$oD)sjxHt$0u5ak)-U|g`KQ7P__a6nNv$lV( zzA|%XTw1!P9BbAE@Dad(?HNezD3Pw-C0xukD>3X|6LQtZY+;l0_O$!)YqpdTR8LJ! zFXG8!@lI%J*n!AUP)0ue3+Nt@^*FqxIs1KovY4J;{B>R!V*ZQ)927KpvjvRWA4Sc( zzEM9{sl7R~oQ{x&cMH4#NgD&c_xkZvYy<>oaDKSj@C3ECEODm53%qZBN}WBuT<&z| zTU%wgl-L1lMQzM|@56kFf*-Ah$}GV{_Yv9+)FhGZy*WpC5%_Unai(t{w0!|1F|gd+ zc&EtkHfvnTyz`BzHYthBy1(p2{}+|MJedBdI`Pl?e>XDi2RVWsh*7x7MiY+Q%vyoqW$XgVTt%lap91 zZP{)aW%R-ujrmwq1DQDACN?_CZYW6;?zpAG=*hXW1kgswv=nF*D!#mvU`y6eT(5V^ z5*0wzXJfTG8ys+~luM~FqVhbmM_&!SLX-V_?i+lwOWS$%Bhmk_s?e*h>FA|7YR|S$ zG}}4{h&zc*ew!N(t=z1qDRFXUL(~*o$vZm?EG#OFJVKPaCcEmR!}9j8@l=zk)KZ-A zdN*tkXIBwisSqg#E^)~m8SRK&~@Wp->f)R_n%1U~or znP!w8Rhoi@lQcbYCTTO4WouiaW_^D{TJ}}uP5GbAEOAC$(adZQ&uO*70>}o&t4*fX zc-$+7zC0W;7Uec(&Tmo4*BD}e;Op&r(lCfU($dVsLW_XcXDDgJgd&eLk-rGNQ^F8~ z(L*rZ+M=qL+_E!b{NaRbHE`RmGx!#O;5#oLDcZwK$7 zF{+QxOkpKAx&);cP6;bTWSr*H`bc9S@$$?_Kep|S?DbaGxS2R^5Z*ygo%a`$x(dO_ zRd0h|P=tZ)i{eILf%Q($P(OzGi;mTOW>uC@7+A5731(}nSgW0Ad7%|%$PAi=Em(#? zXtT^H8aPiD7C5(L_*9)1IA4g(^56a3cXzXal<)23QvenJlx}Q+@HqJ-DVbLoS72Uc zZEayXl@rePYQLjZOng-Sl~@1*A3M_>lyB0Y40_m>W3BbC!|1uV2t(xBhdXJOb_a1+ zd2~5Vxn>@OzFcIGNqHo?{IYS>2RvqOn`>@oQ7>-;KpyTbMJ-2umieD*mH_bB=Hort z&=f6jYhoWg4P;>Hx17coXMAh$_ZNVh^D*KbCzTDQ!@&7n_t4c-^b#3Bj6n6^x4YpW zseGB#SsVjkg+FRX;NhJ`Fr=ZA^RZ`w0Tw3MSVNV_3rp}BOWM?=K}=T{W^hOzA<0g{ z@iY8N%N8g=aPU0s*Rgd_?On+TURy#FfOb8tTeUq-*FyXLz&3P}mWfOz{Q5wVN2vbl zK8Q*}nLQZ&P@3we>i#Ara*^l+%I=A`mFBBOL&7UeRSgL*U`>1OgH!H?1 z`{JN|M_t~emZ72OM_r+qdC4X7Ee#aSfh0fQeInFOsrb+!v+t(WnXnhgW&2F7^VROLV_mj&58)JO>!F8!oZGBSvEGS|o2gv9kujt$3dXQO7aT`u(Y42x~F_&7B5unSbD7-1k29s$k{9yObJwq6(-_!aX&KDKJ zB>t)dd0c*Y)#rRVbRC7S^>7(bs{0|lx*Ga$f{%H3{tg1hZR<5eu(0v{xOnm2; zDibD)q(cmV=sGFJ65vWsxW|^=vjw*om%g`WlK7Hj_Y$&EzH4xry;a$@Gb(^4-ZvMA zP7nT&EMJ6Q{HZT3J2U+Kv_A$Ugd$uvR&Y4a0ry zI<6M_z}>GLsDx-xR8Hf1PJEY^zm+;h!ssQa$ZxMqL2aWJjf|<&%aReHoU&9$MC%dS zPFx@e0Tzm~d83$Orvczz8nv(U|%CY zeK>hQZvj^0H5++XuQr>cj66=PaW!<05Gijn=IcWVXUV<~-pqK{-*sEWKEA| zpZ`bHSw=spm^4C=R@sj_I;_Xhf=V5=Z=YQ*$)tiI1 zo<&jP?zN|@c|U$YbX}w@wmw+@YXhOf*bWX_sRFL_9*hfN->lv^7gnNKP*{j5V?i8k zyu}ClW}XD9=SW6$a;TebF8S+JyV0W&Ac~9T zt`s1v2nR0v`W5ogbYjo&+iKiFLTAlS=2^;|j4rrxcDg-zo2oiog*QjW9HP=Y@m)S<7#huStnU9F6pMdF|ZOh@j zZNIzbYEJq^)`&nZ)Tykiy6N@FUF*!Udwsl%q;FL$x_5SKtC2C&a)y2Dvg;{_@BGYJ ztN$L}V$Pmlwt`>cQ^KGWNxv&-4YVV#9rE&ZjJ$^>u0Ve-jfsTxT*wYS91VpecGNn3 z#+MrSXEezo*yiTjt4Sr({$t$|D!%1jf&gfH5J|w{scS^pFP=4W3uc8ec5cZ`h>p53 zdiF!_lCGR)n!i2$zt5QHA9kM?G)Z>v@9#tD6uW_frpf(%rFUHbe#|(((huJr?^gej zb%~J&vI4iz2H(<_5#MDgQLlr$qg}rJQ0H$qrv76FYv$potwemgMbaqos))|XFJ%@# zu(Xx^PtPm5ewr9jOHW{}DtVh7*Jr1SH!xYM?L|B#^MMVB8FOVyQ{!0@b(j3QPE)uMsa&*IK$uq zYV@O>zceJB4q=3~j;hS@ibiT;6YrY9#LE7bn%m};KMl{sq5BrA78G!|%G+ME3A;lndGBw$MSipDu#%+?xtC%=i5UOi)oc{Y4 zd+&e82b1FkQLcG!>InG+rb4p5iDxdBqSln0c0OXh(f8Mxr$ILTKvz=RB6^?@y*^i)JQ?X2G`OU|m!!KgKx%Nez>G)Bo!EwuCzgaSkbY?USDk$DbLOG!B_ar(60E<2 zUq{Re8pKzcBOW8yK&2i1NBq{03$<#3E9;1N%9_hK+si2U10U7Pb;1;KW?RU{Vo6gu zF=KKuV!gY_5YOGP^70j-l4%F+qsL{6rhdex`N?c74iwt<-`J9giFp<5PF-F&5Hde8 zicCQ1VzcDN;^N7vtO=mqsEWZo=;9a$a!(W|?gvRoXpt+PWP45CtMpxpmu$ig;sRf^ zSS8&VjHG$&uR4fDKWBjqySgm~-NROc8MirkJJFSN%? z)!#N77;=93T3v3$0|IRB&4rb&H9)(>=T8z8*ziJ@+FD;UqGX7c1)u{@mrn~hdv`drJf8_tH@vmmC0i)@BZ>783<6t?$ z5ZYOC_ugLRbpHE&DtMZ-I5yzOHY0QdACV}R9cH$yWAI$Z!ElC8^WIy<7C0wfm}ReF z%g4~U4aS4n@h`;#2ie9@}J~ls)PUn35c1v*R+gYvIX0W7c`E4>`BA z2cu#Akz@w_oqzt|-{bX~b*883w0Ve7a#Is{YNMyp)dk0T>t|m`x&;a<5u9~xnJ`jI zFHlUfUzvtxs}n{3=qv2}m#Bqr4|{_4l~({{a#jW!DUIUG$) zRTB#0E?GRp-+$3!V{_*gn4D%|v*7;xSBqK1h2OLTT@0!mcFiW`M#3s`!zSSOwBtD? zi}|Ww;|N-NgZ1)dA5hRm;>S@gr)0|fDOwFxF53oT#U5Cp_g^^M+g3(p;q5`_zT=B; zi6%~I2l`&RTw1(F79P z)34dje=4o!4gsp^47#JItXGzADA9{uROVtZe3IwMAG}H(~ z$r+ar>V<PrAF%sz01=H43-lX4Gl3OHuLm9gU?5e|BOpkQz3@W1|hiFSpiTelk>i+XOYC+hAsOgP5|SiS1ezl*p^~_^eqvpv*jc_%2j}|GEWl zo)*-+RD%I6xcyPK^)B>eHTdJu)(YrERK=S_>K5oPoWaDb#&kal!oApDqGhRk&kdsH zs~zlX8|hu!1LVI@l=5trlRgshb4f*3cun3yisYt_}gdAi0%E~wtBJ?A6J z^M%*ibdC0IV}*uzZvW;8r$xf4r3yH-$_?W{4sF4vAkHh-|g_LpY@2>sDR)hA^r?HTEZ$ z;X}qV(x1ZDO)eE*se_WxO1RJXa(_r)U#E92zKicH&ok0++bL*QmK;1kJmYIe-N#W2 zPSAbnxpw|(fqPK$3%$X$#`BtZD2M+mI-iFB@}kuoSg*(qq)>Iyj?E{-<}g;3a65nb znr{4-Nfj-Yl|N%1vdWt}QGyMBdWy|z+~o31#L*zI?=3ud`8)PBk{tTZ&a67n|HN=}ZZe;}*te7%5!1|tHqB+ezQHUgi5Kg(%w+%y~)f8f;2RRk{@VFR*7*%y}P1*4GJ>7L+C;9_SzI_S># z$W$kpvS(~(nna1+rx~}ps`xQ)u*HEj{u?@fokaCa0rDW*%})3~w;1XvtTKn>!*ln* zmS~zr>e>iP*B~@5DD3GkC8)Lw-|jRmPpywr8D0_w9jHCFmf;#AVMV+esE zmDOa1jTgeW5(a)HUwSTBiTC?Yd}$Wca%PDpIZnH|f{iH8hjO)l0#)l#X189{LW3BL zzh?;9BI->i#Eez4QG-*<|GxN|;Bu?eZiYNvy{pfs=Yv0@9HI?Qitc5zyORnfgE}rD z0G4)FgvlO$cGKVoSRr8by;Q+L9B>>Y=x#L}7jt2b>Y*m=z>l2Nm|>Cl945>A0vg17 z(iaK52(LQax{8c~nM^@{^Fv;$>xJ)DQ_R*0(#pC}T!N*_hB_ne-A1{w)7lneYAUT$ zcM1d?6$613UW5oz?Z74v+d&G{*P%y@`$H~)RkaQZN)9{`%he0`gvbW{I_7w(r-BUa zBrB;EV@!;#(&Mk|xUpbb80ip1ax!LhO@_Sw51hGLTO3oWuI{tFvKlfP7godin!yc8xRUZ#zOXYNMXc;+aV*1E)hjD8|)^cjbGO2bzkK{0qcDwC@CosZw1?yf%%G{;k> za!u8zlWR(1H(%?*3GDVJ;bKH9Wsfh*sy1=>iHC=7pSmR+CeNYjwv#(z*!BferO~!C z3v$S;9mB8}jkD@wdiumMhI)G>&x7l#U_8JPk}7|&YZFp0h@CBwN7Mr{k$&beg7!6P znZC3-wRExYK+h6hh@-knf%A})C!>+Hi5pR?!>k;~>ACO^e;?RU@H=b+2@<+sODE$t zpJyUvX-Y7u=m;Jw_Hrey*Te$WL&KnBJ+`C0rDC>85LdF+PD$)W8nM0EV7D z=ddhbdBR0LxxtG977Fc^(O{bUAO=_H8OZF8)ef@E8!NQLbaE5u{aF!$V6kJ!k_>}+ z;(0JgNBZ~1!#4Bo`sSO8r&-2?Tan*%n?3Qfn@siO8>-;b23B;k-8gLT7 zpN6WM`ndj|YDL|JXNvZXCzI8My}6%B7M9HkMCpF0nNzgWCDlVkch6H8?RU#~Q+kYjU$!e>;Uis7481sw~*GkLm)y zyNi|q;DncCN92-C>KS&`W=u%L4`C@OJJhZz4&Kf_XsQU#%qQm!c+A3ygQEqF2I>XT zVc(_^0uwYXr0U1}DHC|W8tquR7vOSoDG6^vhAFKSUMW%FZ z+S3(~Dy*AuGx$80=CTrDh1rJxl?JHtrvc)rcZYh9nzKGLG11&sI&XK$fQ>z!(SEp- z$5xC?Kr(&!5B2R>VNMP+|1q~<)Gus;?5JTnOE#8|{6Qa?->+&PuCL8n%zkcx%)5xP za@rG2d04v+DVtzcg)BAQ^BLC1oHPwhwWOE(og*PP-cL@ol8KrhCTr!3`u#V) z+zXZk+iFvI6dz}l2moaxXR_zMXXVXH1lwhca@^&7zbrGA3FRp)nXt6p=vP7R8h6EoJWj@8U>3F(-!xtvKDk$74rf_0|i_@y-<=M$w zlY_YEH}fZcCetoYo&JfH=<){@x4p|d@!ofMKlGlk&3Wa%Io(z7J+u4)ZkIBz(sO)H zmzo%=CR~o$#g}8vCU^99kFb}joq4!Nd(v~Cf-NPjh+}%};n*LvdLvOhev=b~_o@oL zbV8gcJOB$532(llxgpvMt%#B-zvklRJ`y2Hg&;l^p+OLo_ym$>9ic1qfr2gqiFLkI zF8x&=b_%9iw5A$l37LuE)k7);78a~B(iFC$jy=CI@K%<-ap+asbwYGBbqPQg_Sjp^ zkmN#%bdh%vaUNvV_LFEE8$Q(HKA`3oi!}`pbDW_>Th5X?^`-+!KCLy$nz?iWfc9A< z6ItNSu`n?N(YM`ozO;n*?`i@J#H6_tKw7YjynFY>YwKkE+ep1rJKE-m?&=te=-T?3 z^2lh~4?AA=f@n0Go|FNSqG|2SyN*a9MP*YRqT8)BJ zJ6HAybIcB~xV$_!#y|~_Ppjh~r`|;rR~mt0XT#!`H9xoS-Qljk(18HY987HFbS)(x zzu==(;h?4_L7%g8#pQs2t;Kn)S`SJoEFAzz>2!n$6O4ep(V2IP_@!%gc_rQsKN5P; z3pG1U4RCT13CRlK4-%HN65XmD4-Wn;RIvV-coT3Oqw+$z0 zlWL;y$pE&9#^YO*?&P&;d#3yvI!V197uM9z1aD|-bOL!3`77tafgsPPOso0S0Pi{* zm|$D$3=yfI|0`UDaNYx>vjxd^wA4G(r!l`6Xz=n(~B*@NkKA zYnxneLDlLpn*p$%@Bjxj2%lk>0*fEaj#fN|W}LMoP{(DEujX+8@(61xwn5KG;YHdg zLm;O_p~UE>#zKhVe-i;RN&g2Sa>}PdU`2mEIy|`38*NaLuR)<{e81n+Qy*Z+go9(& zKx;6MJ4XKj$A{)t4UF2jzP?UKOuT|EVGVjaySc3mAl`D{mqQMJ42Ar9_Cc%GAgMQJ z(qQLrLnK(AIG(=h$ze*aKodqrjmG9;G=?lkTy0)byM6KW^U}rZ$ z5XUp^bW$DhrI>;~a~LNs7UnRAA!Fo$ts}rdl4#3k=cS%aWoJ1ahK~4NBU7zkB(L_4 zRNxrx(xR;BS-eA*zEk(i^h>OfjnWl|Nl2O29?EHdEPd<=cOGAz6HGk%Hlb?ktz?dA&T; z9Y887MI7&!rO9Zg_>(45Y_hlUd9HB>uM+lRak#X--t!Kn^8-~@r=7e1{KcT<*wnGG z;Hf@U*F@5~OwKlZKQp#F?{~$seE@i+t#(&Vm!^lGaYdw}JQc=NmMo)U+o4EXZ9xn# z%-|Un4(jZfDbC)>>wauQ*$_EzTrD2P*ya*Gzq>|!+55{+fETZdN~{+VjHV2z$~QGl zuqgla3C+ztqjRBIvL}`)IC4vMwo#C1{(M)C9S_bvYcT@i+?*^iy=n7F|B_Uju(1zk z64+9STK^*kihs72qLr5MybYuQY(;0D7bg#osg_IooH}(LCqba&QL~ktMEVzez|u&0 zFCb>MlMLT$)tK6QzyxMa)0yxBA4+FdzQ9F=x2$I5cGp_I5MTy^MMki;=f0bq`}M*7 zeG@s4kVdsIp+BO~J}2Fs27;hnM7z#+(tUZNwtGqwpi6<-Im!P9f%r{-E3 zz4=~S99h#(RK~OW$t6&hw|MYj;X!{}VV!9~4>-J;7VToyfwm2Cmkxv8RSb0|?bGd@ zL9khDCtYmx49+v55|hwvAMC{`W2{BE@&zTid+O+IwGU2Wo@}VUc&Wq8uF8mu#X*)$ zxBD`|?&BW{2`EwplB}5!T+)o3`mi=uqu`2$nnnoPU|2j zKT|H{iZ6H}589xB$xrREYBI%UBN+l)Ij*k=ppWd0IVSm#l|6>1!EwO?FoNl!#ID%E zo5ax3%mp&nA7|}F-_1yBO(^q4c;&qM3_?qCqQ(eHUY|U({enp{JPVEBG*SN(8R;b8y|3Yeb?r+ z_3)lzOC1BLxo9-Ww|Xr!lfHp5v*!JvkBjKL_b-lKD4$!K^*;v;zMM=6lA$4zV#R|> zh5c@&#vEb1r~eMHu&n5ou)sD)5DR83t6lFq*S=%~Ag8siq0dLKb)*E zxuFfn#Tpa)B|;;{Lh7+m9JX-8r{RE9fih9{SeBOztI;^$n)%}>T4@(UitATXKMj7; zBk7AX4;+-A4Plk~g>} z8Soky5=XEB4u2ZCwFAO%5$Wl;Lc+htUcA}k2I%PA6?0^kbgCR4*X|E=mZ3{l?4WpP zJm~uVzKRk8=(BZNkhqL@%x{=n&sd|?ZbRm*LZWA zgX)U*RyHdWpwh)95FUZ5aCM>>O(7#--Jr0=d=>ckM!?$FS zcyCfhdp07O@#%Nb=_Ju-Nucv$)a@NgIY2$mR~#=o&O!M+etAB0n5H)bpsNm!R@ASb z=K~yw)H4WA>j~tYY#A}_rwy^#uZK-6XGsY~495m%a62&@oYy^B<+s-=f%q)lZS-HS?!obHZ$d+ZWDewrX?RWY`nZk*HDYqVL-FJkyr?#0?M-+IZs`%co4{nh@Y z(+Pryh60Xa$)ikB6wpS_&G?Rw56(JOUQ)q*=;-XQ_FWPkF-Iwn{UN!RTM}FDQz6w~ z@v&e=&^Mq+$K~_ecUsJHQ=zQ^zA+4<)UTfM&$hrhh+bKuGKP|tRSJlKA8Vx8j{WlQ z)!4zHwVBXRC&0t)OfI9AAvZ6tU7xvyDo|fYA%(|&Wp6JAMNpjB#2uaMiG_vAy74sW zZ8e;&wZ#%}agq7c@~iAXkm;oLgNAV9vx^xxUZA2P;)NE6)^TNl5jr3G6an4F-)=na z4-_u&dtH1m^zi6>XQt@{O;3|Mrd!Va@^B^L>(>%8z;dZXSCC7uddptNUBNNr^l2-0 zsFvYRKhMQYLZook&JQSR;QS#K995nl=o>!Ri$>C;w%4Gd0NFES33YN+F}k0R*P#@Q z*H{#UCv=SI5N%LmI=NPb{D_dw+#QBF+TwF^`V+RJWBRbc`ti#EBF4E8<^g;{osh1&Srvk$swHj_Y5Ojcs*>_$y0@Tz1@ESjB=&hQv`NHoXwi~JwWwp z;jPc1lU4G?;4xgc?0{P9@{^qR-^*;Nt~5{F zXzLcyHquv>VQee1R!@>g7+%Ssy|E->qh<`z#OpQvv+xc(RT#~+kgz>;+@Ifb+G{A2 zpJcJoEj&L{%KXt|W)5x~T^m}9N4bS1k;xLOF!SFu-+J+%+dUVn-CGJ?V9-xU{&J=T zQ5$)!EFkaXVnq43YJxbKI2wsMOBFB^Sy=QRYc=EuHgYFKs$fu}A^4!_6dl{Ye+m2f z86fPgSRZ|Vd`N7~0yr+VFz9>QQ$d`#M-8WZe_;m}i}hl<&p70s|BaxsZq4^@!GKYg z`Q0}^F2ZeVyJHV;59uZ*(>RiW-%UkoN0q&PQjKVNw=-S3gC7vKzq>o6|2XOsY^qd~ zqx{^zSMy9NXVAd*bCdpJ^W10+5u#6qw|Hl)1`~Xwjxb?d7b)!r`oQ@KYMXZuz1Fi* z$+MG(Pk4urii*yQ7}_KOV#Mj%J4*0|hMPLde+XKRFh&!waPnE+%6VPSkw7y#=az_j zpvcC(^ydm1QRsZO%bh@dl#&^>n*)UI+q4sF-x&+AznUMBO_(*_*(!KT-_$(}m z3uaP)4puZK7897#V1;aoU{fMu0~oTnER$@4kBCq zTPphCgr;Bez3+L^Q4BX8F2GXjk8|+a0Sw%MvJ$am?7+dzS?2v|f`!(*EB&pK-@j6T zq2J3}TdywHsdPV31THs|gd`wZJMf7ZkL1gjyXXq~Zgsq>oO3rb#>B=7;8bR-{`ZqWQyAlkNOD+7<|FN( z44bE&2-i2Wv^7D+y84$Sm*<`baRFtEW23{som9-&=p?zc0fC9*czA^Td}?hws?`G; z?9T_cH0DZOq>82@>=Ag#TkGtLAo~!fG&bOTnh_fG&zkFu>D3KEhuu<-H6JA}^+=L7 zVKy{Zo|8TK1`5Se?F@IX@>1Mzm)EEWU*9Urj#1sQVl`jo3U$bgMyTSERGP?i*u)ST z2U8z!4X-7>A$c{J2=Zb7G*iDbxvySga(?%Qn5pG!o$~8X`kz9*^wf0XE@v$wqp(r) zpI5b5Sw4#IF$MM|U^G_>ourO=M-mxE)+2xy5m09HVJWV3LCW*#p0^sw6ab=HY|Wx8 zug@irZt$C;pei9!A>u;b;5oGNSRkQ=JKhhk96FrE_``m11GJ-Og-5PIp<$u0^M$a( zL3*742X~9lymVYFt%|F9nCJ>u|5`K=wRd_EBQG#BE3e*w%nSy=AVK z7E3?hv7H_)=O~;%prf4sx743Tl(N6>XqyXu0Yx$ik+~`?=}#|Aq@wc`qwOtrW)&kn z;66h6%H52l*Pp7+^0fh{|k^@#lQ7}?LH$*hlU#3wYgK9@h&b75u@d_Tj? zW#q!u$`17ibz8|pw=?p8Uc&e|_HKtwvLS*KL_T$=2;@vsgAj5f9gxMRhE6d$S zR`C~n%Z#zoO{5J6%NfB6SQE}p#iZIvxU6vEHsy?(QsuUj%Zf(R0a zQP7w0CFTb9r zM@=_MAS(Df1A_u|wq&vRqZ0d;vSasdbRKUppkZ732i7^<738dLFIj!mt3NOssj2iY zdT)1FRnmFb;O8lPX*CP%{#XtOUSU^=94;{ihK^meOZ8$ZE2n>A2lmEz%j&#-87Z%q zepX4QU}Dn!?C{^DN76GSe!%8%Mg$n}8$b?NI+&QWmsh!j0fCRDAF&j^nCGIiqO!gvtE zxR1HDZXX&L7J}oFLgv@=cj%X$fm9myd$5uA1XJN4%Jueb*fv#|73Hs zm%(A(rcrO`hSps-`fYcKLh9--X0{YhN63x#(Uu7dW3r**pF1@26r-Nfzi*!89gVNj zdEMue6ERUt9OR=(6(04k?s#2qNo0@ltJ_>%O=fuAZS%AS_!IFOe;sRNmEvg%=N-U3 z+KtY*+}6cu^>=3)%~|N08dOe5ql{bfm%>*2{!f$)!q-p|10^?4L*v5RE8ON2*#5M_ zhGlwJDBQ=49R8CYk!i1=*kZ;xQMZA640oNx3D6);Opi>sv@V&ehPYDl1ZQN3>eblc zSy*TaIV_|`$l87^%6~;B4DLb~n{i_B&&E1O(L=(|gC35(BVWZm-&r1!D;ea>J!29iP2V{K-8u}bvo zhoy!QE8PFd*|ZX;6k`LoH>&+7m<-*s+UDiJo3p91Qh1eRR0XmxnahC%vl8_sM255b zKwH(e{tTiU$;8nI+S?I$v6SGDMZk1X23&dq3}zgJ!BtIbGI!s>gc%83vgYHU&+v|B( zznew2xdZ-y`*oUt>noaoyDQGytKK@KvFv|3wNAR)+YR5=p`h)`;<7KdbSG6B4fvRk#J0HU&zR7ePVIEV}5pRxZQ%h;N|HB$~Yc^1WJ#3{7V zyL-B`{$8Sl^pb&DSRQ7a5GVT^aQ>KcG1V~Yx6O#GX~>zT43yn)rTD-8e>X)oAV@J) zu>~DQnNCk936Z`388}xfQ`E;K{V@t8hHK#>zbVIu$HWXNqr;{t<#ctg9vsQQbquJ6 z^0CaniRc?DjcE|X00)Ynwc(c1fx4WJMAbQ{)3#lK^HY!KIju{F|5osQl{Iwqb~=Yj z@GOU@LxkI-`TftSPZ_pwutZ%6TbEigSJrI82%*T=+pnRm0tuQ4p`R=9B|LvCsWaJf z84D3gx+qk*>O*VS!c1n$#OTEmf;*K3op-%>;<6Wl&3@D}BjKz*KKd*IZu}00vY*P^ zo?+ZSy6lP<3Q%7K{r_#NZOwwD2KQ%d0S_m1em8e1URT>7taSY`vi*eP_IRFC?*VGu z@~ksD#q&tI9sEdy?87ys?07)i!`b44B-1_X%exb-eLLOy`x#>+P}1MpMJK~iyFcSX z#r1F&*VcZpt`-Ty)3%$$IJqvxfgSLrN-*(jQh5ETIU&+H?N_9#y5ix+aH_B)%Yw8Y zwu>$ypDny#pfd+tS}z!D0mX(H$%vYYKy-h#>+_55W6d`SnQ5U5Sq-zUUPO??_B#87 zk9f#@-!EIf1!|j5d@^Lm4e%YM{>InuTR`dpgi-~b6VR`<;KVMTNDF)uf?1&W`~+N%h99*I$$LR!c1QZ@fG5ico5D);iXki z=?%DHE7qasKBaj@-!T;*dkblO4k~PvI&G>&CIs++%k>CDeO82{I$DsUKpg#WN1Cgo z^U7aFg8|vV;u&?+#}yoCX*wtxx@KmPAlBwR=oKyB|2w+e)|0W^*2%Qic6ZKw50ld? zE4aVf;6R(rfv#pS;V{A3AF@&BG)64}kxX!(xaEgSTG`u6{CLLYjz!;@w?3P=pQ2BW zw#Etk&NOKlWuNwhM2H?8pP4n^pX0P2q3baNQS{RjAg!8AeDRh(>2r*5#&bUZb15;&rf(L}B5zlL5)d>y)fR0` z0>;|ggrD2%wU51w2kNns%Z-A+mYCc9X~B>@KOjdQFv?R{lK|1J$}+{`pOy+om#Kjp z_Uq|4KwMN>BvZiK7mC2mbxrOiMU#We@$!y#39-UVndxk8sS6NrC`TnPe-G9>U)WXu zHgGcGiE!eV->Xod=8|h4zWN7p+WtCez2lU)*Qk~)+N0;p@U*!3AW}ZCp`Uc6y-qvj z?QeVCTqL+TV01#XXZ(kM%3o&cD$}oI)LK>Llt>`)&zwFoFtDd<0TA(^baM7YJ#&iB zHUcvQ*)D}c!(#b;&W@h9L0X+o5Mfy%I78g0FnJj}FJ3M~8LSgZm7WBW7B9R)Ns#}SU&_4X@{nUsgp_N_E|LmG1;PM|v zz~d+P>vc1i_r05!>A7ba2id53rq)NO@Ak57$er^2)jyM_erLBl?H@@T7R4fLwbgQ& zAH;YJ#bQpZF4%HgR=btJ%$lLL>D zZS^>VUIcUYzUw>xVXqiwb##0seS1B~iFQ_w6W+Ftdt?m1S5X=Ky|Rq$1YecIKW@9f zO_H3I0ADuI*6gc6D)kDxD=@FB2ip4A(KQeQC}IAIw)mal`s}Q|C&3+>_oo?GsQ4ZX zTeKj?{$Xk9q$uWU%Omf^-a$r6Ox;YPVKovI@`WzQ!Pfexja*iZ++XQH&9Raw2|c05 z*baqZT63y-KV}l)GL+ng;KJ5xZEv8nwnY*P$t0$^HXI?!=>-@t~D zk5jFCj@;(s#{eNfL{PA^M7IiNZ9SU{xzt!5`-n!SDSqynwi>bVVctGTdS)AGY(K4e zmM$#rXzxQXBMiWcX5N~!-jG{~bp8R7$Irl>iZ%u}C^Kb4&CC!GI%pw0L_*TCSmsE8V%uVc;s%Mi z+VSTp=XwZ!n~+!Ee3_qm2#;jVg%73>65D+?7Lz;lM)Q1q^3LOcc7M6$)5KrD&(#Cbl?5(|@V|fY>RmUVG0HSXS&bf`*0qTar*1N@R9DMSIOIcGM(oFme_#dAl(WyOg0gK;=U+P8Xp0pw zQLpr7|4$;mll{dexDc>E`D1im}KXMpnV~c#Gt+CJx%$%_*(qGYH9lmKOiEo zkLilXHv31vV`>;8eJiyx--%8bH_cbY7g`#E;d61cfr}{5!OJw@HnEswP*P$5O_ZTF zlgcc1uEdnr>Ix4m(x|@{y^z_3c53@G_q?J~{Jm*fJ^?!d<(-kORf|tolUS^R-qPi> z2Cq>%E5vD}Sk*V?svh zXYDPO^Yy+5?A|2%OD0oU(TBG-PmN^TBDCG^H%HT!S4YZ~@4wcjj0dP&gB3S#{r2s! zr!fc|V9G}DWB|#24(#r)M1w=9L5NN)N}FO>Xew6$D4G25 z#n%=M7P4>XRa_Fde*bddW!JRye8mmQXbIhG$Kg0j@?+_L!hLreR-lYSBw+9oY{r6R zki`gi8^<#=o#_*8V`ET!@Wg9(gFSpC3nOowiuaTJyQ7@E@q_FCd}uNOTy07ghl8kU z$K_Tgi~!xE;xs`k)AfO*hh6j`AK=1K4AjBI4n$4`rHqmU$_n)o4gbhPbFwc#$y+Tt zNe35j4*Nu`wmO!kb6Lf0TGNFFM`wp_8^91b%omF@m6%!oPr4~GH=A0ZM6}sI3-!{; z)?zU$w}F$ML6zTq`{j!lW!<0GUB}=ECi(>~lND<;JSz=1p^sQema%!0O6Xe2S^U*) zWYcAt!J$7bW?Q&1MM3Az5qPOQN8TJBaetL=4pKH=*udpE;mxLGWAzh;Akalhvf}TW zzBq5J5i%AUydU~HJ7^GPK|J8%MDx4VD}c&ahMPrYlz#DiU)Q+)ku(0#T;<-9%gj$XI4*l+iaCSk!Hw0G5IV2x0&?C~ zpU6#Kri7H0sTq8aoJ4q(6)!X%e!Wf+z>c^BLrlDDw!kOV#2cxyyYx9&`MdU2vr((% z>oatT{a>($<<@RT_-!B){EBkf@8R>bY_F%RUlG*7}>CsS()-#1{LcfLn(SC%s4~)InkatCc?YUr2PuXCi zhwyAo%}_;aU%Fy=4er~|Ho%Dv9tMHbUu`*!1fTm}Xr+Mzfb7`<`!Cy%0dP|4f00GH zgjI2L6l|-f_o;nS1ONSd(}WZ%g(eTvx0)0owYAh>S$YQ;=*=Zw(3Cy7)!o8ZqvFANzb?X80^c`ieiolOQL2!R1XFkuq>gLtab&5BdEPc+h%*qyGd zn?+pV{cypUh4-tR?jJztI5c!-X*xUFsj~>?6*Tk-=D4T89Tg@d8k{Oc8PH3AjZ*-} ziQl%!8D(3dcw3ueBa9c2AvNBwhvul4>e$_JnNa%Kq$o4x z+Evs_shF2Fo*KhqtYEJP+ruskIq`y#lrOQB+QDjGKNSx{Pf|3rS#c95+mnq~l5oEE z(aK>S!)%o&XQk@|;;A`IMbEpr;%|w(HhDg$IURz zojS)&*EaZr1fxuI7#5Mkk!zKEcO7ruSMZhZr&wrljh!~^5l+8&Ea9=)YJg8Sk)rLF z{Dm~4qyQTG`E5dCsD!-pjfe!_)B!e=sBdT(CYv-H#?!Q?F9-V{aU2f6R(@~!?C<9< zBpIopsa-EZdz8#xy(MN>$-p5}2lXg=w5lMtJvYBVg}DTcTUGw?7Nvyhc%_Ag+tdLd zYHT&6D@4cts-o{tE5`iA?#94@Na4Lh|7vNiw+-nvG4T?9cnwVl*OZJ|LD>xM=cR`DA1G zMjh?2w{fINYx4Pf3I_c@*Ko5qrgU{fz|P*)U-mTf<4NPR#S>q98LAp@9`|2B^nbFr z=n7)%H=JZTI<&47sbSJpeAeo`RAtzB&%fznS5tv~Z*W8kf!!{?7u};msCte#ro1gW zakB|cp&Angk+H9iByH#Kp1@7O^S2|OW@*pZ#|dgo%tq|xW~gX%95Fs4vY!le*X%(V zrCQ^Z)g5woomuu}o7IT@zA#@>YQt#&Wo4{ybvfwlG5gU|&_5<_EeQ8$l2&J$pe2`3 zJH5EbSWXg#O56$)`A9tDkS&DfEPW+?g>!pkB<^#sE!=xCRzC`cs?SId^v|DJD@;~t zhtj19T6}Igrlx|jo7fDjPtT8#p;6!XEw;V5bi~MZg0*3T$>attK4`{LPg#Kg2tpqLcMKXp~0T+ zgWkHg3yl_J)E+kIj@puTgog1$B|-(8=3ukg)QsyUK|1l7Bqu$%;J4c&D|2Qp5z1)o z@}BzsN!0G&py|>%aP2Ehp=o{i)>>G|wkS%AJL8*X@y1rk3?+{dVJaP83OXNWbvMcr z?<&qvvclp5uiuS*2QGu$wqrz8p{dDQpUZw__D zwAMh4uk-qa!uCN^HzHMEUw;PY_Vue*CVdGkVB*@d;WH>WJx9Cy<>&-H&NP7bk58_u z<=RuvhNk@QWGDdb@A+=3%MV2|@r^zNvS)YS^36VeWC@V#xwpVO&(;VomxT9ZF1= zB8wncIp*9@PyUrA;s0amExe+9!|m?@hVBMw3F+>RFDPjsT|**?W-nL^fJzNEegOkI)& zJ6yE{MgqW&BRcbrh)`RMlZ&g+!&(*SwNnCGlMd&bR{u_f-2Szk+?X)bLgl4Ai5tR% zq3%@Gr9hn=*X_@dq2v}}R}=~lca(nm2{(&>dop#rvgE8K_4%_Re(>0{IP?+#16o2S z{ZT|VrN}RP%Zs{QLu$#KU`Bm`y!b-fvl_d(;0mJ-kP;6yi+iu~jdne#ep@G|`MZ27 zr49U)=NUU8Ev~r6gtSqELlx1zPRq{vevCHVG&7$_8d8+n$OJR3kQR7ye)(k2A}53W z&S)-HOY3KuHl0v9U?G|&tu$^}MU|ITaDX6UfL~#L0KoTM$ag4kkX+IQL#u1 z#f%mVq4~>n9gi-xUT3DK{rz>U?c-7K_w&_P$HkZBr@6~b?WKI83cW!W>Ye*f7V}!e zjgcP_fwbuNRe1D_@`M&4U&4tmF7K09I+k#G4EVplIVpc6j5e>cQLn_eQrFPv?(c{7 z2t@APU?F^7W8Qe-gg>nK6qr!%5RaUwc-{QLb9WgtNux&+n^l+2lnssbhPC5)`#dUL z7BSiD$!&cKcUK)ZrXAPEY9SZ7}Zzh*!CuzLD?=-Wdogy2mWSXT}G zAUCJ;t2*T{3p#?MO=!`5u8>tBT@11NI$ydP(Fp>H#=o;NMj8p5T%QP~kuQ4|ld$ui zwB)9%`s=f7@fqlcTv4_!w#@weIxAOecQOUd6p@;=?>I>e8~;qje5xnp(0-ypB8z$Q z-szS5A&z-F|GH{5FlbYvMY}C`>p*g&h!xt|a6;d&Kl8ODK)a3dXcr8+VID4!qQD>6 z)}o6I_>FD-@S!ME&X(Cu>j1V(ert6T^^hrR2P#cs(sEZw?qkUm3t%hNqKW(EeK=8a zTcX=Pot%*t(U1!Mj1&6hT~*!W8;1(c_$}?J@h>6x{;dnFfME7Li)#~<8{d%YY)&fe zcS{x6hWU?Pp{=227|a`?tRfhCqqU6n9>_$baHrChD{344XroC7L46u>+(C^sqCcTZ z?Ibn9EXCwj@Rqi;LcbuXyE;LKY1i-K`b$A7+DF=yhqqkNs+JlPO8?3O^IM^U@_#e} zd#VtYCsrc+0w8=ANnuZoFB&LVTOlIz>fTl^rW~X5_!1KUK5~sM*;+VEMO#o(QZj1X zccN}B(2!$ah}~6h4ZQCgH8!LveyQMg z&a{JJ;KzdwAtypO2aJzWI{TDC>J5d!{!+~O- z`~26L-$*k)#26A%Io>lx6Cyhzgy@e0%@Rf4N4#Ifed1@&2;_y}5~T9bu$W zlboAS|CIodD%6exy#=WK-BGXQ1YK=_u+J{6wkKH7ZxTJGz;?GH+eMwL&JW#pGmX4@XBW{o$nuW)U6F$vsuubCZSUQI0{~96t-_QS; zMI^8naDr*UZcDWc0Sk@O#%K=|kGVlBp#^IlZ}X(|>_ex}kS%S*@xVR)-&*T`6h}V%Zs^tnxB;2+$-Xz~-S*gal|NeMVJ4wc6y%ZAyDY?!@%wBw zH~BqNMX(t%`hqu8>O=W=&8?)qwPx0u;0Z%8f7S=vhxJ-{2XU%V#zbhe^-gP`@Rk5g z!ft(x<=xM48tFFbYOAFx70rPG4Q1sNAjM#y{3aW6G%~=e~ zpbS4C0ggY~=B%98p8LESngVO1?L+=|*W&k~0f^PB&3#zgb9YyBUMnko7H%tAGAjcX z77mhMCrbaO#@|LXKT^;|#U}U8QnW#*`JNBNs2Vl}iUU!H=me+j2}wGo@OsjY04Z@7 zV=T=;0h`abq3nPlJz}P>hBc^h>M;M7&`hRDO+dk~!t@7NeOG;8K0kiAviZfR)^lTD z4!&*XkLe}AfR>ag2|3`-Yf2gG@!JkD(t};;vjAMtd?>{nzI{J=YB-Ypu7fYi)^VN? z08=0q|B8@4A&omf;5Gl76|j8i5?sLtnz>xo{e4(K4l?jdEZCF-Fc+bYsIi)G!@*4o zB5nHoJt2^YJ!t3;^7`5X?){6vB6JS$i?Y0bv|!exB4*lKyY_e%6*atuGF__K9`uZ$ z9pE=_%Z#i^OQZDm@hK`QLc_$wys^?(284t0A{Af{Yq7e!KB3PwsIIyW5Zj=K{8O7A z3Co9WRocPGvLoG`dj&6R6b~4J)mA}B7P(^H9^xSsP;W9kYnnZkae!=mgF6L9b zRD}y6#MT<2hiu00W99Z`D7K22DEUgxTX7DtnfwTX^BMn`{?D5I9lEGGyg8Eu^c?sv zk#ME&>b(mY5Ri;>0wW~c@>JA!*;ALBl}UorAcmmst0U^Q(@ks1U{1Q*%hJ{BTG?Eg zdUDK+%XMysup@8AD$~X2v#(809~b#^<k*O zUHfm}xD}0!_gvs-tw5xN9TURKazX{A^>!>9>^7`s?<2foyJmbp(skzHZ}Egbe?fa} zn+^LCs4t5(uu$kWsK$)0)i^d)Q~wo^x-1_b^o80z<8GM&eJjPw-@g-NA={Fevasz@ zz5|#mc=_eyQ>+5{TnlJ%@ zN8T|?WL2JVPc@83ACphTR6{le(5F+=_(8~AEjIfvEaGCALh9N;C^sBS$TA=eu% zc);Ic?Hr<4y02kzDNn{8ZI>I~1Mu%0_X~rjG;wUCdAnRKge5#+!;bCi*ORg_EnK_9 zBtv2dR&T+eqgTOq&Og^H*-m5)n5_EYDnc-Kku^~|MK4)9rdI4XlvmM$8hdxROWQGgkzazrIK`b_V3AxOR z4rdBQ8u;5OV9}lnhZXFZFrobm#Agj~*R}9RO(N0YXj`Cq5{IpB@fQSvL6?`nEDg`n z$S@mqfq``i91RVl3yefMr8Ny44vj+pb)uQ$%(X>exchHBxxSGiqbGk09Dwp@?m52N zMF79t)|Tu1@GvTG!P?_uP~Nn;j+&bPNL6XogMuoruhL}OqxBm7uPQ~xRtcPqsmayi zXMzc}`}$S@`tWbgw$O;_JQmK5SQxQD$%nqlH-W)d^hYbKg}kj%DJIWw`NxntyGFn^ z_)qkPY;~ORJVELH_?={A3C!&5L;+G< z4qQV;d5OZoxrBml8VVKW!lb+E`+&YmhF8td_xo#;6!7@EE(a8bizW-?g+vl+Zz`lM z)aNDA0vNUJ-vT)p*!2VKt0)<7m`}kaSC8hC&Op6BulUZJJx22mIAF0jLjL+qw#dWt za~Z?L--#PDp!rnRHp??3rmc-PTYO5f|B`QY$06L72ZJP!B;ng=ip3V^>Rz2xI)2%nmntV4ISn-OKQlfR+aL(U_}j?c)c{=5 z{y}}b0AtQ`?X%-OOppW;Z+zGgM-&4hZoFVf!X{k;E1PGN|{`T=>QL-#CK=fjJh&_sD?iEE!%i&2E*k+ zT>p;<40uW>amMM@`rZXAJoJnr&NaVJJ7Up9Vr*?X!K)!Sz3_@44h{q~!!s78l3KwX zS4xB6jbz2U$rM}3*Z`CEcV1#5Bj@7ik=KZuQAd1BNq)UL?lCpn`%Smgq#b2 z?W(jkIP5gTn}|whMDgb2(;Iq8_$TD_M~Fd(X>IAYB8s1#k5Ed=$icB}a({{57mQHa z*MFLhlwgs24^tFT)MkIBz1a>0yjCf|nHKLuYH8SDC)TG`fc8w{WrK|rVvt)_SVu37 z*-)D{`w2I=YftvB*(E1kP-u@EgoHN7Cd5Cj(Rqdhm_UrW&@(vt9oGW$6c$wBLhd_% zxo#Lgh?hHp9atG9eu>JS`8JUl5G*)>HzuepTj23t@|)@3dw&q`+v2$&G_fMRS(}{I zW<$mVye0eC`T>mpXNb61+ABkM@WHQty9t*T`iOp~WIZTQ4tB9}1o1fG!{L%$Gc)9J zK>=r>2>r%?o<6052RVP72H01=+}sgJ4`{X+zc2AH9yP%H^H~)0Q%AmB(_!G83J1=q zbHaJ$rUa_gx0^+!{E>_u`m?PvXwe45MaWY$Q+~-35~Rg!>Q6RPopyVn z%ekSm;Fh-m3U1vXP(n#9^0Y?DT=5rf97#P9SX(V|0(V3&GRfM2g0cQ)5UT)ZJxCPw^sacLrM7{j|>F-gNk6#UGHzQ zj)bn$Ap>xGHDel6P{A!Qet&-)dY3X9MEvX}L(Hd7tkt?tL6GmB?1piLhD3XNgX8bM ztAm^qr@D9o;)_#~uGQ$NhG_kTsNp)*&H5KS( zcShr_^Q3KIA-8SGX<{@iEcGkOo@Nn(GSsc|bkF)l3 zQIpX`cXM$SnUTcfA`#tQf(fM0i+ws!r*)C7Ig|%RL^VeCA84jA%BP2)E5G4XmZ)A^ z9qTJ)2w>ses$39{uFFRMBZ>pPuc&o;PS2me60J#nwRW0@!O1DB>>iYjv7hi1tK-=+ zy8DC=)n#yYlZF*^xVvC3v?+d!3}n$4aw_8|u(o_ZL=QdAFjJa~1S|@J{U%LgYv);c zV8kxULK1T%M>Hn)15KA3s}daxSHuf0bTjqZCjL=1uC6+^W>LPOAyH+ok-ia+_ZMt9iP{>ZCJOeO?5!Bl!>n94yvGviqC^+ zhGu4z#@XohdWA+f-cDu=nWUhrbFXbso0JtffN}9`tffaf=il-SV^$rue`&cYDs!#= zrEst}SZ0!TqtXw^HgR6gf_?{Bu78ux=mMpj1t16n9 z1~WF{cxIuS0`3`!%oWMVZo01?KTwiNC=a5pVK?dmR#bab&=vpL$x(Z-aYw{j3O;AM z*L%>lG~k?zN|}t84Dlr0iiZb%ML2LJ|{PN0~3;dJEZpR-8)Y1!4h>{ zp9Ys|3}UzE6$>;!RSL;}1F}nQY*fSB2&B!=3D38|vc>CGq>SVVdUP|^qm%43QUQ1e zX0j8-wk8o4l$<=k9b3gLO9lgyj=flB>qX@WU|8pkR&3pa3)TJjG3WiC3WDXw z48XP-4+$9t;&Kf=cZOFZdq)OoqU5iM+}X!!yB2Hd;ATOdgmw5f`*I+WDKUUy>AJMn zjn-7=k{tSAL}WiU54qTb;-NK^p@wpQyuDe)#(djEETkJlPS%&oGx=zSd98czS1k?I zPqS8_Y6w0E(D!u)=9Vs3x8q{vUZy@l>(i8=uwkD^y>e>Q(26LKu^`Th{vvdI^}n1kBR9d%M7w={N2T)6Z9yfef%T;aqcV z8)Zs79fNfdwkEobNW81;Gd=UyPc*pSpx8jmEpk}fqeqC%yGX#3K%=VK|Jpc^@#+}Z zYS8B<0so7hcltJndPz3YN%gDy-#sA;Q<<23aF6rS$int3)4}cnfubmA)48j>T*rU= zW4~L1Q{{Mns-Potz*En34!f7{v;L_vt~wkJUnO<`t~m1 ztH+&<+p9`(edE?pYI={Sbuo{a|He>}uz+X?^7_EAn)su<)Jg@#%k~pq>k^Ein^e-sFqA@KO~-b2s&*H-H+gmj7pd&5e2T{a5UVcoi*W*{4?4HJ(ex!-fqc ztQ=Yqk@eVU?sVVE-;v#wbpqKs^rina$MG}uB95lNFkqb@ho^Hc|bhN8GxYCZIq^t3G+NQ;&ev1c~>y)R-9pzY*#9>cH0xUjFiK*+1_9|2F5wW6lk z*qKWITR$Qur_M5TXVrea&Fk!rv8e!^sl5LFJKp;R{ZF?lX7`XAXEb;f<@(qn4d}5F zWYRq`!MH4cgxcT5#C}FM?~3#68Bf*q1&g0w4nV8OC=~5d1YdwUt!4Yp7drVE^RC*}_ zzER0Nd}-g@;e1~rFxwpWHvp_!n~B~=OyuheOsco_D!#A{^s@i;v{uD*kZ_AQx?%87 zTCPD6zR=LzfMn-p#ZW}(iuaL&``Mn67IH8Pb36&}auRZzd-EY*meM!T)nTrT;qBW$ zMP(YO@*)5pX+-4yn*$vr{^vM~CGyrCl$emD>=`Kh1}Eb8Aey9*7-sEz+=6p2)8ER$ zk9{G#)*yG)$5aY5_rGV({{}v@pWF)mIDv?8410Sr!>*M`e}uo>N@D!6p;}f(PBikz zxbd+_<>*I;ycd=Dh_OUF{@P<2_jti+A1698j0swPv*;)d+iR2m$JYUfVaI`(op;*h zAbpxp83id?5ki=9Xwq01XQ2>YX4E*IE@j z)LO>viMb{LMU#S_TdN|2{R0=e7R%_gMlK+>wjab@Ocd30$OiX>-7f@HeO1e5LN z`gC=_BkE*}Rl(ra^QTAYlY^U@(F1#D&yjSI zOF0~r7hY4*fY=0rxD}j)E_|vqzK&?m&#F*0yK2jnI{FOA)e0CCv!_huKLXfLct7{+IMo^(Cwn z8yhUF?Al149u|PolwF2*Jh4z|5@cTC+*8UN@f!Vig(w=xo-DJJo&1jDX(F1VvTQeN zcdhR_7B9YW-)29_7M+MnFMR^DD1E5=xCzS1@%05>rq>BefoAm4s*V)4_sBt=L3w3VI2GIj`jpUp;bD{id0mTOA>tn5F36y? z{;sov8PpkN+>nld9#1IGa_B`Fi$I~?RJS4eMF3mqqgk28jQz~$n0=hr=IS`$AC~=W z420|YA2dOxdU_3wQe{6zvMLWur}CV9R{F=#pmc#m?%HT@=>V^Sx>CerSbZ<|Wj6f` zD1j1T<&ykCyQOD(8ZV#Gb!X`-HZ~+3!`W2{;_MW`7N9I{7*VHwSRgt zg+fRQ8a_fDG3>?|h)sg5s~(IOXuLqK3svkCX&Z&#o?@C{huGM;sXe4&z}+ncMspX# zHNjoHS65y4L!8zD?O%q^UYiDoD_-$d0T;lh>Da+B&`dPJ$d!1w-mr2$FcDrVZ@d0; z51RpVy93eGepT@Fv#|pf&~k*?Z3<})oQg+(tUHP;61lz&!p9HsKAflG^Uf}OUn-pK zC?1pE@>Fzcqj2dzQU>oS$e$ll^jZKJqg15Lxdkz#M9hla3fY`IF>H5yqO42>SxDzx z>E0 z(W_Jg=!ee~*pPSX?}!j(gBtWu8NcZ-SAz*Wi1**$18pELUc6LNR(nDmmZ+^>ER;sw zg@;Snm5uZZv$?3QX~teJSt>0T<~9w>QRzp=W>259rqLiboO$Qpoe=e zQIm-ek-8zkW4xfE#Y=A$s3_7U9A8qc$+gX!zyT&KFGsWcQ?3JYbz*@W`y|zBR)m19Yu}D+N?|5qOWS_Z@oC+ZpYM=tA9=I~4Z?*2E9}t{(Jc zgH3;Wg$^-Ndv0FoG@}nIe;(Ur`uW|f)#KWq-?OP7VtxH)_=+isv?Qpj8is-P1@{A? zbfIqR*3P&w{-KZ9cxg1A^pDruC@0HVveERz)%9<%{Lw&~=^?xaFDz>pq>b~UAT};; zxd#gJq{>_-4wmGK!>veu7perhMNMck4)VT*8VOin!6W*6H%WL+`L}L`!>+HX{2Esb zs+o|mg8cPXru_BsRXN$0IX`4mQYkighidZs$Wp+)o^2Xl8KW+{A)fv7NImeKP^@~K zlCz`ins5qk#3%TZ+}y0h0XPlVZ9bM#sk|1lEBql#l#>5w89=Dj){-gJ2*1^fc1cbx z>H+>Dh@V40XcnXrgQHxyzE+Z)k~NGb>7*&{*|c?%kEpm$*;zhc5&Y*SA3eBuSv?V| zeG8Z~weAx>vy~~GTIO0tV#RcX=D_M+Df<%8arE0vhu&!D|lFo z{^w>I2l{kER`q3J)g5oP_rxO)9+gQe#t5P1CApyv_uIl_abx3oqoX7tfj%fP&>=>4PC|r!_e3}Iy%4}a0X$8ms496J&F=AOyEpKA>1` zWG&f3!^)n9hGNW>Z)bqvLdWv#S;na)&(ld}sp@O&JR42lbOh(<#qvu%R}4yIzNT=c zDp+3~9gaUXU2{BUMMq*MRePcMn*Fk5nItsFiVAmVMlGbEy7qpM6_)gp!M9@pnc~(s zF+>;t2`HGrrN+;M9PuM{MlAoR(s3+#LyBkU_4``f>yB_ z6tBHs$|~fFNkso*Rng*=KfT{EB@%ZCgQL?ze<1uizG?4xWv~i);&Oz(*+fI^U{MNS zV~grF#w(~%Gb{2v6V}+s4I5%wBi!Xu^=!Rz4jel?L7s>&C6&=tX7fG2hcJiq!OYU~ zWFFr=Vs+jtc{}ow)u$xqXN3PbAo!2tr=|9+8n013o)@)1UncIS-FpvMV#~Ux=|i22GZAQ9ze9&p?=L{>w%L40<1EH*4+xEbP04zV~Ya3x=hpgDM5R; ziTCTo>gI3vRhkjJTGLP=j$t|>OatPU061zQg!%uc^Je=#!FIi!TtJh z2}u1xczASYXES?-7HH+ch$>focWNz*E77W>B2X2l$uL zZ%2wn;34but}7e@wi<%E(3il&7|3J7ebQm_3jT&w56i6)DKZt@=K(|rRd21X3v0N4 zfWoNRY(h!D*GCPKw%|=stsH3*Yqe`Y$;ZBKq3xM##1F8CC(9W7F$*3M2pGs+2hdvm zR1CTvJ4i|>f5s|o!$@Y8ZgqSl3B(q1uY@|3ytso9^8!n2hsiV`g)O}z&Bu>tw-O-g zvtlD+rj?CR#Fae5W7SHDm!RUq<*mR;&&%qaAJT+OOacI~fwI9d#Su*VPCcJ^(eQPC z6W8SaJle9nt6>}P_+EROocS@91`F{^=*6fG3utshuZT4hot`vKk1nz{HdH2oUWT-h zXmtEt5k9-EUKObP`*+lGHvu$9;&r4iFcp||#k;RMoM`<@jZQVD^50vWl;32@>f0kr z*^#-6&NgI_ubkO<23hojKZid$qH(rX}@cstRoRlgQJ zXfM_53!b2^-3(CQzCFe>sz5|c9r^w}&G5+MuDG~W%@4}RA3tc&ynDSQ!vCaO8P#Li?yV_x2-N8&Fiy+nqL=1+ zk8Z!HRb9f6j6kM!uH?DEKblv6xgs6i{_m?|+O`lgDNt+B+^2=^(Jq|nOROD{aeR!J zOT^E2JwhIPfGjhl%;z<6`f1#HPqbg&RtWqOPM0JlLxx#NQmX zwiXXpe>HrAxzaXb%u!oxi>PsT@N1%^wuQR2-GpP}K^&`=U zX#R{bV%*LbhB5J+@4JMvV7LgnHqhN|6L-bv>5|mGlYg_0Q7h&rQnhjXPbJw61n;p^ zOI-_3UAbLcT?PT*tK+ivW98$e+ZlL$e}(k9#EM+6-%2N9&g&WS@DR`_-YIojp+k(& zApu5G-#Ep#D6?CAU9qVRf`+q2C|OA9NOS1pzy0Jqbyz0P)Qbj2(~1r@U~#o57D--k zyaATgANc#4TCb-dS8Zf@SGi)n_={{~UTj0kksp5s02cHO=;|rxk~kCgZFb~^j<%w) z{*yY-`sB1vztAM5#MICG+3Uvo{wbpeFpDtgyKh`S?WUPPc917z!hm6~GA<7Jk*oan z^8G3z{PFnqDt;BIBout>(u*>BGl|Qi&s$kTL!}EVDdt#jJ$_OGum{5){*HBF%zF6CRuz z>ApH;4fnmksWO$1EeEVbpS~khze>_rv@0**C9d~f{5BQhFFvaYsiK~cmw4%Q-5zjD zaUUuf->RkB;eozAcKCByPW^?pIcz{M%o!*9{g(%8A^T|(fJI3nQc76p0kYF!f(CfS zFuV7Hmyac^extMfSIu@!*xxK7gF-2xDIJRe=z;%smxfHyLeH-`{7N6>xefeQMh-(z zI~-SaFo_2ylyIllF}KE%>FQ{DH0bWG7nneO+L^0=_OqAnWJfIPw4=9fQrHa*?)6n1 zb?&W(Ncl?-WnJqg%_4a}`&p8xleU>QRwuS6W~6AAgevZ$2#ny-w;I0w1Ayb3$<Ocj#AY$NW^>$FqoCjD!u}} z9L|*>E$Js-LzTOYGp6ff)%*}qf+bcmmvCa*ieVbt$6jB*GHv!ufn3t)6wIk~&{6X< zt;q#ps#fW&clSopL#xf?0GEMNKaL~uf-5q^$ra-5*Qwn)tGNtlUB<3`C=0tz3jT=BOMsRQF2@}{_lCEqG7Cpc$EcoT>D|R z!IC9hK*{`??7!#yD#61V8(UH9-OXn7p`DQECPwq^c9; z_ZWlIbk%=0yj^a=;I%jFQg@}BHmI`k)rpU@6pS(2q&cpi8ui< zr2mPw{l91TH0d;uoiy4nS_%Es2V*{6l3iJ|5~84rTfNvP?%6)u)*g(1Rarp-{gk2> z=1!!Aw){hrz-t?iTcKWdL(J*tE90A0DcR7)2$28B{}a4}{*_Bik9_0tD?$fg)n;<^ z&1BAwuCcB+c@R5Gu!J8rJU|k$Jb~VLX;;%A4y}C$AhxrtH!>eG#r(*yi1$Y*kw-BM zxVc7&HKg+mGvTRiU~DA6*@D&0Iqqz$1aW`TA!4%OqeTmltK+@B+c?mdC%zhf8o+BiFCLH% z7@IU{UNLQ(8+%d_51!)wCqV9O{xcz`-(weef=PdbS;OjaVt&6f|1~fauWUTeVPg~Z zRLqApg>2?TNJNA{#;=b&mZ|Rys69Ohz#U|yI7Mwv1{nYx^R6qiFhtt&(<8rQ>d9Pw z@??wd%C%skW@RKLdX2jcYN(IeVhQ*?SAep|=U2cu9CvbZG6HXW^Ka)QS;SLA?VN8# zx-fmzg-2K2W_*nlH@H@P;>C!Ds+u`f%5Pm#TIz)4SV2Z~1~S^jsr?ztP=pl_vRT`E zKfMXOe$w;;c-TtOoxbsuWTii8$N?aT=g(#0Gjd?g zPd@27V*mex|9dbYP$OPbnIDLrT!d8Nt}r$Zc>-esBYxd|E%+(uv9{9O$!8L0IhH@T zdbZl5ZyHjmg_f9@A9dVWEeXD9J?0)&bzL+h$Pw3D{seDmz&KXt#S8x*opMF{oK@Gx z3_!`|TT)knb4Wol>K+keT28lmH2PoE2o}lClU;Kz9$pbadpIS-U;6{}FR+=!{Nh zirTW-jb%m2-?v-ZsV@uzwybGFvsOQ-FApCPLfA9KVP1=&s)`85ya}Cl_w{U}9NKeS z#WB;__`uyOR+q9Zl`!aOb)7I1wvabk`YAfRAOTX2_c5>11!*fm?#_{FHjY=X$P z9}=ln`*D;L~z|PU;{}-qA%DH4_5nWig4vZk% z1o5i!V|?j51x7DGQOL`{$F0$vnDLRWSj|MGH-TiZ75HbiC{@?Kn`FY-1}OqM37C~0 z%6QnU28Xr(11zVNdcJWNhf+`b+qZ8@+S&=_2w<_Dp|-cOpExWjV=uLO|JP~W5lcX< zgx4jY8)P(5UQwa7vAN0e>{-q&u zVb0hj(^5Y(Jet!bKtr=~_^n1@Y-|M&>#Vz57^Rm7e8Ku)r}aK5|G#hQyS*yRc;H8C zy%p8fG#pwaksm)Qk}?V@e{j9F8W^kgC;I!h^zr@ww(mXZnA%{np`;Y7*tg#M`QiUf z^1=mlp|oHV!<;rfXnPR6CkvAK9Z^aZBYQVDGsbX91R&QB`zXz^x+(;x51Ky-+CSKw zGaw1cz2u~mNQWy4EMG8JESO_Yf)NR9z0B3jgbWOP@Ss^s4}|FFudvnG_k7^|AdkI8 z^W0YNWSG(lJRlu<4kC``=alU0DH7N^?oW$Qp^sV#>>{P86WreK$BlT2oIb1vr`zKS zzWh|MW<8-zWgHU0(``#!P2wPonHi1}%kKf+x#$uJLz zDl>(MoF<*go8R=GHIK}HezI>u9rQBD1{j};e{F)F*Mamqd07-YA^{^!CucPZDBfWK zivX|8pq#29Q=Bfpp(@f;>Y@)ky))O+jl*%aa)2UA+zF45`fS)R?SlR8oslQk3v#fg zx-ejt09tId8{Uq8Gnrsu+|jt+T2qm@ET^{jy(Q-UIL3f5B^s zuy&>D4Rewl^Ug9wY%KmRKxKMGDl0t8Af{0>tR_(1*|Y>#vPe9&0#8u(Y@e*_r0Iv7 zH-1PMdSy7<-t9#|&l%&o^gv5gS;@ya+RNDF!lSnR{To!D)p=n$2PyUHf7|&Uy#D1X ze0;R>j8u`vw14#dLgXYctmTdZmoPO1_Aw5&c7HA{|H|&E&iX=%ZPmGK4j#~NC}2D% zl<9&p&sH~K+l>`KrSLf{Q7H2oAHhvm7yCgac*xi3o~QxPE-+)=yx)tG!&*e04nNc+_^$8f3g2blr7d4u5`2 zu_6siNx=tV)_B+(&y%Xi2kIWWE4aN_+|1YxmWI?yLBK;iTm@C)*C=Ntg;-p1@p}6+ z{K{8d9+0=X`KZc59)*u&3!N1BpANJ~-`c8j@^=ikSA5V*;g}75NWN^3#?}3*_*y+0 zX+ZSm%^OopyUOH^&%H$zoGQs>5&U^Rs|QvI?>{{!->6avb|gy?`R$;k=CEN0CcVR| zT!A9TUsbSLH2X4a@e&|nYu7EE_M@nzTVAoC^sKAOc-_U=9Zm!t^ctq7V!kU;pPza> zM-(^5e!$})4%bmRn&umrtE2o*OB<`H^=)dquH`Yed^Dt#;oGG9dp|BVj>HED6GR;5vT*ZO5~ltMTr}FB_5D# z^+OPQRLtmx*R?={(#=~7@RUmzz%G$jrTd)Si2Ob%RW{GlRC-qK*!sDw4I6M;l#O-P zSv%fj8(ev@)+Kp$em^1}DRZvAXF9|#ya-t+Zw-@cI#M$Oo|*Q{!-YW50uZ_w1$Cp1 z!XVR6e*Nyp)Nkw)6y4S6_u)A1UU;gVD@`9yHHP^7y#!DO(CLCiq?6baw&U8Gi>lm0hBiZNa zzZUkI_Pf^kURaG%iCDoVrUi*ews(bJ3c0zwy`%Cr8t|MLIfDn>J|#Az>ON{MQN-;? zl)1ut#De(V%VbCzDg`8R%&K3t{fgj{;dAdSzDSfH4bSXHyL_Iimh-LOK!v$uI7_ zJRG7r{)7loqLu_}&l73*VWO;;g;v82$XCE*Ml>eI(Rvvl?oz%bc(_b^f7e#)zO3cE z+(!C~>;1s+FJ&S$cVl1il*yey_4fsL%WoM#Rll0$FHLz`SEd0RNL>(W`*djvSzw7# zdxMA2%3Ep+2#gLu5J>Ck^+F)bub^qE;1E9;Fq0`Rrjhn0>4~R4hP^E1tv04a^yKmY zmQWY~&RYBRY3o>ycwc0(I2zep?^IXoW#1K8O5nH029yY`D8PW|#R~WM1tt(#Tr`ohSzV(_>Gbu zJ&x36!F195GMtJ$JmUSc7Ji7ga7xoJl?Mv@@&|I%@IrEV}c$n8rfBwWnOZ{%#G(QWt;zOma1( z;c>lV87LrIRQMUsND7k?eFS8vTuf^7xtB$N4^34{U3B7=+Du~Q>Yi0Rt;jQ04*t09 zhrX|DtitkCmJ=V_PFo%30E?DhQ-2?B|L5oAaNsRNXO>MCuS@9+CYgX zk7H-Nanl5pFJUjOtTMwYB}PgM^Z-iDy%-u)cC_PI`=nq-_qnBGESMi;Iw9oq#WyS^ z2xV{e4-}zqftDGdh;XD=IEsy`S~Bo5$|1(^$x z&@Q#Hb-B$lbS%SEEKO z2r+}6^yhEirq1l;R!eVx8$GKaB+dmoDD7Xhh?k;d%&oQ7J!h5CPpf zj=ZL#4ENaA-RWpz;Xi7d(Y%c%B2(KWu^|An{98E>Vz^Bty*f9s9s7;P+OY4x-y>5h zaz$kO>V(9h6staYhpuV#bh(TAjChqk{NykGEl!l57xQRm_h~qB393&${KkZP0IkDg zpABt8DwPbBk!~7{-^u$Y3noJjIMg%Ij$2Vd`+ZW2wyTrM*CE4rX0`OoPNuz-(z>Bp zBC1U_I|mDb4wg==maYPHbAgs7tiB&mZM zg@{2usv`tjQM(;?VOIX&bAgu>+o<&*cFX|JD)f@ zl(KL_zbyTS!T00Gc-0RgtqYlwr0Qo|BOD+ilccE6lAk|+WnmYIL`vZA&dvS6LjEhH z0g?sUWB0WnIDdXMC)n7=$L@j_8jZ)hpJ74@e!MBC2@!g4xvisgbl4tbb-kVx=M^Sk zT7#78qonM-d2B{Rgv@y`Il|tiEqC(XN%J_7gkP+HmdDYq!&KblO96l4smoOO!k&3G z2cDM?$N*qKG=(?=B}XCJp_x+;N&0{$FAS78G6U*1@Fj!l$AJ&M-W<`5a?qsH?MT?X zG@i?Lr_AI+OgG4SP5b}sgOP#86szTz8>(>$jKVBEml~y$EkV5eSh(s!oZK(E2foSO zVQ^U8R{7H_{75KoC-BW$8v;gV!;D^_ju0YMiLuj=%%`TW{Bz6uG7NXl#ir%oho7pW zTPV?pMy}9FygXf8F#(UVgIoMGG0WWM+R^i|c?rVp#)kq4EjoSiByeps_aM4ch zoj8LK%7yW85q5(e4i6(o2R}m}Sp%&+D}G*UTATXI{l242pr}K~%$rR>QXOg}tcs zGtLr#t6klUs~NwD)r?j0Hsuw6{@gmm&_N2^Kki90?K~Shf-TQh3xh!=w$nxA1bjyvg79#TOf=L=iXNZ-L3xBduDN^ z5>O8S8bUx2z<4-v%rw<*@pd!xR9)q0j|@uZK*}4^!@rn?H;l-Ta*EzK+8i#*RH}F# zkOYx=j-S6WL;=x_KN1w0fyKA-*^Lx@7?{=0l(HvtJ{;N2^mJ$xSN+O=$nupFlk1%a z5V})RGADCc5bsLeRr#1j{$8d3)cxkpoTzOWxOmuO)?_{%E>pJPkse{Ghcf>_&i@MA zz^7i8>_vkk=Yq2d&f_-EYkidNK}gu?O_)Dmg%op^#o-KNpG z6L6tvdWGN1;yCuo97?~dkyN1NaqKx%mji5~B&Co$f6@w6ED7LgAM_3s$B!J{i-dpnWd7xeIqcB$Whd0MSI=&ILcrK#kC4^!xLk&Q z=IgtFA-tX<9XNqteWWnMC5#&C!Z5rNqgZcc$Zvj0 zqYy%|#h3s7H94&3&pb&WR$hQ>ZC<2U%Z^V}UEI?r68g+;1ndC(@!cd%B<$v?91nUB zvF-ZLT{F`Q!0BDCWI^^8YA4mzq%lfvn%}hoZ<; z&(o!qcSY1}MKlGpcQ2X~Aq52+mU<59$Nv+Lewn|#HX7#)1Q$}K#BjE(tJR5Xg&k6b(&c2;B00;-;alhSo}laP_cOqEYVj&h@E#JwpDpeBtDW<-cV zFoGZ=ZQ`vN<_K;?j#F8&o);gD-+pX|ob01Ml-&AbZhBlpg%&!J{)ty|@|)Hb*+((V zYn4i%v#;rYGYdzfONx~&pc+By477vZ_^sPgtx$cBO6Iwj&13I)Y?e+xl!|c)u=UV)laJgl2$QGXz<|sYS$8g@Z zi|$|zvP8kdcNE%)opbpL-FPMYx(6u^r5nP_vhiRRQnW?`gD;d+%t)(_(qCv0_AEzA zNqPp$=oBnGCuw`EENBHb^d!=|e2!~dWDw5($J1K{#np9P+ueAefe<`cfDqi>EkJ_1 zJHa)$Yk&j@?(XjH8r&fShsGTmclh@Gynp@05w%acYOlT4Tyu_bjiSlZ!Cxv~4i|s* zwbus8wKO@7#9qL<9j=h3a4ifNAIxh^7`m~C}7EV;SQf@SNl;ly#*I| z6iAQoSL2}h$h;-js{#hGt0C>#xo;aoJc+1$h4&{+ezhm4f9s#(IR;H48B|@D+E#eu zoz+FtlQgMCWvQ-ugh496L=No?$Y^uTQOJ5xRI!(YmC3F(3!Ei^nb9cmyY2HNeRr%DZaT{2?RyS0#laYX9ZiN3q;o9-#B1KMHbJp$VL~?+)7u zNM`o}hhP$+Q%iC0A2tS;&Ip4w!`o9r=;|B(PUV&$wYu3M3oB@hW%A_O-Vu1ULlPJdt6 ztDk-~r1MS;nOcGG10W}VdJZZjxzW{2DYQy^pJ%xLTV-0l&aT+Z8t8sHd8;hsG-)j&6O zRdCNaKJR&+*i8H%D@R7d^gP_#+8O=l#Ub=&`%=ViHm&S1G@8H&zFW6QXXeG^DF}&Noa(<~h4Gq7$lV*V>P?+;}8Ltq1 zeG8KLf->NUn_SZ8=*Xt18ZR|!CbzM39D#VbYkczHg3yJ9^6S$b)j9$0FKD!4Iog_k z!_hyJ@g+kB1FWA~b-TtxQybMaF8+=3Xf*V+uzymifUhb$M$O+&{=ZPFhQF49c6v)a z^P{-zg$e@$ay>tPg^R+0?Tw}1DYGlbq^3kJ{JB%`WiBmyl=Xp!j)a-`pn@v#*EP@| z7CApye*rNdC?eHE=u#-s(*@q?G~M*SJZCP{4I;O+z@zXD8eLoYVPrI@`OuG|nSB_W zn5@Ko$A$(Zc)rDA4c2hiZ*io}qQ1n$T>%>6^BHsbU3Rt;=QX=p_=v?;Y3#acrj2xi z8hb8P6D!tB3N3{`{$-bZFZ0JH>tu&6MES2EU`6qELL3QE>gc8z&NPyd$NZCRO(>5J ztYrQO*9pu zN_z~XsU-oH9C%0;G^g9d&aJkU!nh$>`VB92V?6mnvfyP%eM7Pm?1SuzMSRvzuI&fJ zhaU?!qkG-#Og{){H)R;QBS&Ve^c&r+1dHnicR1e@L}o4YKd-dFH@k1JFl7q=2ppw$ zcs{fQtWFqB_6DC>;Z*}Qc7ev=7F5^$83HKrg2SC7FY%+^B4mkd{6?ecbV4t(DQI|PAlm3!W#PYRFBK{xr6csc5#E$|wBHfFFgDZRJ;c?6z}21f6N zN;JP_qui3N^sd&v)9uvuhwbz5@U)0aXu;Rc1nPGwGwf-IDW0V8!W*)lOWNz9bVH&| zzvX9Ve~<#L{D6n$B3{<8exu|Hv6r-v#SsHsF7Jtg(2de+eEU9ObcDWxe`ut9QLJ=yWL79~9i>-jX0bGPz#`GXp+fABKhlGIPG`|#gQe8sn2;*tuLXN1mAVq=>}1S!~K zIs*!&sRk0hBe&0cry0{ZPW*sV)ky?9FulASCzaD4&e|GHHdO%JLw@w1!3?(W1)&0y zf&d~VYYgF%vX=xr9-EfDls_3)%gaHWa|2U~DqKw#3e0~u5ED=1_ zjG+{R^+iUGTwx%wo#A+`2A98a8#>h~$m4O$B2OY5QI^CE@TTD~NEgD7%bjgjW5c)V zPqv4*5dN4eIy8XhD{-Mu!R$N^4w#}h7&gn9a!?0gghXjm?R?7j%-{u3;vb>Xr!lyaJ)fBRJ)M%p9(IV4~E!Cr<0X zKlR%HA+ui6N1DW##2(g1FN)4dJ!-$+szf4czyyx<#cGTUOe`t*s{qLI47+%6tCV z{B-{sa4Fq>J^7!-w~8ezap%^|9J9C6NB=6=IBIJ!quQ&9Sy?6YlI5GxsjXgMHOO1z z(&I;{!p?k~YXv``<_q7OOoJZG?zXSa^oQdO4HJGbh`(H;>wTU3KXyL)y43^arMUjw zmQZU4TI=f(CvPD*M1noIsmxcZ5)KUvKtIoJz-9n~`2E3w%jYun@$6Mu_$7c<75|~6 zqLM2Foeb2aug}8rmoj-a5YN_nMwMiVPi`tzL{m>ZrCUDxh3%)wnV<&CsLuV+$gsGa z9=2R62PKUi9HNH=U`G=#sbO!YQ{9nmzMsP?sXP5@|_Ksu`1YE@8p^!nSXdjE^CI{Sn3W1;}2NEXf4uZzOWH=`hqx#}^h#P@ zFBTSdFb&+yP%#bM`WK8Yte9!3;J&4Gg)q8JCxG=UY*zcZ#_CK!yFMC+JkO$uyQE-5ucn6KW5FNy7iP3AT>Mv^H@k||k}NA<-o?I~d5cd8!^RF(rKJ55 zSEnQ$7z{Vsj*f2k_e)?K=p7X~BO{uYB_f}G;smv*{1MS~=O)`qLH z58CJ>(xn3P>PqrhBM6IDbaaZ8&FU&jRMDzGC`8>&5SKK*2HzC~rB6uL~8`l%?1iZ9B^g%fY4+YJ5eg8R9XM2^mo> zKbjf*7?_x@Z+PFR86dTsiH){_#^^-Y{m{Bct~!gkLh3ru)sZW@L!z%y!Xe^3UI=rt;O5#ao&@$uoHjX>xBZ^CqY$|u0gve^CxFcTq{ zFV_;v{%*}R0OVNP!ci00AwTjz=bPqJ(o=_ncu06#c)v`JmCx-dUo98BBm)8}^&&3Q z$9PZ7ZU|{#Z{ekHr{4>0Kq&yliuOE=XT(&floMq@>Kb!9IaDHd*Z9v%_gSoW;Z{8e z?|c+i4M!qn%^0orSAtB+-dtB4z(Glsl z5c(W1H^F_EqrhDR>9F5B0HrPl zT#ex7Ii{BmpVR%S54_moXlX}>T}mg6Smh^HCsxNdjgj{FB84B?HDfij%v$PW%Tw8$ zzJASgqi3X&8&wWGL0Fq%b3{mSj82T-$+KyZsk2pPtCvp{ubnE;Jkt+!b@c%T%}?o& z{o#U--w+%WoZ_~f9v@q3HZ{(APhXkPHj?10^Le)O3$kaD)$G-O#MLq4G3)$rN&9E) zB+Emwnfo@0AnNYU{qx{w?D`PwC&>?dTu9_;;x*nos2JTC@{tyEtyJ~(f2Ybzkm}Q{ zvF@yL5CPizC?H}6tks#mnVQuO7+k@2+bvyih&(}FcKR4>b!=AGEjZ6kl`qLO$eQ0= ztm2yFDuMXh?3e~2W80`wv`jH(rqe%tG1hQB496)w%xHDKmy+!RPIo}k`_K>ps^9Az zUsEYo|DlCyk0HE`AT3visG9o4PpE86GUr&EvpL=f;&K$q?Uy zHM#TLR_k|#6n{!AT%z9# z%{-?u!1U~knzxuh=mu^8JuhgPmq#SDE2^}8L9GtxT1uYL0)wPOW|aV~JFj^F^xroR zf4Mg~5F&SkMMM_9{TE07iH?yS_uzo`i@ZF}^Y>rJb*$6O8=l{Q0S96Ae^S+^b-KJl zDD4%Hvxb6tQRS*&hy(?C)^iUJV}5rzteB&|_<#OW1^`;+!?yovl{Y5G2odUBrDU&7 zef+(yE&|hv*df2$dVj9;tPww~@{6g-WrCWqdddkxwF}|s>4$+%(;K=GpiehL>{(D? zK^CaPH8T1|OjI4!apqlg0?ytM)ujp8v%X18b%?U;kUV{{&l;((H)18 zhmA0qcz8-TBO@BHg|zf9v=2!Wla0WwHWvITNDiab#*6ZlK}t(Hu!Uf}idZsu0;Hv^ zXd~T@1@_`icH+So^P~hf*YW=1jD>bH^k@rzm5$GnVxgv`y?LS)>7VZRzj0Pbwc~U(qE5zezoWZRjbeN{|e^mqU0DsO~Gsfsts}eCO9kkUp7ZLjh z@3A!DAdou=*ntDk4k^#hM2lsnriSHjf14&t8WJMH20IAW0>g0z`=pXafcb{=iWbXl zA4V?x>bIc`X|nsZkz_!JG!+Q9)l_Py22BdEQl7DRdTIOn%CDiF3TVUb_5?Bou=-Y7 zj2CM1Ha!G9a-T8ZRskIHMa)&V%b#n{8}v(`fWMpdRp1`i_{IxVr)Yr$c)6~RPSDpg zGrfU%e}E`8507^D^dj5|-=T<>+WXoIh<`tde}7K#2lRpg$8Fi?XX>Zg!I7}q6{69v zq5+1QlFHQ?C0)NiA~3yFCiT^@$fk-rQj*imdeZg?ZN|dUBtokhUhu36MmDsR#Xw8P z+7P<}Dnx&Jz0NU7TBIyzeOgCLN5aOjNRxS^jm396Z^sjKHd-%E&YC}lI{j+8Z-b-) zV=OgOq)uXAtx<~aLd^OEveHvTDN)LhC8BfN&38M?>$`Gj`p6i!_Th$aGP59hQXvzx z)RdxAO9cP^4I~R$zf(u7>TR9+jnGSu5*`74_M}Ad7VquDs`X%>L|kjO#KvRP{t145 z?3v2ucXmz{4FYKf?bvfGZBeQK*bbp?;DWte$}1bunr&b}HkQFnLL@#v<3Sk{9q+## z&yinXPD#(7G*GVX!z2M{ZG=AoLQbs=Z68FyW@$dLu<7%5xLYN&lVk8VcHg`K+P@6p z$xe}eLrdC_JgIfeEc-Q%&4j$Ncc|kZcmdz#>6-2Bnv+}xo%>o?nDIi3N_AzuDvYZ4 zU(|c5kSt%%R{;#tD|dcmrT@!0q`=nl;Z_Hy0<=-g|CH1r!tCa_IoEA&fi=HKk24sc zJ6j-bOrrgRrT}#nDj*I@Y-?afQ7JK~HI+hDb(?%pEbmQ3LBX4`Z}0z`7XepNMfJp; zN4nV2Q5gqBtw3E}ZBRYrDnI|n;Pe?Bm-HLm)Uxs42uzF)DHo>07h4Oy5Z%S0NS|Bx z&d8fMda~eAHpt8YftGe+p40GGv_#W|`_ZaCu|}$U;`iUPlM>(g3ocJUGk<%pDf_{< z;Vdg?XGh8;*(YsYTK&;uk^1i2{+E9;;7rEp?ZazGI6ElO;-h=!Q%j;Sro;^p{T7A9 z`?a`aw0C5Hpze)4{CvfqRJo&}dCFuFckBR`OLT+|B5vF5PAjz!g|e9lZru3$ZYMwR zApV?c0Comfn}ZEzS}FH-rBqFYfYAAKRVHaNrx$7c8aNpFc}*)wM~5U+m`sdRTOBcan?=*d-xWR>o8R@QQ2BFoW$> z3V@HQI3-1#j-jGh&QGoQXDoe&m zlN^YB|E~(g*6QF!>J|g$@hoMaaX`fp0K{k#0_Jg|?!~$Hz8$*LO7c1p?p{)Of=CP~mao=K~eL7+( zV$bTv?Vo|~4Sgdo|8B-!RYvIoh4l>2=sSxXk_%aqSm4)VGj<~b{i5bVWmCddX8 zc2DYl#ylgA*&auF|F+5xmSNNN=kX=>`1Nhj2BqfUP0#IR%iUAdg=>_MbC%63jlotP z=Bh%J;Dv9E)FSET{7pCfSs`Y%;GJk^Cg$4Y-j22VzEArLeC;?gnRispvH01}_3iof z#nH|Qna_`&n5bKFUFv1v8NMK_(;)Y@YmekA;PKv*)E(2_jjZFfqxt1=I~h~RUAT++ zEdO@p)wT6Zuc1_)j^my( zz5NX?pRd5G=Vot1Zf~chK;2}9JTD*MVWAdByG6rW!$sIdkyHB%*&r5FtDZjZo%_9e z!ebNXox=oNALi@DPpm+ zKtBd>8WY~vR^yC1l;G&D%ZzQrs*NEmc<-(oPWWc{fFm$>q|jXtkCm175caeB!`)yw zVlA$}8eM`k?h)J*#VbAt!pst8nDbiI@xcH@AW{7;t|_`Nff96l&PLo;OAy9A+v*ZE zJ*y!6d6^(YC6;@7;5XUE`aJSM3AON-Nuf&?Tg_Jj+odb4r5G47Rgq2h-O1!kyffcBwv?804{7pKXP~yF+%dJusYh4~ zZIY4ER*=`BTV(tiKU_sc>4I%)ZbwZ&spE)E%gvuzTkEQ*{La9wmrweOro!+qB3dd- z?7mH|k%MHig}b?lAj=iDlePkc)?_p~El z7R4IdRi*cCIcYPSzOIct{!uaRm0W7S|GHGY@m+iJY_-*e46m=9Ve3F{Qc#-cUeMt7 zPteuz7UtBhIa$s}q?y0AlgehjNWM{xF_Rez*Iw59Q#~E^UT%zY|5RsQ9#)+<7mTcU z9Q})KrzTqI=;#^q9j3%P;rMsHeZ1Vez!98?ek2dLzh#T>$`X3o54u_~fj#*~XS#2a zd;ZArTTV2;OIGsTwaWiBtQ4~D#NlG64f)``u_?jF&0d##Rv@(eClbeBt*lfN-jMz3 z&hKTi$b$T?yyABrqt533*{e`wt`a<#-|Ovfm-UB4tX&Sl4hJR{I==NWc*x{&clXza z4NS7!G%(C0ijaH(B_L$*_Al)=;ovm%gXeMo^e8j4H+t87n&pM||G&KMQbPm`-2;@K z7kfYqw$Yp1%535ZqZv}2B0{`qwL@ldrl7UYI!!_nX@s6}*z+o%#0}U)Vsbcs4Kjpu zwx=W1?f^dDTeJtp_@tKKjszTavE0#AChUu~O))^+WlUEPD)HCt>Vde?%rE-ps4X7O z+OE;`!kMTS*h6R11%{%0_r$c@ZiPxy8DI6K=vr)t+vO-)Du!*owlhdD?0+rF6~Rcr zUo8F@D>ZG1F}W8T6}7eXoQFj;r;c2lKP0N}D+fk;w8)908+}$)-^_`%0OLyOZQt(1 zrcLft7sZVB?A>m|tcR1PPe#6tQYeTvGSEYIRXEZo2RBXS*Aj2(nd()vYQn>M)ln~a zpH7KOnJ}k1R|`~?c8fMCxDCS7D8R^F$WLoaGsXT)r#$nFRDhSF(vEK>ZY#{HS4+3AXz@-t` za18#YtPHiJ=A7X7Z_L?`LCmFJ6(&JHiY%-=V{JVp)@8=QktCKF)mCb_)*uKA35no{ z;k}SH3TavC=KiAjv^GuT%Z>fkUC4VWOd*0nZclh=VORhU(thy9CFZMxU_(X`<}Cb1#lhdPy%PmRo~m(pD-x&&v5&VMCG zn(zIo*WFY|_gM`WjAXH7v7wc^Ji80OG{!c7)|sUIh+~mc{aX&x~ilu?9hvAJg>X!7DE3MxSj$dVF^P2 zJaXnPuHh7w(U`nB#?DT@qUWLdxgGVfdt{@HcOX}#S45`I1^L5} z38dRbLGbz~2o?t!1a?;%Vn=D*{g@i^_h|%qHN$TX7$fjx>h>mU#@lJv_xjg#PVYJ_ zg6C`E=j#`|V1n0eE(#q>1RCXF7AST_)XR>+njBis)UIjCH@1@fN*SGI zDy1>iBnY|S7j0S~!yc;plSX$9iY~N4_Q6Tx zlY66a)_>YJz^-UdaJpr5KJ|4>B5kfA9t`=bZMmvC*oCP28p^ue^Y+;8OtfZi8J*5= zApg|-^`nk;v^LV<4?ziuI4p|%7Wk2M?9wiCSRt!obj+B_mX^^y9I|S2Ms!=&G>j$| zW+GL)_s__s`_LXMeX?!q@q}9;?QP>JS5^mn7H_YTLW;3LdXDxHNY4%xInoo&B>s5| zVg1p_J~SYs-p`K_P=XJiG)DKwO7rsmGERKLY5ex)QQoLKnA&gfpSk6hQ`EGRf-nW| znu5@EHON7Gkf@f^6Rg>Avocn2;$YW9_scszYFT20#1Q$;U^>F=W{ZmQQwO=o!hNv z;OHvM$=N~+5#4%UsaulsdKYETzEjhA{+s7LY2?=PriI~$$SRWHMmryL;kzCaxDC{9 zx`adhS>+B)dfv6teRWtXfr$PV2m)Je>_Z7a0#P0l@^+&H4RDC%UV1DYHK}|!&W2OK zxPQh&66WVUF8MYrm))N3KAhpQG>hPi^*+L~+rfW>t=FFbRny%A$pe)jf@FBx@l%X& zHg}Ukk9-H>@i`!F*($Y6d5(Qaw9$Ip?Klg%E#}tWrJUkv(`6(g8Mx`aFGZRbI{->3# z6alMxE=u}%Ijb&MOKn86uqPx!*C5qi7Oe@84!Zx2>2$G%)?FYJyp{?fWQJFFBXm_pvs z>vCvgjG~M)V^H>u{Vilx35O7`DEr>z>~XMGtM|^k4uHFk1Vy8N&}ZT-cP#-(#kVy(D^mDQk;`wo%kDin z5wsgh!_+WgVz}9ILG$wm9Hm0SFcD(Gi!a2stM3O5iKKwFL4OT$n;IMIO!Lf{-W;+C zzPb#d&^NdVKAn>Z(;F@Pw?3p@>kO}~t6k)Q0=Ew(|__IYFJ zssRS>{uy@kJKAi+#-?Ac*+8M`s?Z5jP@^)-H_9gJG+jibbwB0|;?Y4^Stf&dH4=dDb!K#yRA0TjTk}KCIEo3z z-6cV9g{r1Sk}2##oqaozohK>j@Pe`(0+MJQ9)18-13{_k3#bzs^fb)&|QC-^ULOO*co-1 z3$xZp$F3b5H26jf-Tv09Q=c)g0JwA+W59;K^vOB-D;?awJfh3UbJ2geCHsf@(`=P2XQmL-THc4>#r1wBE%I{pw;*m8KV1&T>SfNEM!fdz;_V)F55X9^D(ryw=N4^wZMLHyAH>Frk{ zQj2dRyi4~!_O9vunb0#YI?el`qU1^js|1CN5;|@+iqri2!gb>V{P*M>?sO@vE~RZ$ z-eyg*4VN8AsQ>2(HAt5Wq_)j!BL|)34<1Ug)IG5&E=a$MVZEy=9$cGjWfcg?1P}K~ z@HqZT&Z46e-z;EcydKsZc0dIM?=`f)%NZqolYj&wQq=zJ1@3K=u^=OJbJNS&CN#M^=;P`XB2#0t*y0QK(6gv4CU_}U#HnF*enjxS zJ)DZ8 zzs2vr{~BSO-ZyokR(7X<>8AeMMKW;wO;mtG<*AV6sjz@b(M%n6M~iLvbcnKPP+lG% z#1mKEXmjCC;Qb6SB`5!@6&CZ2$WVanp zw0MCMzgj{IV&G^P38X{lJQ@$!8@ZES3na0Sg-l!#m)t&5y9C&EuW(h7@8D8xp<}*2?qoao)Ka3i1 zl`6ds`Vri?`QZ<8pYnJP@^9|n@7cFAm&!y%ktJFyg49b?>BQZrp2SeQn{Y}+-~l{E zlZv#JK!N#3R+w4zT&f&KQ7}1o)}VLocHVboA{XisP9qK*;( z=+u81JpA;Va|Dq(ye%PSM)z~)IpZIeyHpIN}DlbH`x83o5<2z;LP zncB+}Q{9TpzvUyQ_V0d*oE6C6?^7(dT<)n~b?8d#A6S85tM6ahr+nSeK-T}e8>fL* zMC0O+@yFmLduY?K)sm^HeUVL&8@m5|d{p?_ zQ%*#(ck4R|yV&HL^0e$j>Lc}C&}{VaB7VL$SigJUd0kQOfmsh%EnT3@*pXTc2V153 zA(;29B(|vzhSpzw9vP7?XkURiE?oX;Cq-U7Y1t$}Lg7zuQH9p99q%g2>!X_Pd{WdN zP#+mul3x_Cb;^%hO%c^X2~TW?s?wJK=C|-8H9+NnpmV6T^V?-jtv6b#AMHWnbscg$>%qa1jbJ4@kH*;<@4{ zjJW54{L;@7FQx4hgY<3EM&f-zVV?-aB3;gCka!oX+ncQesbUhhq75=vQ^QhI!+!&! zY!`Ts{v~+#%b&hS&jJ>8UU)W<#^U4v{ZdJ(l6Ql~3rr@Op~!88Toe^?BlHC6_jjNx z#RV$zaiOl?O=#0S@GkXk_Ehk$U)twsa@CX~M`p3Wr=_K0Z;~*Ab!RBve6Xp>SMqF) zK~9gZj?9Y6ER;*jgw7un+(dplJg`mT`jWSmCx9{AvS{h~5=;+tZwqikMVR+U>tnqp zGD^eRlS{|A%iw(KOggjxz(|*h^}}2RYlC-5@FvC}9;h!hwe{f0U^0gYyuJSFL%eQS z^*o3Ks>`p`2!;Yj(+ zh`e@zytnhALO4=P8pQB7y+BCzLDp%~lkqHk#sBWTE~|4eG+NNQG6))fg&-}v^hqE3 z_b9gkK?h7ISf*7a@NjGCkqNlQu^ zn9mp)CGhniDkH(IV*j=T54+xBhwa8DUSbI3OTaKNX${}zNP<6e#u`0f-N#6#XGOi zpa=4B#e=uSfKQ=f`t@_u5No!9&$qW4FH!eVRzp?CGp#+dT^&l>?|<~RA3RVSKq#qcztwMD(W;Rv$O86@L%?`XA%;!yb>oB z=kp81My*s{;SOU=SO#i9=j^kCJu+y$oF_3vI8t(cTXvd!w z>45huAQBA`Q+tsTJ!jX9G1cp@cVubm&M#R{+xYvV2ChH%ZaqN;*dXsb{iK?!?56ai zjyY@ng9n`q>xQcDtY^cH!h3TsLJT*2>KBCN+x#7=XI|y6>)L;O_9{cy`@KUO&||S) z#y(Xd8M6u-t~jmY$>zDHO3ZsfnQB(>8YjPo0zBsxlq_~w#Jw8r9(0+v2mzcbbn zVsJ@${m(-y`jW!d^inz*%lQeq(uxY`POz%>yPVkAw`%eD%6fXdCrfG)bDTS>T54jP z?Q$LxtP&JM^yYNyUT;oSPva{tr>W}DAVUdF z?o6q1SfV7&$lf_(w9e?f+St4*){cqPjzEEFFizy%xAHBMdDwkfnGEfFbT$#b`-fgt zEv>P6wcevqk2V%EcpraCRV}@-`9EheZ+heURF#Q0<~4@T>O$8|sO^bjfFJ=jcmFQk-`AJmC& zd9%rok(QBvut@tRRR2KGtl^X~{0+Y^`)QWU;;#DJt|_i1B+JwH^T#CK=yZwTg&)vx ze79)>02fxTd-wFbzAhUSL~W;aXJv$P8sFKo{^E-Id~9y7b#XtfaOaeTwleiddnAn3DF=TvNM6 zK{OnGmP?0+lANbeA@i)GPFh8}`(|Lc`;rJO4Vg6z)z9m6e>gT75<4O$Yay&nCnaiG zKy8QU`ZFOliR2`W5Mq>-jTDF2YUm}1*r<81swGI2RF%67~&r#M|8F zFN6{x0WPWrT~U!F{L(-*?R@z6E1$;&0w-riPMs~IfRFA!5@FvT^CWxgyLj(ONb&=6 zgsd#B3uk{96_*smXnO##<6nII%O!1XK}bjs7VgeJACNpt+M2>cB#|t=ts+7Q4<95S zO7g1WS|8d4Z~DBwZK9q-Ly*6<`c+3wxYnQ7@R>eC6@{-a8#|r_ z1#Zq=2WmH_!SAK|zct3xh^D5K7N8}WS)>mhT*f)y-^)1v61@n<&nlYqd8xbFl$m7z zBG39QxA!7HLfizt{RH8+JO-PC{LCe@-aDc+()`XG3?V7u-{&>VdYL&<9o`9r_X~OL z3c^6yCzXHJ7sko6N4FlrJGrt|Vx5x1$nFY10VnQ7|!syTM7 zw~!p+J^C{4XeS+ZbON-SnX?tE-XTYUuCn`1<~_kEaD^G-EPrnQij(?f8%~heDYK(T z%xkzMPA@=|N7XmoD~#)pmBVODIBxVFnHb3)ll}2-FLpE-PLav6)#jVj&&p92cR$8P zn~@Oi<_}qLSj>pxHlmmk;bNQP!EW5|F2Zk{%4uY$9sGO2+)=)zhAd3<^o6;-Vsvz3 z{JGkE?ssobmYVJ;CCl*F0X>69vFNpFzmhimaVxArp zeql9v+8(_+w62;eGjLDvy-!e>wl;Wy^Vt}!nzgR-3+Q~fuA0{Hdp^1{=z6feDloXG zVD?JT_qb-iDw*_-6*?a!%bV*`FGn%wZ+|e&-pN54?KO&SkHdFLD#=MSp57=2hXY5~H;hx9W1!zdufJxEG zmEY?b^Vje^;n&N-eQsaMw5kSqv0^X`ZHJ`F1EfCz|8lZmmUA8MLn7lb9^SF5Lvkh$ zh5@@?f2KX{eCvWq#npAy4Vi%5{A1?;_)gt5&u0yXaWBfWY03U~4~sv3Vrt@tHG>Gk zlwmeT!GO!!KaXgm!xQ=C3^HVLQuCG^4Sicv4Kfg08jv zm&3c&(eryaZzb>Q=l611f*gz%nDH)JhWA_*yU%hIqxZzY7x(UZN?2;Ds*0ADw7B^A zmzrWgNWskMD!=7?B_AOx=5m`G_sM!!l)FEyT8noRJb})nHPNLzl*bhi?lF~Fh>%69=Pfgq&GFzuy!+9r+4UVk7I{hc4 zXn^ZBQ=$XWh!BvEGk0o|cX;|;YuH}xF!LXZw~^)F5}>wE=!` zH@)DRa&J?TQ~L7rs^-{ZrzBXj;pW@T3*r@=`?w{8g7l*NqSnDTM3^??x8czoZ<)&O zs$eO4<~r@mp}=TMB5lgW;XcEo&FPKWSd!hwH&5Cz8pq7h(UvwrPaBFu%t%!Z^(^HlBPf`lyVJHqUQEbP=&)^*7Yz16?dixTF`{NG5*>&ij{nzLG4y-JFJ$kpb$ zw(y)*l|u0Ns^F@?sua99$|`AYPma=iQbKH^_oO+~tVsLkUy=4`xkv{GEp2RMZGJY9 znJr|dW@e|P&;mg&=2N65)tP41nF&uTZy3^2jnfJboa!K_Hg$Uz4+4@QFqx$N&CAKz z7BqZIckjS~qRHvtaE<+oIebE61E_i3-eTnp;`Y6M`w-M8f$5xw-z#(DG1k3r12L1a-n9U!GcqACQ(8q?N}HXIe%R^*7XA$%Z_DtRi6??l*k)qDUg{u%4+4UMk@qHH6wFOwxZ_wjyzzMt>+@wo55;GQ4NnRAZU`g~r`>$+YNT|cvB?H4~rLK}gf zqeTWob{Jc%xX&{?irlW|01QV$U+^=-KXrmw-;;xf7!(%4b5Il4-!H~U^mA$oxpnB_ z>3T^*5(NX?pLo!z?(fn_?$XlgE+L z>9umV-`O^EW5AxU^(UX`C5D91XX5voMg4xSQtyuFNyL&LAi2p2!DlCdWWVmFW5{6z z6Z|=CK}N{7oyj=X+!(UMgJ9zQ|`|Ab1nNf;k zV`GwNxvzfH)6=C?9TY`mgbppOgb|Snl9k|Dy%#Kc?~UW9W>pU&_jdce-i>OjTDFgS zFQ)P|FP5scr7L3Pn-Z+btXADxxq#-0M`eFy%WI@|jcw+Ae9(8c;nwHr72ktHm1g&4 z?~z*8);V@apjZ*2X8B804*BC==FS-bXa=(Eq#WVYmoNEkP`&pQWPF}5(0XWBiOMnc z5G@CVz`xetod{4W>I6`UM%S;=6MDVEuh;|PDAt{J)NLM^!xhFPU&2`i8KBhz3Xx3J zU_-&mBzh`@&1(@et3QP)qsdM>5b-bWFPvOvIs%Bda>yR&8v_8+Oy|aRQ{|@5w4Co* zB?xnhgB2@Wa*%`1l%`oKR|gU3S(74zFETk+KpTvKkp}OvwVV-S8xU?s5#zb!l2?9a zv&yzyl;An@uE2UbCK!e}J_@4YN#(RReFnd@w!x7X(aw(5MHfb?FBxjBd z<0R3tn~WC6jz`TbRj3%=DZiIq-)g?u4>;?5~_)-IW+9-nbDZI4zu;q+;5TZjvVSkVHWyv0 zqQS;;;&b2-l&H3f_c<1QqjPU>Uq^E_sfwY_h@G8{agcyVShB@)%niLXkwHkQ6XP^w zq$E{bn!_I4qB7FY%1oWI0k$TX>T+LrXbE(`&DfjReG9>T?3cl9D_#qCO%=BxI$#$| zbRID5-AyTF?G#7c&Q(?AqYv3zH4BP>9IU34O3?sX_hr6kg4;k#O~+*mDr^-WDQc|b zff#^5HfSfp3qb)~(B$My-SXGq{b_&hbFfxUr}q*~(0y*h%SsNP4L>S6b}bG?pYIyx z;xmtOIO^;zFI@njrX|6aLdBG?z7jH1lWu}U!dFSz>UR~#MWrttw!1=`S6+3drl;$& zv2{tk=2z9u`@Z4#TppH#ig|fGZHa+s1GTJqU37t%_zBk|8&un%o=qYH)du;2)WT({ zz9`h-)V17kf&5`Rj3bWv-jx|!z`N$t3#!=5&@Kkyl)pM!)P>JWjQ>#FF;6iG)D%jQ zA6jj7chtL%;92BY?v)gQE6B}E!BN$0)2wCjb$Nce)2b^<($J3a?T z^C)`W>Z2jz@A)}()B_~97 zz-9jwzTknNl{BSGOdRQ1P|$Ce?z^p|sMN`W)L$BE+9yh^zVz7B*_i49#8JY!m8Y{t z94iv?g+OKd>fWr#NGWV?fR*7WRaE786K%nMs5k4-vapZnU$rvy%E3xN7Kb)U! zcqE{_-NP44Hk(_opDCv^K;sjcHh)M8gzuFGj@Y{v6Wo5Pp3MgrKG+)!e)2yIV^CA( za-h$6(ErtGs9(=TkGc1&6VHIU@BN$sgG+ib^{?v(zv>iCHQyq`yH_JObR(;sHCuUk1+Hm~- z4D0!`x<0{gqulPcRx82gZW!pEd@bZNfht#Fm`AgwkJIiFdf4_;JTGe{wZ;NR77$>A z<=%;>Utw9@Tziw#>WQ%pOI^mFHY$;zgO7*pi!+acj^7$QzboS8jRo)wrWiPT(k~0a z3|SduA71IkY2+iD`Qhsz^D_TW@w33eEo={nHoRg($8>jp)(SX$wLmsF5RA5~c9$lc zNipTBdhJTfMSxzPOX33*2t!+>{Os((uN3N$E!LSC(5+G5Ht>vbOQ`{5k1qn<2{Pms zAa}|MAUkWxPqQ)Il=gT1he+>`^aM0~ zrk?IJa(~1I?)HE|%UXk+?mP7^+(Y3CrgAxwoNnaHOM%Y`T+-@qjJO&b8gy8fh-Tq@9-m} z=KYmWPd`hn-{0-SHPnyyQp(XYZOz^KW(`U07ycyBY zc>%KbzqHPm3lhs=VfuQYi7C{dP)<7Gs?ohPF3=%#HnMR)xW2ez+aPe(7HD zl?s!-4ZoydS~R4CRJ=xY`>A3!?H7TBC=F9nSiZNy&3x30H_=AI8mjmaMq&E{&1LDI z0;K9;!a}iB2b)u7`WNK@bI%3JJ9pSxBIanc^7R44xkUvdva_m^{v*Sw&xn2}JG#kB!*a;kK}MRku=eRWw{CCrKV# z4a%8-s9kMs{XlT|q|%_VzhN3yB8vhR9DMw~E!=yC7%3xjxg~;uHh$60fc*i zBN`*1H4$+9Op=|G<6XosFFR*8M_}0FuK+6G*)UxI%h((Kg~Kc~q9YrEMNfTMp^UJi z^lc4#2uDL2mzALa8NoiY_|YYwtQEEbn$bd$w5{jIqsD(5GPjCi1NG%C!>e7^f>-_5 za)N3l%X`~=f1rzC#NaXT)z#H^Xu|Bg0(-6Ap0?X>M}Ub$omTj+_S&)*Pg8i?!@d~q zgo29jX^X$7TeeE$&n`WL4#;Eh5@Ex#TcrQ?Z-(cdw_oY$=E3QMV&+lSrdf7l`>%dq zs~m4GOXFG9va;B{7D!#LvQ_q?GNoMzyUs3!IuAwN!f1bZ1ite6@@^^%nqF`D=&b+( z#Wv|MGoZHarzA*ExQ(FL63-meu!*oGS6nww*P=re;dDK1%=^$*mW)mlG#m&{p||&q zUOkU3AOmp698@nl}cN_qz$!0*vPudXo60Jj^k2R{ZTikA=9})WnT` zv3`58vVKNdn#3(0Vs}HYdPtk{G~-d63)d*|RBS62+TQZ0?A6gx%;&c;1hqCb?{k!d z;XVQ;O;5M4XF%v7@d<~tMK-&ubtOHs6M7~4jL2f?_VOwbPDG7$=$f81GIXvZu(9Vh z^nfdu^W_r@0@>he-XSP<35FJU2VhN-S>r+n`-$RQ9D`C5C6$|`=m^HR2Wi1xmg{o$ zYc`D*6V}k?87SIoN%^iu9tbSy%{DMS0^;sjpQtq-PjA_n0T|`e-O=qk->d>7Anzqw zOtnCSU1BJn=kLKEg`-Z}xPtu_36Pk7y>m(7Xz)C)U@%-Ip~KF!02~3K9&@Wh#KZ!h zssF=*7aKdSe0}O!Iw zQkYnct}tHVR)5o?A{=+)t*r4CMn){n4$N6CA@zh4NMi@$Y}(N%3p2Aq(`Q;7T37@C zE4Cz1ZB0`HDx!lDdwY8yIp^~=Vo1E{xK%_)0h<6cq>hG0duiN`MOSZM>&PKWzLafP)CRPTK(-`Ffm0Hl8+JAl#n=|{*?zz}@%cw+@UY@z&pPBv zqmiDhxT-r^{t+h4?Q^%)`Zj!$x_`ez4;rfE-syP5@Qc$)O%g1*&Y8K>$R|Lv&9}@BO;|d&RKQbtoVu#5~q6VU72M3~B#5y$yXa__>FrCLrwg3aAdvm5V-`{fo+ zxiO=c${+SmRc%2!*@61Olq2ool1T`*vbniAlLbcv4!^9o=cjGl??AcSd}8;o>WK!Y zb@NlgsscM#d_mg*HRc;Dln#+9QF9K~D(s@}Ui7418WAC5%m?1Od9d#x+xpUN{rHoz z-ODHyfx^q@@)5=(jGe?;$*FxjSp%uMD{NmL1-7ja)i>OQesX6an_aJA`a1aKZC(ZX zBurkz1AbTR$FIX$#qGBMOWyeJ8Y&**Cy+Mr7;7Y$4`#~Rz5_QvdQPgNP7Y4!!Dr+q zk&n`xq&Ux=h*))KCtw+X)`;dMo1?&a@Zvlkx5CVIbRNUQ^Z_k8y8!guoaU#Ua_ivF zKwFbPaoAcXqRoX4*?!CxMkjd!cSLDD-DOBu4Im(Jn?`JQ7BfTMVxsJP$WFo;(PK!P zAcoYi()G1`ONZ8xdFI0Dn{DYVN-e?1@~S(J`(v)-IHu$g>dMfLY2{OUu)JU&N*oHN z$>rp;NmX`#$cRG(-gR|W-tvk0p{2$4yt~Ww{(aK{X_?PzNELB45E-S!Uv>$gb(f@5 z%gM@NyeX&O{8hS#Uq#}uQ=}#L!@^8;#+uiDs88{6*;SyTYwgZO3bGjl%MU)KrdH={{{JK@)r$Y;6xxj=^)N}We;lx z#Uol3C^ZC?Ed*U1$kvhLk;)l?%H&UL_ACnUqrT_IwjoDm1xVm3Bt7gD1_YX>VO81V zy=uJ$y{>$8Tl4#kLd)8Nw%nSqCw#oB(E%#UONX~_lw5DRr$y?jR>@lSipXY#*uCz0 zhlR2EmD}#3iMkS~U5L1ZM5YM37Ch8y?E7X`3~H3xo#4a710--={+`?HjuYP&w>T%U+-Axeq@RV06!y>cdgD2jr1R^#b4* zLyZ-CDm{2@M;@deb0;7~Tqa2O9fNTEZ;DtroGlqS&!94{Tl1=UB$x*6<=bYxdT4%h zBzuvGG_FAu;y08Z)(o^50I+ zsh97Gm05ry$cFr+XYsgS>At_vcy-pGhOc&Qmb!?44b`r3T|+kzuvQoU3f*jr zv1R(iNbii-*E3A!v{^ar?PVbHVCv}jX!^C<(b!Ww2*O9F;G**CN8g<9ga_lVI42e| zM^4R_^>d0RMNl@UFkKhi zFSoG{N?Igr0DaE!mjW<0hvp0=3D-2}x z#7|<=WOlt+-QL6Diu^m;3|$wno`^uK|3+xy)AZ*0CTHm5y&` zJvax!9_I$x)`$5Pf>3rK~n2LI{ZI|F1ZdN!0m#&^Po zfF>e1-qCTpq6o_T--o)qC`WdY;E^G_u z3Gwlig1DW@nHeFB_k9HplAu72YA0if$WqGocT21@sL@;WT7~x^*2Pzq1*2;|$4>e8 zzpWj?Q+SOEi~@Kg@D7Qi3kzBL`h9nv!Qotsk7&Q%U$`s{NW0Ss0}?Cu>Ypdyg-!_r zvkS82D|hOPI7j{IWTqiJFkKvOW?EpyCi{1fY;xv;%uG zN1EyyJAC!aIwh1obp{J3k1W?~?m*vFjjS5CRTH<_!rXZcfra0vBO_)!gD%UKUT0;I zB+)+6I*_({1%VM_Lr_eeCGQ0p0L(tCW+l+h%xt#v!ph8yufT|+7eGnN{DcN$_Q!XR zI{I7zgnAy0#KRWTWVupRTq!93VsdbIb+y-E5XDM1w-!0xwc_x3!to=6?LqK;@Ek@A z219~oSdF8tJSQsM-zX1H<`EZv%snb+ccNniWXXLg1tO!+vfA3sml-Lio>f0;ce9vOlvszA$@`${VDW|GU`OJz9 zU2hc9!J=#MLp;B~GOq6m+Zsr&2O^$$?Vi5tqyBs%gdVo(7g{Zpv830jY&zub;P z)AeZ&Rv)lM1vZ`Tef)5S4f|>3wM(nwjYosYWwUdwOZ9g397IJ!zrW~nhLyo!`{sW~jHm-mUbAI` zduwfB^P%U5xm)v@$Gl%;%|T|Fr6|wzgWTVo(kwtgVMQpv&ClqBCMK*6jp32{_}fO0 z{j9Mdh0xJhl-M4fiW`9ru_ljHCT~@8j1qw5QR6jVOQTqAY>A)7bE0HfbnnNbYYKmbkbq( z7^r9{9?$zTd>IXFMQD&akpSG+d|uPaa~4L%(CKiaz+z+%L@xNOgTo!` zO|7w+E^qPZ(Mw2Ie>@R(f_6|U;Jd5W7T$N6cZ!!j?ui9OxYm`d6)1LhPqUJ~aVlnN zF2{3)!JS<_i{?F7>WS?HePk(ib@}NBjanDeM_RpCEE7O0NlD^|M^Us-qv!U;F!+-d?m%Jtp z)|NKjlbn7tG3>vi(+t`{wV=Zfa52kT^v9=L-NU67UBj%cgmd<09PE5^%M*&d;OBCO zi<9U;4hCGS=DPiZDR#?JXTOZMjtCF+w!E9XOKJ%@sB=@K)9VdISd9gD_qVq7{_vu4 z-AVPW;R~w{h>*N`)#Fl+X37#L**(5pMH>Kyh&!=1^{)GoG?>{r>DUTE$3L;qf`eQ& z=S7kN9+tY^dPixPRgX1FfR4C4QM+yOOM!;)b@I1GmBV*nnjeX-!!_W4wl9yf^6`LP zK|tFw7borE`z!4EU!OCUlojU*V`ei}ebUPXCGtl`7$K+tw40k7TS93-YjRrJU}Obl z8v)29qtGfXcqw2wI#-}g5|YTNq^o^v`L`2*FX(3fyhBaVszL`#fWUHW0W3z~lhcf) z)#PH1bzCdfIfFG-UcUb3jKrHs6h`2+UBG5w(Vtrd>kf;j?C{wfd8XRc^-V^Y)}9Ll z&r6J+Bh{*PsX->I-4K8YU)KpcvvmPY&E>`G$DS#+SInQ7p} zXHFY#e!qM>RtWyd0;B+j`pHfX|Koe&J2%O?=?RG2PX?CJRZ`|1tT{S6FP3y{S2e<+KAb zF9{e94U?HZQ!#KUU)!gawi_q0eH7?sRSHx#(B#$E?tQS(i>*@ri@P=|gjT^?w`4<` zxIkv1vKL@GdMS>`Z25F@a@^2*I+Um#$L9d;hkN^>sh6YCm1RMf*^!+#!F1p<{o{lDOO z+Id^ridgrI&pr`>bLtcc;Hcvs#N5AIV+n9_b4zr$rtI&>H(*^>>cf?C%!$MP!P$yb zm>K@n%~;lfv>o9w>o+dB!B6BogHr3L9V(+ydQxAH3m!nvaZLi6IG!|_VKetj5F!#VQ|L&Bs zwz{J^*4$hpqubdT4Q=N~+6tLlS?SBl$}+;^8OS6gwV3MEZ%PX*j*l1U)*%nh=?X?qkYF)WdF5dE4M1TEsYpB-kfI-boIBNj=ZDh`^)H*I!n4zD{ywEnglwHlPXuNXp zU&Q)m+Qaek>_@13B0$Km&pIoACVA*XqG-95bjca6h91y!IpIAN0@WAwm3(ThH-G6) zEKnufbGnb2=;|6BVPE+s#ODRei=DTZDOJg|nVnyjfKtdoK4p(f6Ntj>xTeWSGV=#v zG!$gO{!O!$uqd^CItu#wI^VB8Y6y_aa}=06q*jqchrE9)kqsOB_ZEgVzyf`6 za=0TSEzL)uR*-`P@;{HRv@}}}F+citN#p3(ejBVBa92l!3Btn;=A3X_7#fZ%{?1kT zgYr-Ct*xWG(_2?Z2E+ccSPGwMF^cr=dg^m~0?toW(lxl$(W6s@MgA!fS zP5y)Xe@TJyF}ulYcVkZQ4&4S%{bA@3P!({^=R*W7?=AL*_8v-SpzHBze&l1I^J4<= zDv=W4Rt-~s^BccMdXS?SYOMCDxHx)gkU}t5ar6rB&@wSpL&cjf(u=y|trA-RTio2V z$J#X!zq+REYY<$vi&G0_dotbBq&5hTVwTb%pGr$JGcqP82B?7jUG`9Pl40CTJ4G>O z$>07fMJ(C+n|%bTxve4`?l-rWos*L~ylxHUXoxh+GxI91p-2V&yw(7yMqt>9!umv2 zx!Z-{K`jhWa1OL{@>&c6NRNwOfHY|_V3lg~a<#+``l^c+z<^%lr>m)T|1 zVs>4iTACc%8CS7Y5RsSHpt8%SVcbSrLtEdo$G5h>XWvl!eV?t&QG?VqScMq@4;DrHiaUwnN3$l3d*Ca-c>>YtMc7M+%smhotX9cf){j#}T3we`l2^!RFX zJhEd@khx7b8D8ZNsAD$?S-d4(TT{35hz0l|m`n=DSqbEORR)BUlaoI9g9Mp+30p(h zya~b(f`)E8?DTY}<=I0I^jyl#Tn~Hg|J6CfOw*Seex@ z1!l95)|FzNUknB@{t9B(OKub>zv*}8FO@a46vz)p2;U+`XG0qd$ZT`R^*4!%YIMG4 zie!);bY24api!ND}{E;Sw=Ud z)IEgSj=t^7e^*5Ndw})AdAZd&lk%U10x8d*yP_VGjS-B$>M8Jx&V@!Sk=|EvVtMkc zW;ucEy`qY2CssLP^jSHnH(V*6X*n%JF>{a6o^r$=G(_d)t&q68KU|5hfem-<(KAFC zTXeZ;tTO--jV~Q&R@i>PQ5-}^8=WfRFWr|bqsLp_yTNaSdkzbUg`o=o{6|J%A)$Bo zYi^&xyrQm+OD>!1QPe;>e0S#h-|de_*<3=$*WDyLfg?ZV+WqC3%x^fv5w)SG=LHNY zNQi^Gu%9T1`CthMysrVv&Bm(FAf;*somEO5IM z{;KfJisy)1ndlHD?7o)S8%R5a7bcArK2_$iGKMl>w}hlJ17wZadCWGRVcl@_+ok!_1bs) zacV#~n3_=YukdE2v|}@SCoMWZP^4kH{b_?jRT6InBT1#=TiXCU{ZH=0mW6I9xSrk{ zqQ>Dj6wF%czj(<=SfzJUQ&>!#oWQ+F9rVp0DxgSBr*mfk!Qs+u>cm!-U(ipo0BfF= z1Ul~P5IOBP=@U4;;pQApJFdeVBz@ap#i44VV#$lmSnU9-h0_dXkexyiEEhylud8_< zEmERhUnBG9ae;-K+s?f(0^6$l){7-Uqyz;0XWbDa$_Hg1cH`m-7?Aual%59#8h=P2@#4DTp2rOwAK31#L;Ce1vt2KJ#Y;{Y^m`? zRsnS;#hWZEFMXgw;H2^CQs>*?`!+t~Z}>y)7|2!$w)~epCRrL4CC0c77JM`1RP;FH zk$m$kWcVAPaU5fzfIwexm_G4|C0p3e&h0TpJtTI7>>00oX1<)Va=chJL_YHa3&)Q# zInY}oJza}J27t}jRE1FgSZ|J>rbzL-#szHwY{>4lYHLlXiOt+JtL0BVt*{47rf%??g_<$C@M&hXt$Thc) z$6VXW-lyN1Z8Jn--;;PSRbSI6^Y9?51+1eqi1X%nS#GM>N2xeisfi<7Ut_Z8LNhb1 z-cy=o558gb=F3)zoWV7F^twK9Rn~A}H{v~F@-4_VYBFMGfAIk8-4x&f!E$B0bW(@> zb}yc$Jf^_H45L_Jd!vlraO> z52T;l{kdQ3s3*Gwnv)bWX6K{|I{2Bh7wU?8Hv(1s0-2(LKVJ2svr-e}bXRsd%RZRL zCatY~d>KoVKPcCfg0ztjOq!)O^rGKLyf;D&D|}DykwN2GZM(dT}|L0W*s* zBoE+FO-W6qn0oW;k-jxeidm|WYhbZy6etET%Z`U*&3>Jdo?PDjL1L$d@Cl=lAlT$| zoxs77@K^)KQ2Z<87m0cX$MU!Imyhv7Vb{O|;Be$@Pv}PT`C^vwbHtAcLy)`Qy-x(Q z6@23ia;^>d+0TFnC~CS)4AjY+1Z!6Vh&)z8tP?QT_0Hs5grFjsRg^xlXFp34;h?Ur zmI?}@5R{nq;5c7pyp)liUW;yuV>h_aD-9?1l#y`DyWA+62+)m{q6UoKK+V7M!gOri z#6BnryC7Qn=YRJK!qja{IPL7)qkehU+J zpiZ%83Q3H>fym$S^3d?<tbEPYXu3YW59~Z~&DK$B#8D7%f7jOLh!h22yh9rw#h?VJLqEBXnB!#xDp-ad`-_zzGRS6*kZy0)1Hf+TnL-;9l* zS=t-#yw$8UEiHLXgp&PtgXqlqb*cVlg>94?^+|_ZMS&Par1NC++})q8fyA9&(>GRh z{=ABOVsV#@gd-GWmAM)p2s5YTk5+?l=g{Q0$7>f zB#BIc7PB746s5lKfPQffm_85L5WC$l*|NRW`sj50*S^q4IkVM|G;4pxl?fqco%eP)gT;wv`^dsH*~>En++nAPKET zR_Zy5i$(gnzbdgfmUV6b6x%(ggU<}&dr=_^><1Ze$Ee%6T7tVe1%jz7!L@xRo3CNwj8{A;}SKkG^n zn2X<-tY>3M^j<3CAoaUc=jDu_zB~gy{ z0Ubg#U1~z~2b-e<#X#@CDa`0iYVf(5VWAJF9*{*tc68CU%axxi802B9O%ryx_eC~~`%y~;lY-r@E4D#CLxj_Ozj3y@w zu&U8pU4Hksj<(7sN1NdTgbWp>hC818F{VGQ94aGqt@Z!%>p@KfVDl~f!N1Fin8{jh z=yN%#DNh%IzRrYrL+hlR2R(Rv+=(1zCTl#>QCOM+e5C>rR$)O=08%uNs%i&2&&5lye7YWQ<(irv5_!DR$Nu3qgG!^jrz&Y6X%4syOoJ`Q?I1_>`YO^ zz%nhDODEd$^^jVoSUdteJx_VatO4uLpbYIeE^ zGJ2*-|8d5Wp%g`~tNYv0_~y`gA)%nLkq1#KnP|6~%d6>wd!!TKJu}#-Xo&lWGKP2R zo0_zR6>vkT6e&4I*&xS+ke!~+uqCb*fR6A-;)~=n=5%}7UhmKBgElJ}d-eZrbm1}fWQ^LHOKrwQ1e$!YxW73w zx!^>C?wEy^8Y3i>Qpx^is$&m6iW4+npI zA@=Ij&Gp!=wj6W&mMG-6JFR*y-g5eF^5P~AXI%y072s29Ex;;In0cvCsBr@C>3-Y6 z)^38y7U;qVv>yJ?WW2a=6?5^5BU>k(TY`WHFngq0`)`_laT8ySi%dobVgU&-IxqfL zq*Q2J#tVjO|8r|0@JAA>|NT*k?3K{E;lT%H6-KJ>CP4JyzuVe{*Pr>3dqM74iA_P+ ztqbiNDZbWc-sqp#Ewucw`$J2$)T~A8^z{W?M1^(x{r~;H{G|)C!U}n+PDV^RKGd5! z!+SKRj@6v{CyiBa#1_QPwgv?MZ(DQ?8}C!aQFpWHcNYG!YC6ZPg-vps%UF`aY%?O#0bqD{wW{?Vo6{%PYr-|em+ z0}S=1mx@%6i^CNBNB_4;-EOiImF12-(9L~i=5?Yjh+J`b|8JN0vg-V|-*lMWY%Np5 zFc;$ibaLlfsg4I*G${T^vehtl?SZbEGj^s=%uW91(?q@g zOdw|{W*3&U_@B}BpJ%1r{5O35_W`E+Q5VIYf5#74^8t(UZ!g~Q|6DU&+o-~Q5QOch zDQ`OdKD{?9a4PZ7JN#$R1z-Q)rU3ucC;*=5^6#_$8I!@Ft>^#T|Nm!SpQ}=PnY??;B2A8x;BhGu;VmQQ-*O;Mqk#FKy!+s+ZEyF~rr@Xgp6)ZF+}2KR%v4Ki%I8Rq%{4x#dxK*JLCP)b4}~Yl^rOK0Rz{^ruqt zz4NYd`S@%%iVvwUmo4P;0PmCpF2#^lKa~F;n<+;>%<^QWvzj3~>HlhgnKeQ6K0`_1~HfOaquV6p^kO@xNsV z0x*>-c)Zq)dXpzmQ)?0IlXCV4lWO4}z_t#7`s zy!yZ2p2YY6p9O@no1X8*wzMB^ZhV#*J9VEQws=)7={(7v@9#AO}H@ z60yZjjZ*-bBsprN2sC#J*`>K;Bd+O3zn|f3&s)67{dlCjSnBW`J7^V=BK9V7>U&l* zYn6-Rsqx>`G$5ngQh_${3d5Ty@c%}{Cfxm#$1RIUms-rRFh0Ay)k_GL;Lb+-YG?Mqe%Iwm*x!{Nn$L%Bu6B({|PJHa# z1`6Bfx56_-N5AU+#D0%n*aPIQzboDIP|$|HFMD%ikg$(nbZZtr(UG6h`}Cc&3Y8!% zm2bKSjZI_Fw$c4`ezDIWBrIt*V7H;c3We|DV|R}4q0wKTQIN5Ld{$uH@VRw>{^(Pk zw2>q9g0!$pVU~vh$ocTW6Gp#FelfrUOab$|&4!kQd~Z@aKRT8yTP>3p#{pda?9c{E z1qe_NB%0^6XL&P`#~?W)V>HQCjeJO5IABKF5YbzP(SLdbFIFnAHE}YrUe&zLY?c(M z>$rjvwY3Z%ObOoT;Td>@Zu6}Yv{O?O>QbeVN&hGS_Hn*%LR4~o)Gb|^3^iZsJ*OGf z8PQ2kvxj<=;Z1v_G(K>mVdi9FGmxir^SPCl(`7Vr{AFY2VB}in-Kdd%`;1|~ zqY>)8lHVjeQMEYKrTTG2q2Rgqxw=`;pxal1myrOJ(|{t|E?GG&%k>!MObhip-skOfb7_e^R& ziyBJfA%07hSl~N=9kpFJUzBC)X=PK}kf<6_!AG`u>9HGDz1=oH&rXZGII+$>=IBc} z{NI+5yjXS!f}Hsc^m!0Q&nZy|nVh^FgO_tgOyUR1Xm4cdbHmw+zrXl^$0r1Z@55es zWf(Hv>BBi;pTPyf87z}m+(8!(=1N@uXmP*%fb9!E1byDYBnvwBA7&}$x-FN2W9(*) zaX+%YwFCd_<3u#)m%rPaF*2u9Q^`uD&aalMMSs(x7D2EnHDFx&uCB2h(F>I--BBId z2r;2?S=XrDID7k=w$?k(4y|dMJE|6fx-_t{{{yyNPhAO)ObS3kq*5?t*Sxb0%i*J5SX80vIT!b*kTe0nSAI?hy2Z0T3O? zKQpE)#cR07*yMx4wsEW42HT*LL-9Cvl^ zXIotl_mZtlDYo%~(kW?37A9bR$|%aZN$h-qMWFQx!!)@W z8nH6OOmL#<^W(hMB1z60K7>%+QpuYOYG1-;H4%kt5ZGrV_ne7)ke`Q8PFW#Y#T{Gw znZWrUn9E_E@DsF$Rxk=WG=_C9IY3Ha(`j=rjiwn(%n2L+#+4ndDY44BtY585WyV?P(7vM*D*UYhq8Hjn=o%vpbhq5! ziqI)jL-D;_NbUj~nZIdCqM0^PcJh$!yY`@5Hw)?sDgOdHa$&;T^>gj z`}~0S@PhoH>?DB@MD^MJ3O26rXs=uwi?Ey_00hUwG}__AS&ALHOQRiPfUq4##!@G< z6e;>O6wbjlEH1`y$x0T(tR8Zbo}IJ#LGvw*5_-Zy3>dUSzq!$DuRB5;*UunD5y#p( z;)t4)a}l`#$AE_S)qN2KSdVk@hnq#_I;c-PC)=ou`~@U&W?b7Nt6C zh0d~ueYeGI#FcgZ)-HqASNLvjOnyquC{nn#*PL(MFBYEr-rs7{DMQzyNFeR2^t;oy z!tzDS!u4jQlv;iEJch9^4b}PlwE}e{Smjuw2{~l5k<+$@b6W`uR ztkK+$-8Nn4Q6ETtonDfl3!Kk2HOjNqip#&tbuG%v9+qLd5@9WpISGx4@0+r%!K55Y z{Flq1i9uLoE6z8AW>&+EskJW!FY0DNecJ0AfoOv^j@*HkP&~4mh5IYcd==V?HaVkc z)ALeVbbZ$W_nGK7`>82rLa~2z8wHG0$yQs`SnTT52dDs~e(K-;_00BrfLmB3<{ZRi zd9+lPakeC$03Ytk)O}_=QW8_}b}3ZjOEGX%5yz%%WTiZWP_&AA5Cl3308MLzGXfSdeg-}pHj^c-i1K0IbXuB7r44d2rl?XSKXu#I@Pm)yt=}2CttVtatbL(fZ?!`{ z-Lq7BK%xk=WCod|GrpaAj8s`GZH7KrI3iV&J|dZ(qL*jYUK0lo!9B^Xs*t`Rm%)3} zuVBET4omKH3|bQEIBGd3&x0>IEnt>V`%4CP@#mYS%pnXQa=-hXfaE{ZxVWo`!7#;_7AMI-Iluf!ElFdY(Q~8Ff z5i6Lna;NT6ML5WqR(NYk07 zeEeF%6}DzI0e_gOd90aGMZW1G10PC4A=7pK$yQIKH{B<`AVkm<-dpWd;%@Dx8|CIA zk&Xlgy}KT#W!hd3In#%7KA4Bi5f$E^%xG~mf~P+JoRh)iM;{f&%gnRq zp>56fEpks!`@kNq8}exnA$`V~=f}YNTLUcA0Jse;L{N&I8Q)kL(r8kpzwwkRzg z5P5zOKx11#T+t%P-P5>z8dGcw?6vi^kzImx2)G`)F%ZCF0!nT$_BX(XR1{B zqJ0Y;?JVkr=<;}DPAl;rAIt$AX<7}*ar+t3*FSlkV!HZs2%=`KjrW|oWr+b&rhvGo z+`LXU*iG3$SWidN(>*2$d!}aHi`JKTrt-%h+Qo+1X4l~gg?_ujmtQ9J{QTe|CwPYZ zYwH7HruxhWW_YGVNY=nl6KVulEye5=`1ezmok&&?@PKSVByIxM@#B!wJ+M$tsSVmhMohSu7@a5 zmG-IGBItDJ+k>*Hi&j4@QAP+I)nhHl$TXOl8nizbw;IRt%`x&+Q$v|;sYtLE*aQH) z7=k(m#!rYd^)22N(wF^cMmIIPbr1@Gk{fPQlOsls^Z9R$7t2K?1j6$&ArVKd2YtpD$ zCa|^-g|TEc!JSs#e%_v#V9`Lx?0PE9r)Q>7zT|8BdIbs92Us$#G6PU0p1I6o>j=ou=%7_tI^>U{!KN(B#|R0&%)2 z)iP0nQlF<|2EM3G(`8Z6T{2ZPb<>pd(=pJqwlqh$;fTV>a!npfEa#iq?U~ST1`{Yd z)C%fD6DxQ_SIJM%@2QhBc$VYiOg#)&%El))1)b)uPdzzG5zT8N=iO}ZwpJJEak ziZ7f1-TJsBPJOc5)7M4tg0VKa44ux~KM5{2U}a=vAyWpuH}jC8czG0+R)}h zLbg=k3>{>w!WiWWw3R>r*$)C83@wYy^s=}pcYW~~Fby#(+ zA^z)Z`N#KlC&nE4OaAq{(_j7Ot4w!P+b-k<(Qop%Q&(9tvFVcYapEed4~i@{&04qE zn|~Ec|2SC2iL7anVhfbRgsNTogh3_Hzx|Ur1aO{4rgWaP;x`bRL2D#iW;C2eAxo0z z49M43&p%BJru1b7sQbRc>7AN?02e{U5(+p5uafFQqr+nZ^F2kiGx+fW$&}e(+SEYU zCwH3+XRGmw^pxW=e}_k6OG!P)td3V??JigSxAoOZUodLCv;` z36*{)#HJ=?wFs@ca7AJP_Y#Lm-^tNSy{Y&+r~}1eek8^S5)Wukb-u?ZZB3Qs(WWSV z3!g6Wsq#^^Cbq8xKz-s#?<8xdP}wLI#C?A6BM za&qCrNx=&l$+Z#8fB1c;M&3UEt@IHd)}&;yP-ae3I(??2G#F)wa|4ILKp1q=r?%d& zEp67=>JPWc{i5Na2%A1R$tq@e=m@HzOsqDAP!f--{WZ2^-K)DgagsKMkRYdmD6=QS zTaw1T_+JL-j@I-Hu;(aFMrwgoL?0Z)IjN9~Oi7W&?JKD{WD&9b)E}di3a(+L$2#Ce zG+#)ag*dj{2QvhfAZhiw(*=qJ*G=3QGv2DmX+N$%k0KE}hzN2Hy-`*UV0a`|KKeYv z?8hp|r$o&Mi7v6tO=#EMw7tBCyi##cChRWSpyW;>u{7yoX>z>EVJcoioLs3g0>(qdgfa{LRF2eZ(zj%+IY^AS3zAsmEb#{inz}eIa z{F=kbw_2wZE^Ox2tQ~uWATeMo7Mf3b7jY;%Z*li?GcV;djPmafro7K5k4>X*=+nK}-;c8W0Tg`00%hY4GBe`xwS_#agVF*45oaH(5~fNu4<%^?1K z`{;G{)IGAZU4mfu2vbuBR|3Qy`9L*o=&BDe+m-K~AIh(yGir5L8#ed?bhfm>1MhPv zp_o^9RZe~aO8zz47fg-qZ1Ok3*N_HW8im4rXliZbGO_UVE&`XX~Eh zFnYVQ#CvfU`U%zut)-`VfJbl}ndP%vn+@iNhg6+lPZft`u1~mGzGvM_)k|IYqt8#< zEX_VNdl9)AynjR^;ysTC`HF4<`sQK6c0@&e6WmX**}f})j2U^MnfQW(-;IzyVLGe! z1aw6x(TT4VocpZTws9L^`!EE^Csin{D<}?*rjWR@=zNnL1q9A&2CV?(&4N{#QQ05W z6mRLD?+h);zeV5+br?kJ z$92F|eoBK^ci&WS=Ob|#U(Q4sDnTsL7DxaQ#*7<>eHR}=EG)z}t8Xp2&|#&-ExE&m_RtB<`E5FCjZPpTmM~04^vd(+B7}rEzmy3 zTV8#j6P-P%PIPWG=}u$QCR*yMH!zYB9Y>9nz(q?|GN4s9wMSu|dpK*B(R8sH)k*n5 zp&HFgmo(-u6V+Y=o5&bO(aGgBTyCA4+Rmy;O(f*7)7UO!=@+m$Oe`xQ)6~CDJKy6u zXhi;=E^}L?L4WpRoJfFydD2(5578gW!F))9q}qv^(Y%z`Vh$fstCbSBkn;X#KsRG( zRrgXue^HbO8j&aCL!eNdGT$QQAZvs{6-YQ+zBf~Wmba&WGj*;vrFALcC0UBf^IcRu z3K;5eDEtq(|KH~5n7|D<{9<;MtP;Rn^11V3tTF;fNNS}axwPW)$ar=C-x<^I&Jtqd z`X4VD2m8LUXAxW-)3&%ZE%p+es_9SUb4xRbyUP$Fo8coh$Ytoq7w2*Qqp|WvUFe~# zoVHxZ@4L0Doi)d#!jtX@Z$6D5nl5JxpUlK23Cy0xqD$fab}3oCKtojL86z7if&9z9 zUo(Y^Z(KY&MDEH4F*Wr>nG6UU-Tn?neyBV+d_X*YjGoB<6YF?;%=@)7V0(rzl-{7Mzpg`vd6&AtA1xUx8q3aETdNA!a-xy#mf`XFQO4HuXCgP@r0MA>g}o$reAjQ2bZ!?ZIhH z(kuLfF|?sugA67T&jE0Qp?8u~UYE^0U%QBx-vB)>^n0EjWZ;*Qnu>HsV86vWja*(_ z%19IU-(tO_k0$9o_<{ExvqDm|fVBR6*SN_IGSATU;^;7Yc*vo|MBD)^3i)&MJK&Ao%=P|75FNTog5+A(K9;Kx0> zCLRjrE#g3yX}s%S7uijiK-ja}DammI#Bc`PjgzC~$(7$&1bpD0G=_|7zglJqaiDZe z!U`Q)xtNtGFqhz%)P-bCBjzbtvo)bWsVe*LGi_XEIoh;Z*4};}q&TF7pEgW5djr(o z<6c<(8P%0MAGmqRrtN_`gY4By!a>X9cufK*Z|(9Hr35F`R^xJCygY;Wx;+)|C-?3c zx^B9$>J;a?<~W5*Boek-A(t1Y5j_{mN2!(eG|Cb0Pa3q;3O<}nWoDsGr{XP%1wj;r z=7^wufWXEZEdZ6~JYvgr!oS4h*^doYtYOg{54xt~r;8q6PFlZvxMKq&o~==8E=-us zw94vyIi_p_|2Ns?TyYCdY8`(TI(M~AJ$`8VsvHD+sjBXHN;`8*=4S$QQ_4?fXacm z55&qSU3k}3C|=xyKR}<7dyGzE^D2ZjlYpF&@@rdu+3m}8RO>Ns$B6FDKA?osJ*bjQ zJJ|h=cBu|0S4+@#i*#k9%`y>TlNR-<3jF0;QKDq?m&_@lkRM?QxL^PsdxO4spuJ%M z`?IASU#rWq@!YNPvCRq9ad1x)1ZK;1Kn|kBb78}Iyi5c zQfKwd+kyP)1V4x05MB+fSbSmC>EF!22^y;B9FukTXy+^5k&$@NA>^*Dt#x}{eM%7M z{!#f_NdIgJcN1&OJ{5e&XpWu}CKzY)ygOe58D|2uZC|T_u{}L8t%yaT!Z6A`21A4b zIDw#L$jbKdsR}ej=m@T!#xnYJx=kq??Yf1AaByAE!AZ9&Pi0=5*n>_YXQ+~GWt9-D zLMPkGWe2hXc3y!G>$YmRwX@qv{o&~e>h$a0mt*w593R@Y4ha_PlYtyL@{EvA4rD)M z{#4cE$r_QiOXqWDhmtQQ(%V+q25R;z%ptmddiRIgrrYpxJmC@ zGWq#a4?1DZxzClJLDlbac)gKf5Xwg`VTAlx1Ez6kbi-QkkIK)dUcb+3jvm0geKKMG zrxjl!kYJ}VdKAcaELOEFrJe4%`jd#e&+fy3-ASSaOt7pY%FnWOlO**&Zp&ZFuUK-$ z%~Xo2&PaPJ?hn%3V{pWrbn633@H_JuQLOb~>8D`2uyoQg{NHxw!Cd0|`J{U+0nwkV z%w&5oEJo+-UxQowKLWKa3b~i2QhEv!^mS!4b|p-%7bg$ zC}zGuCtjn|-&^O8$D~L6rC9LA?+l9OhW&!<2UEA|XnPJso3eUpR8@r0!ChrenuaSb zYCB^o|LbSO|I0V$a}<8e7;9w&LgHss{T8oTTX2}0qJEtiSTPT3%ms$F>wX-~hDhqA zHjTnpJT&Z}t=|H)^0I#A>aKP5*l)kfnvQ)atJL3sxA9;YLNb3^YekZ^K*X9dxjJhP zw(+qld1JzZFs!VXWSsp8V%~wwes57vv7g7M)qH*RCq8{nsBde&i;e}?cc^?^T#)v> z8o+6)_q)OB&WO_T4qt!fU_9;bZ$;&AeI;a(tNGqw;MHx1H*TkzW8;oBv~0G!IPH9( zI(RV`C#vOgnmOtH9PDmoL34z`Q!#};5||WxCr#h&v6Qrx(YE5CR{l{^_P8GN#X&s) zNlXEz<()|UOP-#ztvLHzdIgh2Qelsh>-mU;c}rSQz~d?^ZCaVSSt0P{i~A~JeK|06 z)^e9N012Oij7u(N3lt?}to=l_T>EhJrFw*Y_*V+xmHRD@uw+Mr5_4iCv$zm)7GW}W>3(ld0yxS6xzJ|yY465p-1e)iv7ftiyzGb~+p-olmw~*Gq z9>}9Voc&7rvmbZ<0=0fzn%Yy~b8CK7{?XSZ0HRsQAh{VS2EkZDLmW)x_7E#=u#WGW zuT`?nQ=m$s!gM1QsecWj;g^0Ehy!Z8ICt@MzQ;3}%Vc6N!y%Rz9&Z>SgWSX>HS={> z_r|$&^}VIwUyD#Xfr?RY82>GyG%{u0q6Wen$=Q+l2PQ%KID%(3U#eyCi2Yf0`t%yZ z#cUj*QiP}dUX^Q4rV#~A@|sDM1yB!W{Oe#mX;LfRk;Du4Z{#|denNc7OsS0i)M$4H z#(%L*R}1m4qCA*-%%F+UOycd8#Ut=%`6)owYN&TuE@U#48~xKjS!#P1aXYFMxTkWX zTbC;{=ibN!Hydknx7D=}LQ{eq^UGtRDoO8;6PHH(7=J8%Y*}1#XCBRP6dm8T^DDq+B`nxPpin0 zCY8+-%w?xqp9*Px5auELkFdkws^WR$&TbjXr2*DNb`-4Xg&WK950-1=xQ#L8E)%XkbaNj_x0=TuBzqaG` zB0OIS#40mB3prSN8mKVBMA7p66pew9ZqT#7<_tbuYc6A54yq}!Lmd}cggbBtK% z`XC6yXE$>9+644#ZXRCFY8}syQph%^Nr=u`9n*8?@E_0_g9SLQGQ@*7pEzps zp60RO8gf2nbp#-TG&iI=nWHI|nn!i3$K=`vuA=3tpv$`SR%H^;n1=b}*3u!dwS333 zxu^$%bz;CT+`_yG}%b@R%zD( z&~f-UKWf{vJxx>D)QS;Q6YTL1mHlC6k3=aPwy|lz9cGWBV$>y^RuTK*^4cMosQYM1 zapRr2LILjv1Ve36N+heY~#u{i78j_%Fq%DRS zuyJ*=@iA@NR_-!RK(~}RZZu=Hj~V=aH#IoYxQ`=)pOzt(HUeE#-+9ww!+ZviQf)&Y zkGS1R+*v<#-+jOwvSLdm9E71D4-tGozocrah)NWJfaun!k4DiCl*49+w(e@VG_dsUxtGN8G+OxEA6!Tug&1;FR&|+Y|zCINH zan?~AMLuQSBZvaRBp<|)-xYB%hDk+o8)2t?KVg(-X9is6dzTPH8{-O#za}v7HGz>U zq+R58Og+R>vH#FUQphZL{PL}@;B5RD1(*Khnd~U)HZLP7sraQss`O6R-@V}1%>gr^ zCyNcfglO|%W^@g?HuS!JI&btPn-9Jx1rUD~f@DW}_HMdsz(9uNnLn2!B4{*IEd^j>Kg_$_w?;SZ-8_cM1I$^LN^Q?v<= z)=Pu*lfKC`F@l?dfw2RDbEg|=Y=ktnb0qaR0y^YNbl1Y<%rZr>OIdXgw*H*`Ds=V= zoDMY3fVA3&m>}t$gR~Rv?LnTX3q$vnfv`it{X+Bia~4>mM(==Sazde>GJofq8CytS zy9MD;*9HR)7GibPcg)dzx2|WNF+iswQuw-1XtgSW;Z5i;(vXjBE z--7HbhNZ+V+6Sy0!!?$eKpSqxIMJ(g!R2Nbm1!NjV>nYOy`7z~4+X+C#mVt(??5%~ zf|v(z>Vx6XyG^~H*26Zk*FV6gtGJPJ^lG|pC*q_UPQ{oh4R2ELzkV_Mr?30c`aHGp zbwh^~hm%2kf+oD&h(iY6mG3nWUApu!-S+g5=jVh9%ISU#N&eAlvtX$obG+ucsCQ>i508F4w6az5k2!m6P!vx-I2s-$V0 z#4Idv!FDS{oQSb_UY>Z71 z8zZJX?ChfNzPP3*U=HrKOPKA(Ig;K1j%9LnyI&wD5b($WxKeK`igdkTc%eD3jK%YH zKY!*P?kr%HyO#aZ=4)I6aP7asV3HF|FiIld;Gf4if0#zg=sc1w~u{hSN zv-y8u1Q*gW*3NQFk1tp5q-h#JWaxyN7lOIpNlmltuQmeP6T}Ly(2b^`v)o+RYcb~k z{0MzeD6C`8Bxw+$kq(4uijZTz&hMHbTu!T~yA9J&tF$yK(8|VwH)=xf zf}`3v^1vGXC|dea_YT|4@lG*1lM99&mu2qkO$TDYs>1r<00GJ|O#tb&IAf-Sy)M-t%CV^-x<*!C1mGS37uq+$d-8fn8CzxAGs1n}?e10m+lCAj2n zC|=t^hSmQr8_J!>*?C`q3;9^0yG1%z7P9pix&0m*K}M(Xr=Z#@hHSGv zsJp>txjO-q*?WNxgV-Xe>mJduS#0-t;`WGNwlt#h%=+r-K|McjxJA^86NSKY8|#z6}#5FZR|Y>{As@1jwC;uU{_w%t&|?Mo4bIF-sX(T zA3)m$to5_T0~+qv$OuAteRFkxp`D@UeYLrxsTi(0T&A1!_KG1ocnH}581 zkmgSehb9QM;ov4I(Fryz_v=U`99b&~W((q0vNX2?WD&wraSf793@Hb2giQgNROve; zKQvq>*-_tGhw3t>!WR=QfB8K*-SCka1Z6x(SAmJvm7Epf$q7kt-%-jr!Rs6b@>{0V4LJgZe^lN4I{kwq3I~PZ|7@VZ~MW&Nh-{Gd| zO~AoTisl)J7PnLE%h>4>GgA76dg8&+GYNbCZUMP9CCcJ`GRBG^{e#W0wUH=aq_oP! zN23Pd{6UA;?hnsEr)LAGln*7j!BuX0K}?3FG37{s0jPH;d|&ki8l}L)shjk2L*<)? zD-un4!ALvV_fTEX)LvA(E}=A90j-rahR9Q#v1qjy~)NL8)U^zyyqGww zm`-6Tb}P%EF>Ob}7>7Y${GCEfPpl>}2%FIb%f?-hJ`<@qd4jf<-G8?EMW1J>d<(Hq zJ5W!@B3CX`edM@13u}@31u>q~U+sx3D+bYyy*BVKRLd#=H7`=oa(Y5a))r$QuQ35Uog=_t?(D%CwW-d7bP+i)~58iN}TzER^ z`=If0MdfG~QQLg@SijS~sWpjeF60E8QsF9j`;E|^x=IE9g>h*+*6X6UW)fQ zYeJmV3M8is`#slC?2gedl{bd<8(fLD40|^N(ihk~y_tdKD&6^VUz|yNm>ltd?HfYG zw2`0H|HRdBlzeIiIu`3wg3hEC`1sn8|MA$Nib1~O{AZ?lE(OU}`|ygD9tf`{Cxoi} z^pxq!i62O+>36vLVnCr*sT#eANsQ(bbk#4zjI3_88Z^hlZxf zVol0TzGJUlU47r?wh0sHNp6F-nyFC1-jj4fl|JPbFJe1jQ}Ssso;7CuP6eypNUgS1 z4l`gyJ~d11#tILhIwOx6AXHQ_M0;(9KR2=s!3dOoJ$Ps64HMIMtD1%#Bw*EcObn1%T%FK8m-$L(cmFG`oAlL%{=kOzZ#9n7{+LeSecG1IVKePxOMH1p#xQ~fC2L$1o zZwzo|V7loXY zZm*ZkgF^l3*LP-LKKq^VCde*>DlyL1#;GYng8$mSHzYUaHmti^ZXamo-yR-v_b1)b z+jR*h`|b)1baL)S^L%b14W+{1c*JYVzCco1(BMzgtWB6prfVY)Bmd304}apRANm!@ z3XlMn?@U?t+0wVEx4Y00#*Q{w>yJ~2@w8W>4`DPR`Uar9!&wc`J^oR`H2+Y0%a^wS z9x)sWJij(v^o2_B9i17hqNc(8vSGQEvYKt>{IaH~2B9Nj_b6(^wphTy=<&9f>+69# zM_zkG=__TNaP5*tpzuG+7XC0cVj#3jNA`~vmj9P5PDP7^t0!6QMOG;D{pgVFkB`9@ zMx~%Z)?P~L3Tdb=gYL8ci zt71f31GU$p+mligy$9u>%8T{p24u4j{v|GJ0YrJ7j~YFTHyhq#L|%%bCNVV^hnUXt zga+Zq^Ff@G_IfYOF;jvTWhDsm_(NZzL{`RD8?0a}bBjt*@Hfm7Z41e}W44#V=TB8~ zAce+)!4LD3w(%WZo(!+##-yk`N&g2idk%^>5d666n_1U6sl4n5?=uWv>TW%#-y+@R z@9YaC&<}aD;{r0|kdRg$v#>YgWvnoQ?RE{i--gd*$Tf5@u7@77ISZ_-0qXzm%2!ak zwZ3gwj&dUG&^fY9?MM|WjKM~j?UQbF9?ys{2dF$2b&K1Uz0t7VLms6N)O3?SF6#() z7cwK5Sb`tHs)6}6B6dIU1vQ|_s3*evsQDY*@-o;Q%QnuJl^@z;41}GDCl(RQftXe> zz7KC2m_&ie1QYSvC;=K*_qcnkhk*AoBI0(B)ccqX+G9sVGt_?~3Aw`hb3izDGdPnL z`)|SN9r*lMp1h#bl*xtV_#hpYL~8mOv*On_w1$cNZ+j02*JDwk4_;df`=gq{DtR{c zCX=okfCFH&rG)KeV$?s%8vT=uU{!CVJ)_h=rAr5R8Jl-Rynu<)o=U!rW{?5n;|`LS z4%CO@M^numa7#tKT2-LN1CxN?k?Th)-Pb4ZeBhea_w`wACwLK<1>;*aE+s!4jFc4% zX-G!#+bq{e{V9^YBThX{_K+nmt~chxI%azxIRmWmYA4X%F2Vf;ngcqWc0@7z?MTxv zTzitfXMLac=mHMiuN#-|b|I=%-jhTf*OksJFRmP6a+ z?0k$vCt6&*1%uTycSV=hgQV8eaw#{Ecv`+VMmX!e`Xd^)+PgpZYP^H$brPb-gE`8m zZ>e2XaXqzlB27IMk&Q&jiv_Ms1W%fjo(|`cKbq{Dny1y@7SKQYg?UE>Qaa3SJB9s^ z3p?-=_{875)M46L}e_J9~) z4(co8X0l4Xzb0>(gq_omy{d&?p#ZULWpb&LW=lx~I*RrG?CeE}nsyi?WR>kMKT>jv zlNikh6-wJ^(5H~r5gMn%lG0FHQx;pI_t&Co^+oP0U z!Jg;vI;{a;x}ZGlKBJ3}2SF%FT9;JepgZP-(x|=SOZK^pjWpX^XkLc{%!w)RioL4i z1T2uWq&sEmFc;R6_Tv%kXV%6QW?*(caVu}p`chVU`DrWEw$5VFtK4O&pAe`$m%C3D zo+hJvN3CCQ!1Nm5uwC}AsbBL(+uDgH;sEfn0ShflC}f~2b@pzpH-c+9UU7YhSe}gv z`p{Y8Q{1v-Ina(fo1Iu<+jrJ0@@Yyr2c(E5>i#OR*T0-`biT^y%1y(9x(0=shNBYI>@mAz2nf~Xdm5)6=4BXTRJ8$ng+yHb! z{@pHWZ>HWqCBY7rWaFhv<5-L$&%v4#h&@{Z16xGF`K%crm61V5iz|10!A3%NG(CFo zTl07>G6BIo7ji~~or17HCa%$UoRKiO{^tLPO;chq%#`ze?wfwfnjecJ^LR#)&J=v2 zi2WNu6~b81NYhH=F}zN5z*g5Efa3?plYynE{6@dj3R9pIXuOqNl}8s;d5mDQaaDNz zz(V6@g$0i&>d3>|7+&rMV<v3WhM6EeU3LW(AH0>a~Gce zc~7I@`c%mopmCMvvpLKr2iX1q8Es&&zjX!%aFz@isum=hZmAGfn<*3J7Ts1G;k&-S z>|pRi@!yxXSey+fQG7OKqakDzH()~Usq}e2bnuQdX$hQjT&46EobO)0$|OS(T0V-8n&ZH#r#x^BkmN1}tFwviUw zWk@Y*i~c1YC*3hBKj;ey-dJL$qCY|oVX~g&K~a^RlhJ$So!FXVur=E+>*mOXI?)v7U`9pbd~F+-2Sm^|T|Mqw-u{c5 zA%FBU;A+*yKg3cc^K@SFeb)W=O#Mhu{X0|TLO36+@Prq<*l}Fhk0Ln6>M!@T`p1K$ zNt@r&AwSG&BAZ(TwH5so++65F|A{Y>Y1+X$zC*gSKQCIG|2WE(H?-tDXUPr{|Hf}m+tXy8$1m%@eaKWq?liyC$$&jQ4C9aH>30!dWW zS8~M88h>(La_!bZ%FDeebbXeAuyZQ3z02qvi^3j^BAEL1(BICXPb0ue+%Tz69pGEd zMgjFtt{bav9BxYxIzkZ9{BN#5l?}t>59N|MWk@PbF^SRwIDGwtwZxQXI-|fVIxu;B zyqN#azN&YP#FyEB!sQ+~PmNVE~iz)J|REWr}k)d27%myY2X{ z#^Gqg`bO(|Mi23mi;2t6{dwB&ynG&xs|Kby#TK8|lM1LofsRlkbqEbAMKIA22*})R zjbZeE({)8cDRA>tW3xP@j5XTC`SLQ3y~e?Up{$ViJ(l~Y&31t%SWMSWo2S5f@1j1h z*VTW{!@jP5{XKIs`2x9Q^%*obi#@{R4#PL<%J$NSeH^eKCh>cH2gC!e#u#cTGNH=_Z22s!H%>Zo+O;GBN9$(FZe{m3cIpN`T z70{fE=XIGKu7@vI*Z3pKx53@?z3i~Z(D3KJ-cg}R1neePQDF*sK)-CDUZ@PK=}O*V zBt;m`49Y~LTxCHsl$Y+`L1IuM$i61R7NdU_)Z9!pnrSf*47{jV6qZhDe1|SAz-y-J z-@-DuKKuUeB00wL=Z^j+%5q22hwg8`Tolg8kf@s46OyzLU^lbPMXm{liZ;K4QP5SZ z&*Wt?!c}y{dpzBRt-eel8{~pq-TUh5|94t=5##VnlHvdofEPjJnfwtf8HrW>iFcXM zc5fM_n-0FQ;!7@&X4rj~BqrC8T>GKKTdmL-B%9Zv)FiFX;;P8&eHeZj+Z1C`Q)jJR z#Xn|W>;3Kvd=~*XAlKm3O-*jy!+s+IiNJ2%a&rcG$EgyO-;D zp5fYJH2IbSYayrws@a{S7n;%59%Czg^%U~HxK!U{5X33l!(*{$ymE}O%j}866l#i7 zrwjfMUti%@<@S6{cXuNtAcAyvcc?Td-6?qJ5~V}B8$`O{&?TjC=#mDdB&4L}eGceX z@9*Bv`wu+1_sr}yYptnx_mkRX%p`$f&LgkHBhCJ*-&(l9zs=w=(_;UX=IbD1+y1vQ zmWX@Xm>xk@u@Lrm9-%V@vrKGyW0h`eVL$3mXa~7r5Df(3bXA?c2|mcMmYGw0qSK$) zhLb}a77u12ioCkFGDRGFzoKH5>#ufWZe@C$|3hzX(a!EC`bJ;5AmH5o3z&s zLJ7J)j2+_GY`afRa}r~!c>b=KeOO(I#x$1mVpNgh8{=!HMWc%wlUZq^L0LZsyA2~N zSIf#=Y&o-qk|@09=ivA&5Ar27(oLLw6-Mj^ACXNQqHFQ6S5d}KOy!(e){L(nW38IO z8$4Gm(t4=+wBJ;GoMYUdatiw`Ds*F5Gn-*AUkJq=Vjt+^uy} z9?rIH`{V##5`Q6I`azyi{M6q5I+|G)Cc}u`s%L@ZvA`zFENg<=B`Fe~!Sk@(#0VR$ zms@F_Yspv$51(iStat6UjE<)dCGva90Y#;4DL<+kn0^7D>ATCAyB&xuW;fTKEV-8w z!%Rx?oA`b%WG8!Jul>NFk&hsZ0jTx?8ZZU{hkr?xrebrkDi^Sj1XHE1R>2IPmg9vJ z1DqJ&W(K`tl2b3Pls2E&9*JANNYAo_W}7=O&e1{$&p0v?|M6Y;m^|)PtL^aQD?7oT z*6~2!i^OOn{{ChuZe3=!T_lbEQ$r3Zg`t>+j8JsYqg>m4y3-WO+PQ1KOqSCi$yNj( z4acNyk*_M)cG`RkH?9?4#SpHV8Q_7K{SmR%Nt8Qr=-G)-F;klB*N>zt#xY{Gvhzqh zowoS@Dv0jlB!36!3!F^d5VMrjG55wed8%F7GAqkW5JwWJC*odYx)a~e&_P|{4)P&c zvt~WrRjQe0P;P5A7T}*mxQF>>9q;&Mt6uTTKwGp`R|T1u=oqxpn?#l)JWJ-pl&@^D zeNl7DNHIFajv4vh^jf^8xUZuO@Esg&g;K@c*eEy3|FrV@Mvu+XdeX*i#{HiekQMNo zO3Cek6Er+idya!FK3hyH&Mi1;)0z_H&?P-=?ER?k@p+H{CbA)g~Vf z2y_S$sMUvI5*27-W%N&QhFYC-=1rV|(W(rXPw{&YL80ceRQeL~BYvFd zoB!D_?EZ9qz|N)Br&>b^e97M#2)-w;chddans$E4HaAc$lo@I$1)l626`yCC=>EBED zGoywUgdbXsk>&&8J1v73H+EfwtQsyIg|%;Qu6|9`QZKHd(oyyf67NYgSteni|K8b} zr)j-;r!D5c>Ou_6Xb)Pt7at@!yS}`B33O0|cYhGs3BeXfksCKr$gP(1e%Wk%)JdP6 zb~*g_R`NEI5kx0;pKfgWv`3ypIQflCcPoN#N4V%0596t&t6e5fSgQO=G|rS6;+zhq zZ9{-PQ*8sx6}3PcHhT!5*WTM;c>N>_05B~gKC7G&X)CWTs{1oskpa~n5avdBf@S#o zjFtf9BtVq=yY2kh+zLEM#-aU%ocy zo1|a$qE@=ZKUpr%M4({u(RupFsCRx@2Uo-pUxjeYtG|Lx0G6c4$0v<^Y+oaFXDNL%gH*^q0z?-S1Ps%}Od=O`4dx zTC_Q!!>D&Mke8mcqo4L-cr7-Mm2lM~^;(R=!^<(f6eDUJgD|3mAg;W_zm!b1AeW+dg=%GpTR;Q3ZeS|((QM131>iRMus{q%ZQ3ka(st;VSoe%J>shWy<;T8po|*0`I# zvAOI-1^_-`Tk= zlp`X2v`TBb9UzX!NKbxJ!OnO99&6A~b$fM7J5rXK3sy^j+5?FC#+(U64!K|>n3jpk z5xXiTckjO+iBZbqu66K>Zs~Sr$(u+$O0=)9qSV9kTm6Z-16qj$^Qk@ot5$sGFtxI? zqx{yCQ(n}FF{uXsuBTuUn&9`#`lI$USj2|$?Ct2(22&jb$nP*ptX$@RhHQ7Z2WmV9 z)2sbY8;DUN0)5Mm2gQlm%H9N>FW3{>`{~^W+i>|dnyWXOAs$=HiRDscS z1f|3)^%OF?_m zdglK?t%3}ca(g}$8LD3Jd382=EQV7@ zD0BpT={{y8WLrxYNVR;WKm6F1Nw5AMh1d(S=z%1SK@S>G>i+7ljl(zWvJk8X@qm{F zj#Ix&BSE>o!(c(pOkXBv0xYI7_1JrbV&XTfENg}KpZ#O6%h0KSgDFRB>ffO6L;$Lq|Rn>drI zaIWx1dl4c9=F@UcVjP}*qk-o@nfDX+L{Dlm_BsL(Avylq?!~4J3ApxR^OURprEuYS zu&VbE(h3@NfftblejBtP{ncu9MKBDUNdj}};%DNH-V;5th7|!%1gIJcqZ(!BC6iA1 zC5sH@WLSRk8KDfX7-*h3nsi)U)afzI6t*V@iWq8IY#+EH7v3vgTu;Tp_$V-s0?sclT-s1Pcx9he)GwG1%@TaeWFoJ@r?+eqAYtimEK@i(__t9 zmUax^@v-p>m=6nHO&#-@_gR-=xq0tiQ5Eg+t_#3lzYTCz@P(4pdNBe^LfVwg`m(hJ z()wvARNl!`xa}GtVSFW&LI8Kapj@$OEW21whBIK9mr z=uIyFD47IRrJ`r(7Gu4qzpP{??~H8-Hk#c6hQD>ea32wD%5a zO_;pPgdSv7hnk(B1knT!YXi&5awn5)4#kJZeu#vvzKW9qMgixQ;#4&ctj`)F?1F(_ zWQK(c)erk^av%b4(SRoI`8Fw!KDdvw4l_TbnYS8}WkH2=XcDD%tA=5D~uhtljL z@$JZ$&2DDJbK&rX@RN9#9|8Jo!Q}hYn%P+L`p@j_{z`bq0^;bzgq6C*eb#pNLhXW8 z_B|Zklx<dViRM4KB*H{_s*f9qj7Qz=?IXnpLA#?#~GSqvrqJkfb!$?gsIj&@buHYDP>4{=Bk# zxpTb4d*md+kD6re=8q%?39Q@Tp+ji}JAx%uZJEh^be?*>8d7ovb*G8uq(=HG7jDnJE zadP?U;)p$d^hV`5xNWiIRn!9N4tG1S10U=i($DzZ7jBmi!HsCS9BD%gY7Jps>ygJ1 zLsX7{LSEj)OZqXCO%>wX!pMsW|K`FqTXjES>O-bMctJX!LLW{jqA$$3(ku7L|035v zU8!WthUlET#p}c7H)O-cr|{v?ZHzC6K8SGV7&a1r)UqNfIK?yehHtK#Oi zTuH)++oO-^%V2cMav0GNd#;^$JIa7I+fom{09kwT$l#9s7H{u-*0sq{9F+N#JDBu+ z(9129X0kAKtSaG)*P)%Qt_z|g!Ag|!=0$3Q?}u(npPJcs3Ls0C*-31@L%DdoQ#+Q} zl+u@{yNIMoc9l~%Z1d#5p2G&xrJ~DhA`ynK%V;BMH}-?2^}rVz;$5E)xgVAro_+U7 zR3bN67w3z3PEvo57=4t*m*@C5m^dbp$fS_@c`Z9(XBX9#wNzI=F4KZTKiPsw@`+`W z04OfWz_dpJ+^u~etM++lww1j0bUNMkY;a{V9tr zxZ^`Obo)hS)~3~XNge*s*BbWA@1b!W9z5G+%kp!q=+j03nl~k;92{YFLHY6ulLePrx(8d*tb80qEsW*Xj9-juGsdN_V|Ti{tYtb zcgDIYfVjXtWDOF2E}vswhkg8YjLnK}cuehQgb;_(sBX7;`Om9NB6RN_&+A;nz{~Tb zQ8&MJyZM*pK|3b78uX+brzqLV^r(@0g%XCeOH9SAMxy`SCe&jhUVnl_$Rr^`+108E z&_~5xgj?7boPyS-X^>7BN3eCf!9^9BDZwvN8qlTOnM9E*Sk<3q4Y1rlhkdqZ>A4?* zGazNBrc2}(^pbbkkID%-32@cONU7qAn0d4IePj5?*8Pm=mL{Jj;&wJzuIihvo1r32 zd#+6dD4Mem_jmEhSChdVW@8Z6m)Gbd90c6lms^WM%_HtG3H)3Bp21G>V*K#9Vb3k5r0jGAHyIa&DWW6!6vG zSy$8f##ml;NW^v&#GOxm9rSeHkApoW@4Ng4%1$%g_x?h-eOaL;w5-I~_c7q4x-8kH zuPIzk)8|`rn2ZQ*?*?0asJ>&+AalhSnmq1a4=?VDVBG&hbw9>2`-D>O?B6S3N3GHc zL<3ju@D%%=Crj%{&{%ML5CSjmHuVh4pU}8z4BO=Q2z<1>N^d2GEtO<1yMHnoLzM0!IQbVHmyAf5@i&?Nu1G?iEPDgpErco&J>Bhl1YzetC^zI!#iwbjl zMU8(Z8M#7upf>;VI5JZJ$&E56bHP>gi-3O(Em!^sqk;yQof;QkJj^Dr8Pw^3{F{@4 zHKtLWfl+nM!5aDek|O0nDvi2;^1TGjZ0sbh@d@QfXVBo(_Yz|s{!U}IBUxklhD+F@ z#dD%<=Ez!|w}=GaUpPpl@Qmt;cfENVsA zm(sl7#8dDC3;W@C9JB?f!5timWc8|SKu8Ro0)dV63CY;5FVJKIN!u-Qx_oJGzxi?G zKvMO__2D&ZZ;Nq@wCwfSM?j%AKc-ftA+AauVn7?tZoOO`DwoRHpn$^>FtAS z8H(XL(kKn4ZB*+CXeiN<<|+Xk z!-q94LY18cHpaJtZ&3cN>hZ~LB15ox&f_rY!27D%R=uQ9c0E?Lv_cZT)*&)~f?Jio z{1cZ^l$r!qlf!nvy{IMTQ%elS7Lgd;0%>fIbLpG($o5_)P6Cyv08qp6TQ;%e#@*BB zy$P1fulq4K>FIBzGZ+&AK1y_f0)Asa>yJ9&p<&2%N6gw|bU=y-tTL%`l#dA0UdNse z+LUY;T4;Q}|EFWO7U4_karBW2RPvrDiPiblyeRjQBVdsACk~umI=VTsXiyY-Mr@(O z_F!g=Y`5RMVBWJVT>n_nCF2;B4O)B&j3ywwgj{QT8j?= zF@4YE;Fgth;b_hos7HmK=SW;qaI`kk$C=+vaglz&(GO>Ce%2;8`h9_HOzJ4>U;Q8v*xXHi=P#!TQuICctA- z$bTK|%^e$WnLuU80?}i0aUXx{a6LJ8?chYS>XYp);-iB1{u6=|Y>I3>{Bslhu&uXX^VtweG_0=JcF+G|-*T8)!&A{+OcHq~ALcMU z&SKrk0_s4bl83Vp@^`*ePct(anF!P@7IIAixcEg%$?xn95vA4pKaZ+2t@oCL5TS$BPn+I14 ztu_FS3s@iZ2*NhqjocVtW6|D6kZE{TCu;VR)VgCm`C75Y=C}!JXMBl;(>}UUF=R9u zX*AM#1loZ0ezfkov$_!RL5QiEzNO(11gbbRj_tKL9EWRivd(J4u8W8$3jn|-!{6kw zPXiG0Qf^VcW+;Ex-$Fn?dCTv{Ud(N_up-N`A0#&NY?K=b1JEWy=~+>0Gd6cWoHWfo!pOx9EGOZ^D3%gXW{gVd$b6TVD^1u7P)se zFgzds3oJU`&BrHBOlhSbdIMDpxumlWaT%s*{Evxcw1>%WWkiQtfdaU@_=;fy?k=y5 z(#SYpaaWOM!($>k^XQ_#RVZSH|N0&AqEdDQ=a0b)1kdT_X8{i4oH})&1zk=E#fHss zKcExOGbN@qY4M{7Idx$FxuhY`#P-V0ML8-2b(eil0id<}I1t}u+goD${(UMW1G@MX zC103tbwK~LLIA?M7`JMMZOrG_bw}PZ+QGz4Z1B?vc^jKNVdQ>L$?Ua$eaH{qxhZ3il=iX6PlyEg>W3N@L1D#(>OtgP;SqPKZLVZoP~l%ib<{>Pl2VEOa5ojOnW^ zU=%az(A0d!_YPLDSY3XaFWyuMygUJC*97mHopX=jU?<5Genw?+_Fh@J+b@?Gz^gxm zigYI*(FSc($PLBqm>e ziliIwr?`{<;hB&z<4Ztsc>Zkg{8_0IODq&x_`5e%`)TAmt=L989x@i=UdL_QizQXT ztf|~>rTp#uDki(4lSr^R64V#we~-A|BdDj*S{{?|4_ehr*}igsW;EVfcKi z9jDf#xThllx53^6k@L~Og(ED>MyyL5U;k#NwGdze10%F0$0WHV3as0Gi7XdALG|l- zHr|Y@?EZ5>CqeLpiL58_aQY-hZ7vks+WmohlN3)N!>{t@@tumx|F*R-{T6W~zRuB@ zm*-^w#DEMA(*=RL#`&%~`f*dm;xr|8-8Qq^Mc%kbK4xOSpb9mD0gXB0N-c>3s4}mm zyIL4xAod}@9uGg(Ve9+D-np_kEqb7%rCdkOkV`@GI7I%91U{oW_gVy0{)()doBs)w zv@K|)1l6^zD=*95B!p8*=^$VSVXbIu*Q5#D9O4dQ?`phD*wYj$5RwMf?0a4f~Z zIAD}8k#gMe06KwCh~lo@PEtsi-yComk;5UF+A~<+ez>3rQRtejx+`mfvn!@mFDQEt z$N4->ogm9F5$Orky%cL#6ieX`0CNOEE|%@c1vsgXjr>76|I-3)=?~Dk>X}~I;=Fs- zoWaMfKWTTqb7iyIWA_AX`%%Ga|!wS{!K zMImFeVL*o%i*}j)qNma^eMwSG`>z+;AtHGkmYn(*h*aP|ZoLBI?pG34iTR7IJ~%K7 zm%G9^{zIlYo4Kf+PH~$1F;A^7r)CDavM`!YE3g9Y1%~?iLtS6kuZF2pc*fnpblNKf ztEoLoMY?v7l(*;`qq_Khe2}ltG0Rl(`Ed+vIOtl#Eg?2R2ZRzpzagWFzzGM}&tzyU zE^M70_Af%x|CBD2m`;4*AH?Z#q$exGPs*<+iu`-(xt+5jF7IIhR5Fl#T-SSGN4{+77a+muLHcCGn+oE@DRyPzAn7f4R9~18lIRX68FP1_8&v+eOD-Z>0#p zOEx-}qVvNkLUD3^ChIT*iU|)WhP1k<1R-h5HRRToqrnwjxcPf$HJo8Gne$NhxYP+h zx6eq?ywv4HO<9)tZU?P#T>n?~cU+dA^#rX!PZTJ|R4 z4lqa#x-&^f2gMTq?wTEc%^wfwP#lk3gqEpD4-XwxRpOKp0o{h^YLz_wa~Bb(FTiTX zW}7uCyU{=hru+48O*;bLQ_qi)>w*;$Sf_Ul0$t2bqaFeb^%y0dxhn}Nrd=?MU}|X( zjD2f`G)1*N`F9*UxoE_p-ltgPX+N~laNkdBWuIA&C*@swK%=0jfV+xRiuHVQTdCS~#iTM6e|2%uHXWBFv3e~7=&f(R39ZnZyJg?~(Yvk^GAma54j=H@& zyfmK9w(p`;%P1fyw4My8JuXxE@YrhSe4V-DL*p^&S;`!50Qrm5Nac9@BC6UEw!(}J z(eE;LCqL!(*a4RU3t&AB>cSofRll(PahjH*J8JmHq@pePkm>zWm)uUv=qS+rx{qcL z|K#UAbT`2aD?@fGqP}zWfZ#9+y%B*VQv&g5;%jiJ+40vqQ^cJKU5rlp) zH^VOmTniqnpe4PpQNDJIH@TK{4PdjM+v>Z6NMny!Su z^I(=%CgSLO-PbJ=J?=zh%?&vGN0O(#5y#|qo%yE}lEiGN-v^1euwLn@ycz|OhU?G# z^0`^QxjfSD)vTg_3thX({7G#H4rueP3l2Kb=9jk{3i+>KbF@M zyqd6G|BD{<8zzs$4F^pv^|VlPW8ysEm;BHH;B#%8WqN;n&Ma)GctoxFsoB6VP=c0P3v^y>_%5C{L?AHpW2Ev20IHgNs8J_qlbrc8X>p+e7>d(lBzNb*vCg?1 zmZV(98dlCJ4j^ik>-O`F_?(bu=AXg(Q7O+ai914SZ4T%zhHw?u%*qgrmf@&c#*Cp2<3qPkgKWYs(U}4)ltN;sy$%PtrGFKj z_nH;as9{J1Zt^2smF7+P81yN#9&C1-Bda@?x&?9{-<{u_({}y*R-(&toHATqFAwl8 zFKOPqQmLvALs#}jTF`F)GT;={IR9=7lVa*@s7OyIQ*yq%OL{!FK5$khfsm=2A4&fW zd%v<4FN$)g65ulWXymx#MFZfhz;(I_Yz^J7mH;@=%0<-f!zg)=2_C!F1+czYXQu?} zLQ0A8w}|5~wXgG;1err*_ztkc$p(i3y5&u##jHbX(~`uA8UL%pY#tW`!8jF-sFU*Z zA`%1&8EEjkzQ^kLR67tC)|0h4rrrL)OXz(?zuHbF@|35A1#xDh+;DmV1W)V}RN_zm zx5OV%%SfGJ;@@M(8z0A6J4^(-B>n6g1P)tBGtAoDas94_VlsVk-f#`l0mCK|!f~xF zlpG5}Prhc+>`dO4k2m)*fjh(JgtNcERK;;5jkVj;e{I3$gXkl(q`yxS|Fz;|@b_=Y z@DQ8!dH*$??{8UO@i;X)4Y)sabq*#P{`ESmv)V$h=o%npygOx5tZ~iC6UM8}SGhUA znyZxU^T757(M6Wv#^8D~Ja+WOOap?VW1!`diR^{Pt0Qjk5_eNE>6W1|upf?m%P+-0 zJ?9*|c)8HxSD0t_%oLs=xew?0PVL=-3}7m zzGw9)?^1Jtso79OMG#+jA(ev*2$dxnU!A1-L|Y>_H*aJ%i(tEGg#=esRm zEtIYv-r9bV{YFU1K5ShU&7Y5S6rd(DZM~RBOK+~#(_QRwpivp}po6H_8+?B+9LLaX z)Q}K+D~f!+%qW~9(n98V4Con!Z*0i;mFk zs(<1XlY(-#ytuivf_WM^T^v@(VnG1|1sl2rmeJi8&N+uJk3}g2p^&~Mt4aMWq+e}A z4Cr&ZZ(%j){S;ylVvO5h0dEek%|X&BDk4KOk}81?Lad5Ruvm0_zr54%GP;{?WI42m zzSdoE)irVp^tBE?nL9rR_}+~cPF+ORfC7tE-M#%Sk~m{goS zev3KcoIAF#BOv|)nCKV6VqXUwP(1SZ0Q=b39C(^(tX)mEF4EVGdum_&{BF#ey8sz@ zRPn--rTku@)AknBSVsm*cOq;0^9tZ?Mv0y@Adg=w~;i}S_ecdVSR?6vt?20(|V z(p*FJJmVVNEVBurZurW0w*>RWjy=0k!ns#**eHu|E3vKqhWH3UO=M@R;#Wy#C9qzjB*~$? zAgF}|isnm(_Rm#tUlSVT$?YL7W6!%GWSge%%=-rF!y;mNI$>w!HHB@drxxYCZ}WZ>E*0 zrFSdA+cqEW#TZ5<_?vvjyEikz3V75)lP+NYclWk@nd!Jdq?FYXT#E$E!}1%^0v<}f zACpe<#eNY2cdCC&FyHKe#XaB9`ZU)^TIZEcIe`9q%EZ>oE2rizS-24QpN5+$4 z4e2#=YK9=MF}NHh=&@sJt<`R%-E`KL|jGVxqc4Hukwb3u4fzvHSE~7;|%wfqeaB z-^L%&@!La|v}SWepZxRn-@mzHOsG6`jPR@dTg5LvI%p7H8kJgBsKhY)R7({wyb}o) zWRcpc0Bpeacb5%8mL$jdJ5Xd#pNfy2*8IR_o2o&0^gSXIJVe(b8~Eov;B+IN0G!S3A>HzyW&|PuqAWsxU;LCF>gl?9GQTQI zDfSmR%ZH;9zOo*t);Tga6?$BZjI!WpJ!=%=ru2PrOWAn-iLd2=ElcQBlA0P(5LNg# zq78X?fh==3HI8*>75tDErJ>0MdB0jHFoV&{v<8g3Ld3K}3=d#>a29(^_w;2eBLnTo z@tBHv3Nc@jj#9ikRr~qXdH=w^1K!?e9D-W%uQzGsvdUtKn52~r8xbKY#HP(c;>^~2 zEz4FH(Ajg(iX%GrqI4%e>+5ao>`$}${iiCA%p6NY$ThEO|0l>DlMqxi<41J+vahi3 zGfR^7faHTYe5Zqkrax3O@q~-#<5nj%J=#!U)HzufYLr*EfHWFo#^$K7Hi_#ON7Xtk z$?SG_4$bf(0lDwiG_T>lA>K2JQDWW6Zx4c|r$D#a4C4ews5K>IhSov+0}hW8aHQ)- z0Q@IhU$-IQX26zBnflfXf-X+EKY_kYwj!PeerR3M84=WuUk|(CBjcH&=@Qe|WEDMP z+pMVuEHI&&7HiSmEr=mA9_lji57Y)kO7@I?V~Y!96?}k99dxT_zAMc3y9{ZZ9r=m4 zA-6U)8Is&4aqW&5->4I;bzW<+iJ<8&7IFB8FO2w%FT4nN?UgzT~&=}n2 zmF@SBg`=9YP*3?ijHArbf7V-4-Qk<*e(`Xa!I`gV!ngVoX%HBc(a|G>T?i@2q>(V70kJ_1m-NX@6h^sSfe_6Nc&G;$+JJJurieu&F< z`dvtQ)bm#4AIa`O@{hb#_eG^~MMC0JYhVpJ)ul-g^M_z?0;xxxwYwar#5 zN#O(%47P(LIVUZ^ZYp+Vk!06jl5(Do^{&ADM&w2@--h?XA?hZ_8m3QaMy)ug%~nxc z5fF!hUwoc+N?Kq$z()k9pS`^FH#S^-_BYlQd>38_uysyFgrK#NMd~w9eBU!lgm8Gr?Vs>U z<+)wjv*+c^hRl1=nu!vV;&V?d)~v_hs&_7+t0=Bw-5o8j zxsZv`rysLAl7DTzjmBc=b|QesN$o_C&O?*$jb~0U#{Q+-M7vP?t$P>Zz+zuGFAp`O z1N6|Vsi@Bf3_)t}`1irjVx+61$DVV}lnvZ^KHQ<7hJxK&H1Ed_W+;}?IdWabm)T)~&;e5ibLMD+wk-6zW4B$7xB zQ8!T290t2BlnbW+c;R8#8p`0lJ6HREi1lPBGanzyPJw&OGy-%MuB|Msx+HM%;sX%N z;U-P*!3qH9OKXTF%l5Vb;z)uL+6(j%Np&nl&R8^43|&{P@X3gbGt9ITbG6)P2V@8s7Izx?Sm-CE`G>EN~VExzn(b>_}aYO_e`>B)WW3n42ZDWk*7@6%d3@DcJP^n?rRk)`f46wtmd6$_mrL@JP_0OaaH-ADYm7Wr#`3G@ZbD z{}Y;LS(E0gyc*V5e!QVXM~gGig9fikwUEBTbFmBF7!P5`E%?^o#tmn>-=86YMLXP& znIfHNomd@36JROnWMR~!$M$*bR+a5nJ&hCGT4tXH#*=69|IuI+wRTUBH= z0kkYI<>^0ofM?`pHwI=HD9~RrT{GA;2s?Bb4`BCYheAC8WuZjHTQ3JN;S2(4-#2u9 zlZLmjL(cW=L*MHJB`GtT(1RN-XdF9R4?a;WUaxE(^tw!@x!`_}iOFh3uxQDNu8Ske z2Ug972{2Y`#|i2ry+%;B2|*>BRuBuNB{<%nvK8nUt56JOjlvW+>`7{)4V0V#&o#lLGPa$n5 z|58^!op-|g_QMlItNVRq=+xJ`!|2eU@nLjAe)RIv%Ggx@DT!^t0G%%>t4P;YVVv>nX={(_XS zb}@&&kXnAAHp3m_p38GdtSt*Mlt&9Ue5+|R%oYN^<&y#O$RvTL%eB$GGE&nXURCL+ z9mhvWH2=p9M^_4(nBNO6@l@I7M`rfCBi00yuSoY)kWVY0DFQ+2wkRd3m=1<=QkE?@GV54Fx;`|t+=Kz|t#Lh_ zttrifJImxoE#5qypn2Qt_SeG z>ms^;*lVk$LIi@{G6spLv^0VB55HlkkkE>CDw?)h0yu#+kIztAU?n%_oV1+Bi#-by zDNm}8yT~=U?dhn>3GG;?y^e5~Yi@{-=;R()E7mlkk7wTh#-(O z*|sno(`z7xpv#>Ni|=xqqq0eO|MqMh!{x>#iNGgGs6oPgnqb5lAYniTkAJ!CG)Ri;F^* zfy3h=HHg_s{8-ou`|lF6YgkQ?!dvG@m3~NZ$~vmw>KFGhamRW@wS_m`cLM4&^QgU_ z_$C>Ytpbi!TcG%5X9{arPG%nS zY>GB<>M0a56FCl04Kb^DH}4djVNC{fkQ)}fSJ)i-<#02Fsw7Sw=`D{_bOQ=ngjuAw z{uN9Ye8Z5L@n9yZ;rknF$z-_FXV{ss)T$mR<;@IbRZgh^gT-0Fe7-5&%{Tr!mU51e zbWG{6;@-Q`(BGZ@=XEC@70eY`@8c(LonL*Zz)-4+R8@Y8hcmWoYip<8k|IB*&Js)~ zoYn{`E*5KjiZ#0Y+T!Z${i+C%r(y zz66?x)HQHOb$T=v8%ZemdI5&{t!!A8FtK#R5YlUz&bZ{A)NI@O+g;$?1#v)z#|}^V zhjwCDJU^ftcUrzq9b>{4=+pbJlk}RrjeL$>X^U7PQ~$&L2}yit+QcT6f2P5U@-CmB zpVAkuIj1ITd6M|3k8$LrMoBnPe!KRd7~i_~OpO2~W6GDxn{GJ1-l~DlGq1;RUvPg9 zQkz$0?RY07t`CRE9LmPlhg6w1A9%0q2Lms6fiY^`dctNZFyRD9m=ye^CTUd`8-L3= zeVCc`4o1(Ye+HV1iz2Fjjm@3~zlI%Rw@o!l_obR|V!E&X@&`KZsPr>TF$B`o)oEUM zbZ4zqtQ&KzebGfb>E5RMDnleF(%JGk;?bxZxSq`W-^x?V07@e-Tn)#D>mv4H$K>Qen(^mudzN~d+;!PZk8N1WV&C! z_8*14>t#s0DTX>bTF)&c_-h=)AN}0^_Ar&WZf8wOhZYS+^};;mh06ev?e#w3?o_ip zgaQ28g3qAr4#!pajQuZav4}LBIl2Hm!unly?16Ygc4_>F<0mH7ItcaXaSq6;_+`&?_ULFkq&6LxpaT>_ z_K&e+eh+N>y>7Swq1Ihj_#-y!dkjC%RbM_Y+tNAUDv?=bWd=29a;u^@=8IG@Q-{j8 z0MG);+=*PkJN3JAv=esrBLppi2ZzB+KtFdwa(=fx z;?@R8WE@(EZW+$kJriz&<`I&u?A0Kx3Xyn`CYcOghFjQKSI4eh~3`NNi2G;Efxsbq|x%RcQ4!; z-aKWy5qY;mxJnP{fw4x5q-j5STCO&}XM)?&gdD+Hea_DnfQlhPj(z}`?E~!XML6Zq z+nFFc`CPvq(>RpT{9jCbDEu}*yaukI2Y{(wy4Wu%i_oxEfxJ$)ayQHD_oBTmFLDxH z7XAMwsaHts0d+RN$h|ua6ZCl70N$(R&22t|utQO@|GCdwF0AlF49_sH z&5_)mU#+*F(WUjY*B6saTruse3+L%l3(@(I-5#=_bWwnq&$qGL*91@UpzB7>{F26T zM*>&+_^U64?uYhGj1@+!dnR7t`O!iJg1(p{pEn=p{@dhqn;+78dp}Utv$kE*{8)Fb zxt0Ti*&z?v8c~q!g}6}{!tYUKUM~0VN!z6e_M-bs29=6SuRJ5rA7hFTszUc&pjAba zB+KW+eAR`g_R*n8n7-X6l^ceR`tz^@R9Kra<7RLIS&OD$WAX>?cZr)epyQ$S>8F zh!DE9GF$%8qkyS=z_eQE8sVzHys|*M7`9ZZanJY4N?m|c4p%Bk`9EI?7te{UP|>DT z%vsHUv%O6F;k$bXZvr+Ya3AzAQ<$y)oh|=7HGFfs`P`Y_7(6)64H;F^+$JJB)BdS< z1GNm`mNNK%UO`?!FjfXpOPX}PZ5v8uZ z}|qr&8pPxw{{W&fqH z`?Wb#B)=>!PjPHht5@(mWt|-cd##E_iB35{+^QOA|MwWJ;e3$ulnD3gJ+9Rihb&g3 zchrs1nCcj}=WZ@_Oz8N1t|PhKti=hkNG{gULh2EVy?SvrcMgvef4qT zjP@>IT*``l8!Vj$Vyk2N5f|z2UQj9g`V{9M2%>1sAUf;!C8WeQ4trh9`8G(0E@t>H zbS*6aUUD-~1Z9Q(Kf2B`AgZoy+Xw>Eq0%WLB_Z7%5&{C!DZJQ>ed}K0&c&C+I@Ykaa_U zb`6xAa5N!#`|ywp#Qbje@S6&sU%IKptIn4)Qjk1D?sV$&slB0(=4R({>Y~`Xg|!Bz zu;*=Zu+>#%iNHgs)^N>!?RMS*8ZFzn1nxt#4X{sq`AteDg?{xthA&Qq%=YW7oNj|V z%dh*SAsy7a-dAUe*NnzRfKCU#^N*ret&?%rTHmb`ZM2&KyO1}XwDbD+yLHk+1a&tF_PbO!X~Z~FroW;ji#*sTZCN9bU;Dt3EZ4#_EgZ-F)=6&kkNgkk26}rHHq;7%y}dLV z^EYyAgD*7==fxJnzx4K1>Ss`G&x+~n{KB;W4+7e69l1}gshfvsnTk^#lLPSc zI>rd_DCb9iO^N;98Bn9Zn59I=yi={PG{0We!~OF9>*#Wg89)3U`%>p8=gtpl0`J|z zp7^7IqeKwg@Gj%DDHaE^@fFSv8UB_;|6|$gYi`6KEp|r{_{$I_Qt}2{kH``81FCnJ>vE% z+=g@k!Sg1$AgXQ3AshC+gYGeo4}~Xyp1RXwQlXIRQm+6TaL@lWzVp+7AYGrFM4Y}~ zq)ffL0bH*1@ugm=9$WrDHtM9$Wq>_m>S>mYeG=0&xpnpZ@_; zBzu9F3NY??Jf_eEHBKkQrCJ<)|AUEkd%}J@XbtuvM@K2|yrE{;`6*x$=zWtV{y)j| z-&bp!#R*UrN?8xnsYyR~?)wEXlUoV1sZS|d1(07NTVHGo8{Yiuv;SUu;0+Laz`mdc z;4rg3Yd3DrZXFNcV?&4t8m4EXa6A5&G1%S*D6Z{woo?&+TsRR;tE^`B1NjyJ9=p2L z|BFf?Gm&me>obk>VhkTmfu}y5d(03-vf(7Y*I%Y7Z@CeH*A9pj>D~4R7wA+C9av?347R-7ijt}TlP0`@TakN z$T@M&{7SI*PKfz>*5l??5DzOD$qB~h@X^gon?JL>EzI!*uHuCyRAvP7c)hnLibtPj zg$(mOlZ6;Hs*u+?y~F^~=I6gY{_XF^$HXcYpnH^KpYV?NWCGeUpHwwChjEwBlz z54a9{h^L$(Iu@ja|JcW$ZXId*%vuzVsR9Y{frD&)$R)uiCXUBt7OAiOeoe|V!mYGI zUO2ixS)bg`9;t$RR(N(i%B>JEMpZ2TV3B^^zY+4_!{;H-_80A$NX~%t%T+C*c&46E z)9h&?KMn9g20Eez((UXG?hG93$1DqxTC?BA7+mdLN;nJVm zVL<9bdj4LJi}$4BN`2NY3}kA(DPp&6k}vvYQZ$6zQn=t8qT}E2LT)w(JX_h~G2Acu zUnxLfWDl|_`XXmo$sSimwi;q+Qv0`cyn8?xNjZ%rTmSXxzTB`=wIl=Eu4>ibRHOEV zI>{19z6T%@^^HSuG`Q9w1AQ$`@L>E|-swJ{8Zw}JZk^coFSysw{f)--erixeisaeA zRdmTJefk5gkLJM_LMh9u95dSqp|_Z30kl~Lr%vT9eju#kukeBTRh%wBQ_62gh7krs zm4ca1f8h#46=B7gPNap;s#?=n2TiTy3dKo<8umhtCp1z%pv z#BZSLr|deTIwnJ1?2#PA%>&HZGu?sqC_(A*+ZE{>U#34+&hfgYlGraA|C&L zo7;T+@ecWm2S^5yZN6_WV4jS>L4*#4Q!drYB>puOZXKN}#1=P7ZZ~=ky3P4Op7i>` z+?(HJDxc}ZzsQicOK3-ekXiO@Is9wnvc*4h;MYW<796?Liu@Gt53nquuYHX^r}w)q zhreFh{#V5m>WIj%8k;4!T##C0_lQeYw44;zOtb7<6GDKNCkdV$+kUH9|I_Y&>!=Sq z5#5}o#_XwF8o6D(Nj7Ge;stZmOrQQhtW0SsQM}EvKvJSC#k&Y=F~2iO7Npmgwq02%o|2!|ow=wb~^js$v_?@NYYa8akuUk)&_vJc6W5!IWw%cKX!6p3 z5+(><_nsH$Fd3G8U`hB~D>D z+8bWmBT`X3JMc$1w4nwoT)yJCGl4<9i}NnC`0@Z&UiPYWOteJa)MC>*^5e6^4HK*% z$ncwGxu~LSKx9w|0P-;4>tY`xZCp*S!aA;s@Y!AY{7x`ed@f6#3#DsV;J2M$CPE-$eGB z7#xtvezEZ5wn3)L^MI`UvXooeggFg&Uqsf2SF+^K!E+2X9Hm=N$xk}&Y8`}5&y3mj z2j)3#J=%3pL5uDIJvs(4bXP1=IaPoVIG=*n%@S zg}MV_U=#w`urA8oKj~Uc1LuAT9R|LV)Wb!ytJW}0Pc)$ukmX|=XEGM#VyG!54t z=ItXq-aRc8Ah(LRfjwKhWAq4O^0`|6q6a};<#oy7~8Y+7sW`qVnJ?n($AzE1)t|4+(%E-{PrWolnP zmySD);t@gORZ$0K75;I07dgWL3q@GHdzJsHhxe)v(DBB#PDlqSFnVNWbu|c#?_7TH zDE$_TLnZV0FZtgdqTZ*O6#8qyxsc0Hj67PwyQM~VWzZ7|&j#!>N{Mp!=9i5CPS}8z9 zlI<$$-mx$Aqi&_($dSuSN@P6!M{{Y{#T(HOG%QSn(GRYP;ft=wfrO6?eIK!|eWfJ?u z_Gn)SC8`GI*2Y)Bn`JrjxBU?-bYpfDCdg%}BKBK<`pON3M!^^bO)MMjhqi5`3E`6; z=z*FrNs0aC*^fJN({od)MKf7Xq8B-5^;|5<8%ypJV?z}K-j^QUfw5?eZ`a95Uws=5 z{a(YLY?mQ&^q=9HM)K`=2#B5i>ybD=&665k9WVwF1i37qKv<}!FFO~+sK>YJe<1`{ zVJ${VUOoV2BlfAAj*fbu@*qEa8@St&|g@g!`?tAJPCW50Lqxl&`DGi@-4J}zLWLQ9Qi zdIaZg4@(DuwOEOAJlQvNkL!Wd^g9~Ju_Z)fPn3e#Co=501)>~MB-^V{D(77rXae87 z;EAbtDvBf?x>PZaUZ#;a#)7Q4s1T;f6O;H`b{1$1~tTm9ywP06{RM2P&SQ zG!}OUfc1Rr$mr)W2Hq9Z%-eBWNRbueCbq9B{OLd(rhBIHBv4n@t$EV#k>Lzh+lZon z3lwRVd5xHxom;vI1NZU{n-ClhE2S#PH0!y1P-~IO?l+co&J)Z62ePR>rL8H)wI<3B zSB`gh^bE0dkAd;~Y*X zbG1J|vZIj=Rsdpc!IbZ7>!N$aXKAsaJFw7_1mP&wy@PP8#|8gLGRk{{M~1xKNA+T3 z+e?sCy&xzvNWNd=&yMyXL`mZX46wdTL=ool7#~XHWEIpxVBSih39jXGZx}baRxNRc zqb<|>2$p?Kejp(F87YnQwc;MqMZo|_+#h02UZx}e><~qAeHmmK82n?D$+aMzG0r`# z$3d`zJdJW0o0?t|RW*wsEm4{lNKj#f=X?DXD4fd!tz?LzhQ+qT2TQT&qsrjt6`wL$ zVZ2lcv?RL9gcGLz{gyDne|+-4x6Wr1XU(cI(%_Veuf$OZ7U8-+6c3!r!zWe z@LR#lc!Ic;*6uuH*fsfP!l8Rx8tfX63&mC+ zZA{B~`y^^F$PRgFmlOl**qB%x|LQo_w_vOkhtik2JFm)<3Qlq5?P4uy?R13isziqw zzVJQ7uxTP^qz9?@^bEgKJ6z$^mK&>116lwaK(BdtGbEPVjd}Wq`Foh_>#5UzOmFaN zUp*~y+elxCWs9Cw{;1HX^_@u$k>4^kV^@hBKcg9vmg&n!xPDkXe8la~R=x4w^B2F% zwdAoC6YQlFe$$oX+a5f6<{DKcK}SDr zt(ip;k3^4l6s6#MRAO38uL9Culb`foS7Rai=TLl3%JX?H57#B zFGF6efq`)7{`N%<*LA~bC0%r=3Q>tLw?mddl;1~*NQ~F0dYtqNo|XE47=0O=crf4i zu?`#FThkA=jkP&v`*dYl^jpbjX^-u>PnNiOpWpbwoC{vDiB%$bNHuj`k z&dv&qJ98oKQ&$H=-sW*Jf)&MJ1ZnBrjGL0amm@AH|3@?un)>F}X};zK?O0w@?WISBOCZE~Ygf|?u-{Gns8wbl$P5>4S#S+HKYT|m> z@u*v^E(*ihx`tk`8l>`go9E;~i>C#F_e@Noyv zFV|{a@-(kL44^yqGYq>tD*@0@0C(ee`U~*t@C{#^1a?*Bx&oV}@ehoj zPlc5p>r!3onwDe{Y`OSkyT{kBxEZ!h0Fn+|yUl0Lg}YHoj(w%dFF6a>g2 z1p!DoaNRX1;eeOv9SKQ-Ek@R4mLXAmiiJZxJ^Ryb3*^GpJlgqu{};nP2`wiw(BjkJsrC5 zuoQN&!RgX*fC}+nVp3?V+7;-mLp8X9Kj1^zCbyp988*wRliB9Gf}!>uFIiX&zRE+A z7_N5E_xldVjf5xPt&WST(=D|GWgHi-pSNbTX(;j8Ocm8R8EZJC3T+Bayq>M&P@=_f zic!R=yd2W`)4z4x0u#vUmw&YE0CWCmHo2(15M?lchYKcG3JZcFp@7pC<5kEJ$Q4EGErGOK4FRJzJi<$`*Gn-as<{L zW)}N9Hy0OFHV<9qR)7^#2n8E`8<5)Ej{4<9^?4SGP^5&k)8kY$GWv>+z_{s^I^BI$ zlyH&zO$6yW&0cN_h!VS7$GnO$HRJL0Ma@Y8FW_~E4zo46m>oUdJ;DaAFXm-QHa?iD zRj!_QdTP2uzbqz{S|{0rrb33RwMYpUm$irc+j`TD&{-7FHU|5O>ZJA(P)4@wJhAPb zdwCFI)2J`#l0>b4B0yd)Zl&e3a!4w)=5ABSgat@o3i*K+PMp}@NAg5@i#n4z5C|CQ z(xIRtFjwBr)jsF+4pRNlf^_G^eaNBANPMMrjz32nsK$z&3g3}K@luKrsf2PyX2z42 z2nsLqRkIFEaw2LxS{}P&_Zh(-WjO z8jp}GkM6CCs~tdhym&8^H!%(WcNNF|o=nD&28^7D%v9G2IX|URcWRNnJ+XwS!Lmxz zN6q-Agsq(G7w#)E+yYHi2dEi&deV1AGavZw_ft}u-s$0urG;e=vsM9+gIK*`B`dcd zFKP9!D48v~`cSb$#d|i3wgO$U%vE$S?J66kI`ZvUT+OF%Lu4@RTc29&rhFc=RMl+HEWf9Bxh;b{y%YlOX<=5FHAmm`Zss0fRqs_}uHA)&00=3P2n~8z zK+C+aR%(N*3Hj`BoG8H+WjWh$T9svT|EsTa8}}Yi%BF%KrR<9IY{q(*NBE;OBg#9+ zqn6ZIB#5YHiB%s6{R|mK8aqnI5%BL;xME|OOhZfBx#G-TzPXch{{Blk28|k zbO0G+UjK(T@#}9G_8yF>?hT`_76ONAB8dvyq0v1e4`u_1u6z65uC6%czZYgCuTWDa z3{BPGUV{0a>RbbaP=C^}y>aneefs)eOA*EJd~CIKZVB~Hj`J^c@gN?*eM-@iJ|MIV zqS=2F_4$Nl&1vn^M^kkrhj^}vfAX>6i``83_1oLnwI{dXF55Z;m{)BQ05rJY%sZKVlVEPtp-ZK&@ojE9f*d4R&$n)Fz()r_=^D`J0WZu8v5K z?#~t}of(;I=dsC2%=__54PE7K-k;6yk?5A6_vF?zpk5Dlhx=fQNlq zJ_(x{@?^UX|0^GHLpczcK`J-xj(v&HPElyv{cT!hRXT~k53dFaT*FD}r?<++W@}2d z@8hD0Yw(a{FL=ljBPJ3dzh^vsufoX2!VUfn7C{KXttZ5%JCb%k7sO^ge!!2I@OfIb!m_L z8@&FfZKyYn(;-EqyU33oE0Q)lqVAd7HQf#S)l^@qZEn3T005S4GLO-_O?N8~o;l?zKHfev%CS>Q7Bj*bg)`3} z7HB*nd>*^=*_WJf%GuW@BdKEU;^M9m?vFaWapEr+5@B^W}c z+q10eTh|Xz0gtgFJwU?nbN}ECZdR6h_vn4=Jhg=s$_=pIi5tVCTj>GrG8fBP=s2k*P5 zu8NEI2hy1@$2+@c@S^rYD*&AwULjtHA(W_I*%J}5mwHLrd4h{gsdl`DJc z5QZsK8gMpvFg9%|;4m&yMZ;R_^0;cIY8ue>>_zmK#;Q<%jM4lgTd509Sa^YSLzC0# z;w*7_;o7b4vZ&~rnSEfpa2H}?#x|W1mx#fNChy`>VuEmvX8OF8eVs?BS*>%Q)HP=BzkFd6 zkx+b)*3#;n9_;SJ*i3jGbb)%ZT_}P#Eni7$i*j7xGrdjs(@%MkGu`@Dv9?hGD?+H> zEHkfYy)3jTw^tXmu-)nN8FWk?%L86`YoI+x*IpG0^^q2+9&LZDEjI^7_V3|g74l`* zyAh)ZQtWeNe*z9LsIg>j$In#q^hX*tW2YwnIy z20^I69gTZ=A>3d44||%QhRkf6)sI8%{BW~iIewEinLI6TWIaxV4}=$nH}uV1(= zbK(Nm739PfWDFx!ynlMfwxf9qWW6tP-nSiaP_vwS3S_z-+1#S zwZ4Au6MA>m1)4PB1)ufIH^dVT3=E}>fY8{OQJfV+h#Z|FxZ)>4ofdz`xCwRx4spmL z?7QR6k;{Whhlk;%?|^f`UhW*Ar^@K&wn)FxduF>2sJ!=ToXuV1oIG}|2uZDFS>5hu zvhyUUtN;|<|6w}84%(ye`V57N9m4zD7Y%7**4kn4`T%S{>!is9h(AC$kWaWf@$ z7ld-8y!Gd%swN1;{i2ysmo!t2HO>TO?>A;Skn;fn%6Bkj18f`Jp>`>Kh$kxA4{I&R z<>bzsX;opxEs!VG43CwT$5$T+MKpBVo`PI{Q3U{vA z9t%hZU~qe6PHImTP3ru*{!_`HvP>pI+TfoV^;*C(HYd+P!*KTUy|t&8FMRui-m|#g zU@N26bMCqMUy*Qu#b$M8uS_G|{UJ~aI6e)JCS1G<>jytE@rQ(S1msCAajvF6AZj;L z@1}_WHe=&$6m1q;$-#W~78--^Nf2Yayy?~M zUc$ID{F6!4a=mT?f1*`b=eYT!qUclYz(-sXSjXm>HyEukbc#BSQc0lD8S4FwqDR4&C36FBd6%3}v@Ijnn zD7Ai)P{jQ)hIANgx6c&6duhU+VP~qdfgZoxGn?zttK);$4b!oXm+sFjT z5ddcv`nvvBP>rSJVzDy1m+i9YMs4GC0K38c&*Y5D`5t*;1ZDlZ8wd_&hd0UhNL^ce zC3kK-AGP51>$vJ?=#oJa^Cutb%nL5SSjm%~`HO=>Mw536APt7SuiWFgF(!#@JvW9X z*?&3k{Z8=EHET&rh17rRB>om96F{I>Rx3&7kh#jEo=sVdztM|5;KO0R?{HP8{Pdcn z*=kdjwi7k!ZhqUhK9}%_Ev8TGh+hR>A0#1KZI}3VRX62tP}?nxhc1DXhL!JQSVmRt z;Q#IKQ?JsmU2N2Npiuw=rya{NlhQ0Ga@B$-r^lui zwWw3EvtDhC?VA?8p0orf$2TXG+gA@v-T0T5B)8YlP^9XJ5d&pxS9RCyz94jCezm-d zY!Q5Fhl5WVygu+$+hU|TIRi#<`H7N6Y`qLCVX0dHNzv)Vo){0EH-KK=pg1{k8VqWj z0RWW&kDSZugXn1Nf`@|I>64xg7|ZR=KeL1E(?@ct4{P=%%T+K3S%0^2D+rVpZ2Z@pkMR zxJ+>T;sXpv`T&9-KlN^nFrz&@r^EnZGR6Y|)s@*B1H@8@vg09Z*L%_BmhWqc`L&JT z*ih6^wv~?s+8ZyPd@6e%*48k>E|T4kSa0}tEL>?tKIs)4_%M?Ke^Q7O-TENJY8SD6O#rWpTwVRdh`i*gdNOFNMS>w?)o*92UpHK`aG(l5g#T#4nJLli;(p?vn1n& znTRbN2^FS`v*&V(gC-fF79ZFM2EL6banoPMSB+5hmX&I`n_0jo9}`{|j@`{6*Fo4E6D41qAz|K$0HaK^P#bg}HY}sc~$WjH2CIu*#LpHe)%7l1W#0 z#KkBP5Q4BviKuTVoVs#UgLTy}XRn!@DYAZ|{nEqpS0ga67=Zz%bgf@aUp<#gGx6+f zv=3}(&*n&nw;Q=7-d=zh`o1b>6jIdBI_@xB5~S|GvG-gK@?(A)69fd7%-CXR>+@qV zh{4C@N5^v1`QB8zr9oNh#e&+eTxkbQ(8#9G;EKV+y$|nx$FO!zJ3ziQ@k^lfU7^*! z&8X>XoJ9R45kX%;qy;jSw@ff-n%rU_$IyBjCJ_+}j|}`=)87&u1p)dcSEIc`v*21= zT=y`rlS0zmR->?_KPxsX;d~KXF&D{|=tyHAkAg?debOeqGfQ-uKDZj#DO>L+5 zKhX6*YLbN_w`A!%(leqxKCKA`AX^N zLOyGO*g5QZNjK<(!`8W9Lx=GLc-1a!T3eF&T?-~w^+j*EfSdFB3l|2R6>stfHMa7xITUg zvAz{&Zc_`s4nhjBYfIS6WVUyCxZjupa|fzFdhik`S%^f^Qvgbm_WsU^gi)UcSOuX9 zN?hc0lCjoK{#8pGA^gE_J9#yRX2sGJhtx5NYGBeb?4B?-8#s^U;v4)R%TWFRn5zuicJe4o( z-F1?awOa5tm|HeB#6>BdYywc7AmQ0Tf6eI`T> z@DG1UyEL|y_PgFA&j`JFa}u9D$Fj60Td-W#jrYRRG7)_7Q@O-WC|{aX76@%t#1Ocot|XL{>SS zn3`b={9F$o> z4u+q3ACtRScec~o;KGBhD$H_8={9Wu%q;%TG#B_u$e3Qj__z_nR4*Z4&+BqWhoXBg z0vP(CGL5sI4yW~sCvL~QyEuKPKf{9YhY78=AQqY}j@A*`9_B({nuv7LHPa0j8pf*5^0s@->nmpBB|GlgqG| zj74^8-2#C^qq;tJqT6x*uTsn{XAaRQ`31v{^|yXZzMe_5A<;d@lWa|Fhy*P}x=}^( zI@Om;bRz$xG)1W?+W9WY@$=1(C%b+e>pfM0XU{W$D+BVLxGyVDoWUD7z{ic64F+yk zkC@}u0Dp;e8ngR*ty(aE04*S3&6!9tmc$eW1D5^#0uIoUiP?G{6YCbPfuEJl#nY%n zkW~8SyVT^gE-kYm61R2dThlyV#G0e)L@Jcv<&6>0zCK7qG;{Pb43L*n4CsFFg6ELc z6mXTQhqvp-=Buml*UdXZyd7j`*doy$zZu%?@nvjMzpU>12PkSA8IHXb!}@xQMB-zx zVPLUh6L6E|i;rmbDG&R5-O>DH3~pM%p~l~AmISoas5eJ1OjGirNXF;{5_Gr;HFSm5 z8<+xCP(84R@g((FsJ#N?zQGB~L4)9op~J1O=-+#Ko`Wf7!Ue6w1lb*pdyCXoHi!wG z&k$|r6`(NXnNmaO&>FO`4=4%3nT3tT)|M}aQ{2j^^{{}!UY6HUZh+Uu8-0>ey-LAX zq~gvDEcou79Y3=8(xl^0l#%MtB1`{z$?7DXTft-^U~eAFNyVX8I~d|_+ROi}Um3@x z&pVA$+q4QZH$#z4v%Fi!IA%O|vP1~=s*`jUv$D78J@0p504ApvwkDUq2T3E)TlYZ@ zg#zDd^)hwSFao5iMV%e8F!t-uL{gc0ggZL^{bzD}*T#5FAFxF=lal{QV#^zWg4~MlsqPV9;*eq28C<`=u7&Wq&;HQ2Ej>?wWIiHLk~E zFUSMEI)@-vC)PQ^M9@J(9#$K`!DM}E&Poc`DRhNcG$dntSU3p_qhtw@hmdQrsB2h} z1R}A;ie7OZ8S_X_x@Bypot+!P3LH*`#v`93k~N|Q27wLxt<3PpXHwke{a)%Efm|lo zZz?2yC5C=tp3V@Nu6Rc*$Z;#zifb%m0FVliw%d;xKx>l2xuwtF7rOPR*W8&)rKKmS zS@e_dSkyOEYw_e#MAdsk(qQU+I&@%6kC_XcL6`-=T-O% zOZm)otzEbmkDx`?M(CFoqgEFh#@pl-37a!;&KKY*GdVzVQvyvb+lA2YYv{_xY|m&v zw)MMn!|DMavtH8$BFTdKTwgs`z4Z&)ThF3=n`|Ato=DUd3B3w+pE z5FEuNjztJqH5$fcnO@_5fADue;)LBtuU<&5w5?kelvD#;Dqo_x-{R|ph59j#gc95T z?oqMDd?9%y>F`hsv1RL2>GP?M+y}J7RS0BlL%arwGh%r`@uU=h!~nh@ru)q$&CLnJ zSf!tCXn$^tvX_FHxxblR?)_WMRT8GiZup%`a$FU{(|E6Iz9QGT0OfIHsd%y?rDjhU~?v5n5q2n+qWvA+PghB#fxxI zVJ05KspU7*1yXX~%%pdcx+f>~0W=Fcv&ya(==Q0){IyS>9{^?xz)S!l4MQ)V(kt2`TZStH z`;99$xgU^K;URn^(AQFp2_rw*JgJN&QdAsU31p^MSs}$YZuY5VJ;-;$tknu~>?x4s zm7*)2VL|@y{tw%`S|aws3brfGWS2Sym6`!Rh=8sN^58igB|@TM4^O_H4_6*v&*w!Q zruJTL0{jgCgzX*;Y(N7Lobcu`OkC`vL_JRQH_16j#&-pbmIqB_P0!VDvf(@$r(n{q?0>Yr;l`}y?IKxt*X$Vg?I80GR3#L`hS(O#67HF z5z#ZJX-#?zq?1U>Meys#JSHz>fYVbmTg)sU?YTKzSeam(j^CTqnS@&g@&8a6O6l{hmN zBkf(0r%Tw2%wV}LXMtZU%;vy<2{*+A;_0!M=^JnD1MF6C`?L;Z*&=x>IAiHvSkg`= z?2Y_2EfPM|52t~Z2Ukn^0X}F}H_OmqRq$IDR67M9}5icteKnB;Q< zF&cC4Q|peXup{7}4-vY(XQ}_2Z6q`yRZbjSGdRX#G-3brvr?$s!y{2aotMk9^l5OA zOJXKDpZ_~DUK1r!j>z-aoW_(l6%RYWyS)PUj5Msm?;nqiCe*6|)~m&$cN?uU6tLj? zVN=T>=w?l@Y2~=FU9h@mjK9_DoDixc_}^^pO_Ro_QL=(E*cI=d$MUo9OE%rA1+v@h zo~3#u`F1gLa?hgF3QbSmhxiMas(I7S9^az1X4cRI2mvvjMc|Do9M04#OsVW1cd85; z`=BT7l}`WeOWgW^)-Dq{?<-#h6UiYg64m*g9-b)@VoDm!C+6gL-A~=AuX!x&cgqRW z^$vJ#XA&npW26xPNZOO8*$tH|pA;p4@3pzIITP7!FAEjNI%&hU%^N?h{s^P>Fg+?F)j2OeBOL?r2Wu#Q&uadM>KTD-#QoJP;@rB+Hip+(UQcPF($wNsjU8| z%Y?b@&!2H>{Hfs55sKxgJ5FT2t6An85YphB1|PY*E0Q#arjnLOqzce}g=N$zv{++U zFBF=|absS{awm1=nOuK2%|QLLt%6ujMI=hWQ>QsDY%Rxd0RR&Mt^>~%T;lThow&;r zQqY9R<`2aDDgvoHrTNd@`_vtP-T?@3!{b5I$hq^nd+Q5t^)dWwWDT6hd#2)YHsS;L z=I-d)8fiKF(JC_gaNVb8Zt-lk(J*qbT=TY7Sy^W9D zENKl6PY%NB*;9P=t!Ykfnv@dv6cJzrF~Xz}*{{5N2d1oMQkt#e4PgJgmKSm5skGzz zj42@lXg9mJSwpeg;U<2rDfkS{O_?4MUcrY@9#vEPbj3>kiG3k@7X8WT-vd)Qe z=(*8s#>LpF#wJJ1L+94>j3R_~y(x=(JjaW(+WHQ16Worq-|d`yKi2LWEH9 z^g%fpPSV}4ABnRz1ihSxAZS7G5}Jw05l{WHxl%qvr_P(%=UVGS%ebi7!emoHe7rm(PCNry3m&0_B_3+G9{1b*+$JY%h z&GJSSrp2(UVzngGj~akqGD4l$Vg{(V9};fn7h6;u_Z}6Ec;X!9x zFiyceKwO}7wD0?N2g6s^Lp3+SPY&8026VKQW?qH5Q-qKvihfo6WM+i66w!guQk7Ou zhAV9AEC`dq|4S;*`OpPjr%vY{$HB@MS6tQ8i7%vs$_}Fe4O*X0YW5;R)q`HWP2cA#b+iG zqKZ%TcRz^xZ~eKd&$U-1IQczG?g1`w2YkAnIG_15OUKo|@0tKg(at~4Ld#U&K7tiR zE+YD+Enwz#SK1?_SZ@r+IZe8B8odar(9oRTYtNdU-nTWPP&X;epeh~Rg>#B5Uio3(&W6%De4%AS4hj1Bqsr`aozQ-KBkKfOSOANRVR-0a+>-MP*j zB@kl`N;cFL^fOljQ>{HB7vY-iFC0t8NXchkQRVyrX%TLw)2J;^b^@EP?!HI-`!|dMkoWAEL{;by@3!F9N(;8R;I%nk)@5TeQ^sjmJ=`tU?B)+eg z%=Eb+uD||i9nhOlXxX1C>%(F;pj+)#V^`ZEJC%2-^WL--Jsb<#eYldg(^1I*De`g2 zL5D~ep(6XU-Sz}}VXja1FVqXCdkMdvj!%5!P~M}~EwsMb(&_&K%tlLNh{mwBYMU6Dim*@u7`Y3Sh3tu}w1g0!YtMIFSD z{DHG)kno$3&hzs7UMU0k;J;)SZYghzFp~p#4F%b#XnNUIWR6|P(3Xc3pC}iM^{3En zF}+?(%8}!~)JaNJ`mm9<>;pYeRR3lnWAhlt9f4A_I`%cec^*I62sf?^?&nDok}5V} za|p)CMqPkDKXhjiR+YSfF+UIQc3k``CDlG~IG6HxaHVy$*asE}38fZoZNVE>bQ!~m zCuZY4^YoW_h`RHp-`$^UOskPz+po*^(ObmyxrVAbqjDksz;SlM-t{ABxf|||y*aFU z>a4Hlx(wmVl$R8Q6d-n~K0YI2?4x|yA+dZPO2 zhx}>y25L^bjrdSBS9BGUD4MslYZ1KGYy<;Yq;Cg>!PckiXEsF2v1iCQh7J4Tt2ZB3 z;+F2jyhE|VDUKzfbb#YwuPz%K5@2--{`}*SK*@e)O{^3zER2G9t8gqv5{u#+T9 zwl9Oy!rpRkF&U?|SzRzIW_l%Z$E<)l1G}t_@VY$g2wjO_-XS#|N0AC+G<6MGI5Fs$rmvNq9xOcFo|NBs`+={y*6pDw$Tp!lC`C~z~IaErP*vM%y_o#JZfiP zd!2NU=-qrpQ9`uO=@8F@L5dk_c4vE@P$4Q58isW_Jr*!3`(fJQ`>{)^{dY-;{2H40 zA$NZM?zRHkRBGS3RM$*Rrj9Asa*_J0L!@ixyb%?fyzo`LPkR4Y_WOw9#Ttz<&v_E#yZQ*uS=UiED?zu9Q(| z2uA4WLM^K5E%gX-LDi{AviTCd7V8#S6df4}im%PKlCBBLS!<4OGR-Q;YIn5dYO?#O z8g%T~=87AlCwR0nlC`XTM|#bu^U)3XwjKiw1F%vtw4pZa?{6YmuNFUY5POv>KV9 zvHq%q*Z@NbOh?b&5J}6*s4Y2=giNouc^Tq6NS|Ulv+C&7KFvmh#JRrzg_WIJTc&$Z zUIRnL%#4WTM6ykGP#*c~iq-Waf+?DQtC6Q{Sn5*;ZT&w;*LQiV3*L=vdl%@KGseqT ze~rJWYrN8cFQ3dlbkj`O=^blES2e-~rKyPqk4WjRlYht;j}J5LfZGpv-mB$rZO1T%stg~Hgf->Va zT~Fb256etXB955pJ5{q=#?eIKXF5#s&OTHYcX~4A0+0H*D=~0wF)`t>lm4KB>nsle zGYTCa%n8`0XqrE3XYre>X`6p+`P1QqKdW5tV;pY1{W#)Ds!NR#Sr4JK;g$t_hZJu@ zvJ{_+$_tn0Ai6J040P|ER}$!kMxMbx&kYH*EmL^7(N0urVm9RiZ0q;z*n zNDmAWlF|**CGfig_&m@1zTY4J&4;JKdcl z4szQO55;@RJ$r9R5K{D>IW1d9Pim?g75s)WIT!V7jJCJRPm^(321=3F-wwQv?u9Cs zg)t;BE!xX*P6izMueeJaV9zqpEm7;UFf>liFz1`Q+$U*b+sI*%uGD(C)}ZTA5-5k2%&2Mg|Gnzp`RQmilJT24WX9KGNmO z<&NCH_JEK5u&L+?eC#(E)f2$Ys11(0ru5~S&>_)iv=Dse21#g?9lq}9dCyoACON{Z z$ppbW;j~xZCzKyq*E5}~8MR?icvbGqcu5apA2KOAvDYy_lq&TI?J=OGTjC^V&9D9O zpdk0tmIN%vFcVlBQUhKG!ez^Pg{B|B>+B+}g%ifeFnd$5Q6g-*^5isOn3+WJ*+b`^ zP`G#6{FoBzB^XdQ8R_uOmqDkG?8?|XXnKFaTOy3F?usN)4B?0*mUP{*wbpw}=F>Fs zgiw3sv#Ym|TI($nHASxj<5U+dWRJosr2a1$iSozP>ua?Y#mCQL9&3P5mMYSXIk-<$ zrY?hR!OkyI%M6e3%=@og%V)-k6@P2#y`pkBfc1dasMmNX{mcky(sx>mZML{-hA z43V%<$7%61+dCINt#Fr+{VB_+yFHGWyvpgonrb-b7}jQNG|M3s(TfePnyVYC|{--7VLB$G_9vQ4@h&3C3cwNx@6TG zHf9*+E$jNkE@6q*GTbfNX1HMxJokoGGjbrt52s-6;Y-p8>H;l(_8!@2%VI)F`-SZc zKh8cMwBnHO=Iq}?<^+2wwCXxLtTXmZR!Ei~%zMK$e+|}ew3~KNQbI;jM2ciy7N-^p zI1%)C#dw~~-lZftH;){Xh0M8?uW!&8RMSJU(1%4sv&;CM+0odxZBaTW{4=lN`6-+jap_>=ookZlrfC*L z+Cyo7|01geacV=gzJ0~avPqL(MSx4Ar2izZjQD>d7E&SMi_uWQ*IyrgcAw>1SU4hj zL8VjljC9e^r>4!O5nr(FL`DkOn+*?Ork|H0mYb#{qZjFU_)>h+vy4h|??ECt*NJK7 zyw5n+H0lC}y<9)P39@g!(qC z?c<^`%tbxh&N`AF+UpU&el{ubv-izc^UGISesJdev*AjUa$TN0sh={z&Qz?;_+3dW z;}^H{BAQcuajE8RTy-Y&%y=Dmzx^`N6kWwj%l-dx4I1T{S&g!lPHQ7nQhE`+@rE|) zGvfSO>$aiExm`bnEMqoE?hcGcx#M9FqV&m&toCx}vH48aut43zjBk1TZ^a>^ z{a0s;2TrC=+Z9sy>#f~_CzebsIG!3CXj`KfS=(!l&06qCvrTT3*zwuyPm(iT7UB2e z6znR`ajf=gp$`>0A{isfSx=1rD!$(~s`C87cvENPNK5w5nws>PCwfus&4B}4jARX4 zug-p$s^AouBg8z*IJ7RzoIif&Iq!WMEF8R+*i`M&-fUS3WtjM)xuDXqK_W^U{^X4m zE{QQ49?R%<#z<@IT4R2@(qzmD6Dc361`C7 z@^Vy2*Z%m_(}kTpsw&5(N=ovhPlPk4>5QDJ=}!dn$Tg(k^U_^dzxT-3TC?o*wSj`) zs6>TauM33O@1}iDD%DPSGnrQ}M7@C*X@FX#P~)B)Tb0R(_a0(AdOs2CTq%k zmgc$Kx12BJ-2(l?{flOT=Wxbni+<2d4#Y3Dv!zHDfvH+L$6kflX4`d|@y66F{W$!& z01w)~gt7o^BojV3{g8;ft5Ow{Gt6RM9(Kx2iw-RH(cckV?q(9zdfZW;H;0Uh0F;Qq z$$r7nQkL+5d4%(q5w!zYVj8AN*CIVFakgY^Y(BC!X&%Kdv}jh`pliVswlk*wY4`nI z41^^h!>ur!5RTqebq>`Z-v@&R@Wf~}>PbKI@!rQUvBbCl^-67!J@aazg;&ilX;&-* z&HB9?;hSaLNckN6hJ>nKh^X>VUl znF+JVCM!{J_8;bFBnu=JH4qXHh8Q2AQ{qZ~yt|Gh^QBx3zJX9%4;6f+I+vLH|K)8y zhS_N$87q~_6EMc#-Qj(yi;fYuFk1Q*Fd!pck;bg)-BnKF1}CgqLt+}siT(*d z9eZY4*_3v}(7yw^mU4Y>Y|`f}WodDkJbU)gRRUo>COB;3t!8~w=G5$W%ysi@;H{Lx z8BV6LDJTXn9&K8jlH+`zGO+lQ!ecc~@=h}Qr!1e(WInCU2Hz{lBMcz$D91oe%w6LE zY4KBQn)!F_kSA_aqj82wm+7D}dt;n&hT+)}VOZGKsZa7f!>+k+Bqg(#{AwAS!0Xt3 zJ|yZ1IiY@Y45#MI^K)Is1sCyrF;|KBF4f@ULtn*+j}gV*$7{h!?rYPNw#aG4;Qxec z!<<%#MkC1NvP`-0B75eBnz;U#nt;N#3!^%Zc(<&hFE^?!3$x!;dHv4o0mw2Gfg12f z$F-!|i>^j@E#F*Dj*$ne%j7*G43)g_df)C&mk~V5@lJY8^&H<@5=l-f%R#bvN>7*^ zgM_&3ya=Ic_(^$a_EQ=~LisvEZ{K(_}F&Bwp9qnS(>zJ=1gShzZ6Ef8d$8XG6!84;>4HV7Z5k=i$f+k-lUsS#YH`nWtL{x)_n~3twd}~vD2xjXpF3R7F;_TuXu3R8nBOmS6`YLO?`Ey z%VMx`PFPdrr{?15{hxH@m1HXOCx-@$EzleDb89sThxnWh!PkSDnDjdk4;OarTWCA~ zh^esOr88bp8fRaUIq%}XGE#n3gSVD~jWoiY^5%Kw8e0Achhk9`*&nJ&9Pzq%597W9 z?C=NH3O}u)4jH%O6iw8pnH{Z1^zCxvDjaqinPN^tSh!3a|Hs|^Ws~qJ^NqNaUWnV2 zo@8w*IwUa;zYhoWp&uHa`Ji7WW8l$!(nRz8#PeT$Hgj3>2HJy zT}ZlTwA}@(2nLpKk#6VN65<3ZSTKtb+pl7*A07?$8Q}5oOCwP@wRNm>u!%$u*Sger zH)(;d-3c3yR;u9La~b~1IX>uDvX>&g?@rKWw5|%&RG}?9(|-8s&E=>`_A**9Sn!4k zuXAc-50qD4(mFo%^FKc=i!+n-Dm_>ILZ z#ZBIm%28VHrgh!v7z}tKRLF_hy{i5YI}Xbdy^QyeqcStt1$=ZLzOwF4lC>!!JH_`9J*{oFOazsRuhrs}{5eaW#67R~61bkid%kT!!7<(t-zVY1GlMWR~G>;#H)ZtJ_it%}hKsT+Qyg zTQMVB5XKl+;cA_O_ALn+W?4b;EC0g6Qf$`;211A?4q1Y5c6&x24?Byo=9Hv|761$# z8<;ZO@QM<|AB_h8Z3dd7E9SKJH6GQNokTHtt-D$J7Fv#rBfHvWhF3; z1Ag$0JZ?50jE6J0RpgF)3C(CCBSqSP$cX548T-EAL3Yg5Z9gB$P|%aONb(Re`4CO| zh9baynoWyZ@|Y`E>2-~|q}t{EYx*i1fJX3UXo@o3qJ*35Bt!V9em}>)YC-BsyhUXg z?Opl(t7W>1hh1`7B-Lp(L!NuJFhsCx@g=nMA%MNpiJM7oR?6*(n8W6p9Ks^Lx1N8?dN7w>YrAk$-y(M+6)>?O|{t;{^=K>xwozryAQBa}&HWH4cB zZMk~|Rv3F!xa`=~E;K&Fxe!&pGIA!Iffd=~gR>0fP1$bViAk2d&rW(an0W4TiV6^x z;_yy{J5KWIeFMc3d$ezn5K=H}xpigQdWkYYk9u-!^ITlui=>B;nQ;GaCO5<(H|s@3 zW0@kfen?G{A3kIL8*fP$)?B_yZpoYd@j=Ij&sl9q$*b{_6-ORpsH~7*(`2mGZ?duE z^3licvi#KHrb5H3(+A0QTgN>j1w13H8h^7h5t|kD|IFCO;2&IuBJq1{{_o*{ z?Iz35eD1wkZrZL*Br8yu8M7ViI5m#|z=RC|6UlIxpqmTbtU%q@rkNSl@SHTST8nRc-C9^~D5C%4Iupeoi<6d3xK+NC*M%l7B4GGC!4%-J$ zMz{p;*JmL*a+1VK**(1l;d|ZYklLqJr&at#=LrGYANZw7BJI>p)$KniDSYmNiwkt@(%6zMNUq>odX@iW{R!K&xOJ7js zqdSv8UjAVzjF%FknYjDv@{`Z06qEe)c%#xy&@{bfNiViLgeI;0f7T*<2>UglFISHI z5w;DFXH7HvgyDcqR-cu2Ofz?WmBUzpf7T%4J z2zuS1g?Kmln~a+=@9v|7iyRZ3tWf^ky?<&;iijT)&-xkS;-7oMq7k~3Tx0VWFX9UO z58tGQ=FdWVq`@&XziQ!u(JtTou>D)R#u-)9E-3EnRsRS^=0bA3gBSXtNr6voH%JlD z{fKO$08mQ)F@>w4P*0P~pJh4vh40L87&X9t+3_|^JxCc+Yml?32$qnGA8*d*&HP4+ zLp>tim!3JHuN!AKFj@_gPVxQba-m+=G;4Xcf-=~4A)gKC())1k-{(w;}E|~4Z+f?*`IEfSYcx-qlqyyR`TwxGOW?2K9K^SNw zw;-0Y76nbeHuR@agHB*)sVp>uqTkNw$_rfTCVP8s{`3yIl+FP==69Ct@A_G%D{W)r z7T*vE3kEoT;A75nOwCg&*NGg(3=2bk1skL#gg&`ptCKQPOLAm{p%g!Q}KTgr@}3i9qfCzp^0XZQW=+Mzo!a>STVZTaXeb)!kD0p}#B zC0tuB^=G7{?K^t4SyZte^g1|8pkxIYke#P4ZYNvWIMDBq$;s*hJx=9(^% z$EbbfXbU(_!}GhJ3np*niVN(^9)wHTC2Cj@loIrNe*0y_$W|drujDYETCRCcnFybp zL{q%SJx^yvrtQZ!SX&v_j3o(EU38pfs7_5O3E$V+^hQVdvRUtm z?Qc{|WgKQ$+T$IsxP;5OC;Cz*j#6Y(m?+qtVdFBd`@XuF0m8-bvZ$83GU>znMi0!b zQOi3B`jU3&{VX>9|CI{hI*A_E+@ivr`=SjY_*@N=2g9zqEfN>#HG%;yQLqD2FyvlP zWtx-eA2g!A{awWzeq+vP=sIJRmFtK(ZOK*uPWJAHn8P0z%m6=W;hqD-E58R8PzuK! z6Vq9W*P=?Y?g@Oa0YGMEDS0Ge*{bZg+ErnE`UrngXh7Qfa_+uV6)=24yRkfm!5aw+MDR==u{L)`Bc~EC zATTo_>)+)D&M?`e%()4+}VXq(NFmtdEIXmwVB`NLiAO+`&8`Whhczl4+o-zN7yP!O5vSLD1R(v3tr$NlR7BOXN^*V~Eb0xQ*#8Y?!09WI zfUvkGUNQvE&BJ$EtuUT>^LnmLmthO?RqsoOkh&>wQIER!FEdXcR!_aKE+%e)%E+$V zXhX@ubVTuQ1h)d`e7R-ZBE43Mbm!C$E^cT%My2nFOD(lG#kTQLq;xN{Sz+G&gdGQa zUIdFVMtJYwueeF>s*^oqB0sW=*UWgB4jJT5%%Iw4zcOrwaf0Tae_JaX`&e|`eRD3F z;y=>UAi2J_%a>7~Q0o)>$wBcN;G>RUgQ{rRhFe_H%-YS=FPtTkNmB0E@M~PYKh9-? z$cgg(3t%b#r7wUli$uedA*Y_GGijhyG_$BT?8OE0!=oDhF53NaVlv`X0^*~wwS`s| zWx=gkj#Yslp`$6*>{oPwyPfqSQ#qwH$9g)O0mTAy$M*<_)y_Ua$?r-Dv@|!QgAmLL zQ>=KI?d8n&J>_gG?av>lYCehxG)rFm_?+QWOkBxZl2t4nl=F6MyT}lzFTqndDu@3N zneq=`E#OX8T6)qC4XMS48MAO6V@36so)t^CAk&gSZ@qokW{hzx-FeU60y$>i0H*&%FP$ztyI{C!PSnv ztpJ%QI&*T-`v}>Jc!x%Aj1WkZRp)T+z5NZoQq71g>QF6!qWObiC2i7Ifi7kD?%a+@ zc?TAM%M}*uNr^=i`>TP>KN0bp&p;*jQT~JiB0r8Lx~7nX4b;8r)KzfSFz3?*5vFl} z{WSc^B`AE!&VmU1*YoUVmZ}+4w%Vuj-i(C;7J?7n>X?QPM_7X)=PXL(8NqtDsZ4>q z^Df2#TqT+3o#Xn&ui2i5)51l}|GX&mdFKEG1ghsU;?LC*9#g|<3$N&W<*ZPv5=nkW z+6uvcY}9Cq_w7Cs{OsOo&f9?a!ZWaH@T---Gdg@QB=>nL!wBx^cID$NsmQ@!l7=1_ zxFSi6KhpAH!?IQQm^Ni0MdURqa>ed_8UhrO^Tnu?LeN4P2LiGKFf68SvG72^__3ux zhOJ2Ii|w5Anh4nfI73l;G4UgybsFm?!n<+*`(&}?be%NLVxZV_ZYjO0idWdneesp9 z!E!|483kp>*@;0vzgjv}0okGCA4f1lg;>&7#1?Augp@)48k#M64Si1?RvO8%YsZc1 z;VNkQ>y`I!Ud@f!(q~M=6UqZ}X#Fg<<;%ZBhzqbW7Dv*OzgB;Dwqx5qw6i?kE;8qN zIKEg~f>`|RMN4m2?lA}Lj~oB!fEu}wC-cd{i)S^~e!0~s4l z>zu2&BQ&Nk_urE=s9`{1)Sgt-+w8Ljkv|-UjpPNEfnv;+Hm;?I4)}#dT#Ub_zubq+ zU`12j(unu)Q$@Ieq`sZMnq8{#)Mb%uZ%%;|4xJn2a^(4!Z~)(2lr01}*1wA*G><&R zOst@B%`KU8ARohQ(N_L~dn`(@fnJIEyXarf^VQk>#l&)o_Vt_XqF@Eb*S#ZUfNnwc z;ob8BFqKeL_Wa8nwcXN-)(=3tnRyf}@(?g@_jeak&pe+z>j>VP{!&Z- z)O1^edH_|xxb227Y4LORY4eaf2SNF3PPrfn7*zQS%0fi8fOhdP-yFJiJ>$Zih@Rth zq{HdNe{ZX!U3ymHU)l^f)i3!~602!~@||j6n0x2!qbecUXD$;NI@d__eZf`)byp6=EDbH`rH=H~6fG8Id6w?^?@6x|%P-E(7WA5|WkK;Cem{iF6`jacU z2Db2&(joblHDuxb;hnuGeQ4gbW4&_Ir7-zrHGuWw4g}~POYXD&J6$?ZeUED1ViBQw zE_6Rz+>^@Jdm3q+le0WC)EqT1t{qr~g!SdplhcsK6ZhA3mJ;PRETn+(>8=Hnv3E6qBz3$&>Xh+?`j(}Eo~~_b69fw%ZP+T{r$v86V8#?+hGvoee&N1L zBZpNzW5W6jPI6M%zCQZ?;LhUs=tkW0LApHtz^}twHHs`{XJC&>kZA~0E~*IfTh<&r z8VeaWZY=a#sg2h;<`l47^}2Lhh%EHyRpMe1JTPA{^sDQP7G+IKLN zoBOF7p%FRe1}wwf;Lk>$Vbh_>+Jaq@*#m$by5NyB@S*85+KrxUQj!%6UoyJ7I8kzt z@2>k|F8yz2fDvV#j;}Lj}u+?5Vd_&pI1~{GP#gSeq}8 zb?`rv5$nRH5z0rK4~4-D6E4O{3@-yISnl?D(CCYt>4T<0^|Ke_ZmT&L~{ z;@EaAd#m~G&M2ua>oS7ARN|@)J8}xYXEh3fw-tQjfWFFn&=8|7O6pInqu}F+M;R7( zQbyfQ#qvbUx>rM>r>)GGcGL2oV#R3Yy49usjAGoc&Ny%BipvNzWyrnLRSC4^3}JoG z#uB`o8AnyDPipi+y6WBhf0Ln-py@W?wEQkfeI$jQvLfs7+y+!t>>n*;1O3>lvT!pp zgaR-E>K~D@e&2Vx%2|)bqb1-gb$xZI!AFMAc*P{U@j5FA*p6ap;3=SQE-=U{{R)iu zhvsD%)tX9h8|0C*nzmQ)!SKt*&k5<7dpJutZg3TL`JiytRjv7|RHcK(OX%IVK;8-x zOv;U1??jzB_R#dtK&z$3(ZYfc{7-K_@wTHpQ$#kJI!k4poHd!O5dxSec4=gIM$7_ z8-9*&HCBOFPG647~kI%n?BuR}^moEedeVG9SA}j#JE;qmPzl{&a7^SJLOcAs-QS!!Mm0aLhiSfAggH z$z-Xo-WLvcRQcDn8r%{zVCJ-CK>IY-gIGrNacXh`9s=EM4-amceBj{yET5ZC_JzYC z;ru|O!H%p1z;`aU>~CIHCrPz-Zk`LpjJozpM%5J_51X0XTm`AiRpfTc-yha~s>P~Q zD$+eriiy;qrujX)TE+idW0W1-JJVe$9StPrrUo#1QAh9|4V>>;5fjg+L8 zWxyJTI_~Am$=dH(i;C}b0@n;&{^%LwX5h551-zyad>|QujAL+K>U1WV(`o&Si6;Ifhpi;z&rG*-i?)5hlczp=lzMJ!4X|#2juE zBgo9fl8cxxe!HXY`1|?c6S=^{oKHF$?)dcmc?58F<4M}zMM$XUju1dxk}l@mTyJ;6 ztjReZsX(Mx$npjS&-FP464i^FUXHld^#MJ0&+zuk5Ucdyt{ciz7r6aop}SpW!~yhK z_ICFaV5Q8wj;82P{PdCSro|h{+4q{jo@(N((Ki&mN+pJ`_Kc%DU2OS5lgS>4C|(oe zWMu3#$X!XhJyl2zP;pEA`|kwD&fkpLzZIZP$18udVq!82u2~pN=|Se6T&)0NTb2de zDbo;>L@r#a9faCt0TbASXm%K`2%2uw6U=cmjgFrjQuGZlix~LGlQW!$u&$eZs+!p#~8i?1e=|bhV_@Q_v2x}9zm=77VDq@NgU3vwCc6}X1q{* zsnq0%vdPE)`)J^d_J%KF- z7x(S@0+-}$(0`r@%+;RA3lA)GOi3VFj1h3)XtW-Z&$VGG$@qd_ukAZt3mH`=X|!Yc zi;Wysp_huGk_6!JI6#D>)&R8i*P}VBt$+QTiX)VTilvV|%XEmX)#I*5L;pwqMzR(y zq91)9HJ@W;nxFcvr5D^+_C(g*iPb-vl-NG;=x>PBX&=N&nE7*d1HVtSblOm4Y1@JE9_v%eSuonAKXx=1d#&vSE-0~ z-77S|UA((A$oCB|Z!5RWuNIL?FLGcH@@zn%uvDe?y6vPTy}!8R^lR^P!3+S7aoGtC zh3@*!B=+Toz1tbXoP#gxOczvRAFDdDtTR;Tc|1PvhlNJH5#k{i>&6JL?Q`)~6u~6^ z>hZ`vM8D)QB4GV6Qkfu*-OcWQEEk1Kx$@?GX>DYZ$qoPK)kzIF@<$c3OXk7L@~!`>|F6k&e+4^#o`=J?>1GC5X}6Gs#C1X1(k%aePO z(Ss%nzOs28#VSLJVZE(clA-fpDm#S2)zY1LhwreGVOEexScUK|&^8e3{uN%EcH)%~ zZkNVPn7p$xEX^wNa>!IWjNK&BODfN+>WNm^nP3gkY^{<)T%^+$bsBPxOBEOWFK%9A zn1m6T{ytxKRhE?*Bh^#HzcczOQ=gM~)q@x;rZck48khCPtap|SSn}+#3ksH5Y`K9L zKM(R5WxB{$u6g7>uXbpKD1<@TSQLL`nWS|`q?NBB(z9*eLoewwp!;^T+=?Cdm6hp|wG@}T zf(gJvt*O%>qghAX#)LtPJSd2N?x}R5n)q#+fj_}q?S$oH9l)iw^Fcd3Y>Qtf88#J!rUgywmAFW6>_u7B85 z*9(zkh|vRnkK*Bn?@FKL*n01Fh0CH+EqNch?QiOyBz;4f&1_}bWb9CycxJCzDz_WG zaOLlWsnvQLQ#307#wZ-6tF;OPOTUS=C(St}8CgXMU=ur27o>{=5aVMp>D6}+Zb9{9 z^jtfajI=edHa&$o?0Nq0XlFutasHKN9s1R)9C#-WwniUi)pAg!ArY3|a0C@GAFOd& zsv^tUzQfE7xqD52T>1U9pZR|FUgzgQ%SP8rE>a5&@x13^#Ex&EVl z?N0PY{%XP`x$S$XTqE5K)K`GuywU5!%hRecA=8iXk&dsoBJgKgn=x2AXHeJ4O5fdX zh{xUcY;K^ZJK;U+dX~XB6jB)A6>ZkQoU^tm(od`#!3?emq_uy#f*E*bfM8&|k-wuCfms1YEyyNwZZRWCEEWXfXuXoZ%M+JQ) z^C$0(7xggl(ppyc#3VNA2pF4pP%z(El=n?@^niOt9cRudE?mz3cdzZvU z!Ah*IS0s^4wHr^VEmoy~j;9v}l}x6z#xfndkk;!gdL$Bznz=~(3yYc^EOzvV<WaiGHX@7dgM3f~G#~C|kT6=^uQ+-WTvv^gwR<>`@o~BXQI;*55U@h}2vELjGhE zwo_%MVP#Moh6$zv$eZ|6`t^)g%^X@g=Z111^OSW;Xkfg-+H@0j&4nPi|51C{KAF74*7X%tS)n9D*IRCxE{j#Qi5l? zr)19Oz9_Gk8`b8523Sh-R|*Y2XgT+eC)LE6BR=9~cBySH`-m;}*vuKpPGzu3=vS@o zz8xFUP<~~;BpxB2YwA6OFet3Z>qx4gzxlyI7UHT~CIQPau7=6cRk7Wr;y z43|ZAc&X?-GJw%O(A+W8iO->LE`7JSFS$u7hju1Jp&e&r&B~##-XgO}DY|@~_GRk^w=G6 zNU6wOLp-AuLmG~7KxW(DoH6d>(QI9Nqv-MZAEHlu0crsKT729zXUNBB%+qhl)5(j8 zCyRn7W6w_&qV3A|mydoU?bGr2v~GJU6qAX0(Et2mX~qitsOj8f#`j8lmXc9XR+^~M zM_~cY$3^Zuqy|&$ti6C!T2hd{jWOSsD>UD(k0An7 zSlB!!Lfl)Vg)0{y)`N&^zS;bMX`W}>`I@b4is@G2KE<_`*RN?FTk=paq0#lNaJ;s2 zH&~9a+&TAUEd~4hBEi{5%pnJ1sZCYm2qk1_DHaZ;1_wN$^Zye*n$tcS6%9StwO?bu z4Aqo<()+-8*I#eZp@ccu?K1H=p-gonm0?YH+w~xc^TeBjdP$*!oImZe3%0}|GrF;m z0@3u|6D}~0m`}i*tM2md%T%r?`uSnXer@;u(QT`c_#vv5rA_hLABHCSVd`YM+bzGm z!y=}FqSMg?)G&q4_}S8YH87TgMMUG(WV;W%j1A-&ZE4K(W__O$>_SO z=KR;Bk6t15pQj-12@)Y**XwKM>_J<6YYuEl*svZwykcom(!q7=+pjpDqcPB0XKA#P z^luDt3IZN(oF1CzhLHf2K;bI-c4YO!DplZ;!5Y zCY67q?&_LR%<%$T;U-T20|=gCx^dGV9!s_#yyT3{^86NScSddS0LHVC;0$#rY3mw% z`ZM51tHwnX_CNP=Z|kKHil0_1e0hwI(Vlz`8vgwZ)H3gFztT&UW!{QOaIJ#wY%Y;~<%L<<)6FPi++L5&BADxaUp!OG|bIlZXj$=4E=s(Nt zF#dE)cOxW?*KWfccOAmw)Qb!(zo0?=5@ZoB2OOX9DsBs1Gh}XCaz*_kPcLeLrkD9N zGTWQ%kmQ6i;u&ADS&aW&T7z}D)v%6anQ6XEGn=vvx{Vw=t8Kl2I6xn3r z@>AwP{Q#?>PNb^Pu?}bCgT*onbOqtPVUe1Vb`~{`B-ouoUJHUENL~8PdyTHu_k1MLnPx^_V$}IE{Bi%cmAl4W7 z&GaFep5_wvbl_hQgD2;DT)uNbUON-lP)?Fe0*}=d$S*I5+PmSYgL*8 z9MjHRFgT`xox2_ z%%(nbLRzfb@m(763FG8fE!pnfyjOA1;@R0_%uF`ca}ORUI@gyUN=y>URA2PQeS%lY z!}>O|QV`CU)!uk_y?!3?^s$1pb&dV(i}Y{GHndbre65P%7x-_~nCX^I$aLb2{6s#u z58;Rbl8FegU;37XZOg!-= z^7_Y@Iuu_vZOT<=iOubYZ?7U3;o|RA_+yLJ)3tQKhrzm6opm=1DisiVpOEoNpjO|v zk-5tkY(NnCM>inUxk^tZ)y94Kl}zg&ZS}3>2WTYscm^`5ccmD4gmXHD<1ZLuBL;rm z!P4827JeVl9{xXKu6j~FWo?#BMV|Y%;qE^WP0!R80Ga^649&xb0UdIAr2APf2ya|J zkn1KwaE~$|39ao{8ld# zga6Mz8uKpHc<@iyFht4|OiKYg*PBmb{0K|4RBy}|6yg69lSX+rEs(YC2^9I8p_X{G z2-C}G=wAcPGsyMj!LF|c%@R|627PULciL%HXQ#vtrM9Z?l@6F{TzZT^bBvylq9BIf z)cNx4AV`z44ntdI#N+%TXqBMuQ4`vXOtuse5m8;JK*?e2LWqQITM4)v1MdW{qi^>q zhpPkWPV2%q>YBFQdoqt;_rul+>rjfb_&?QBFsy9Lmv%>VXOuT}D{(|m{SuN+F4fWc za}_=Pz6He{&(;L79F+Htk+6=!7iXW4*0rrlTql}-r+_m(I_@pqs1e%N(Qe`L@|=|D zu<+>sT{#ugatT{8k$0&%T6(%m>{mM@bX^h>JMZ|^$>pc9VwstX*&Xo8KiWKf*!Z9) zg4Q|=g|H4WT{G)JPyIsgWXFOD*KPEq6SeLlhq|78eYt!6es=!~<{m?d0Q|{FD2f-0 I8NUDj0NMyz$N&HU literal 0 HcmV?d00001 diff --git a/doc/x68k.txt b/doc/x68k.txt new file mode 100644 index 00000000..16bc9dec --- /dev/null +++ b/doc/x68k.txt @@ -0,0 +1,109 @@ +------------------------------------------------------------------------------ + + SCSI Target Emulator RaSCSI (*^..^*) + version 1.33 for Raspberry Pi + + Powered by XM6 TypeG Technology. + Copyright (C) 2016-2018 GIMONS + +------------------------------------------------------------------------------ +□X68000固有の機能について + RaSCSIにはブリッジデバイスという仮想的なSCSIデバイスが実装されておりX68000と + ホストであるRaspberry Piの橋渡しを行うことができます。このブリッジデバイスと + X68000用の専用ドライバを使用して下記の機能を提供します。 + + ・イーサーネット + Neptune-Xと同様のイーサーネット機能を提供します。SCSI接続のイーサーネット + BOXのようにRaSCSIが振舞います。Raspberry PiのTAPデバイスにパケットを中継 + することで実現しています。Ether+と似たものです。 + + ・ホストファイルシステム + X68000のエミュレーターでは標準的な機能であるWindrv相当の機能を提供します。 + Raspberry Pi上のファイルシステムをリモートドライブとしてマウントすること + ができます。 + +□ブジッジデバイスの起動方法 + RaSCSI起動時にファイル名として"BRIDGE"というキーワードを設定するとそのIDに + 対してブジッリデバイスを生成します。 + + ex) + sudo rascsi -ID0 HDIMAGE0.HDS -ID6 BRIDGE + +□イーサーネット接続 + 配布物に含まれるRASETHER.SYSを使用します。このデバイスドライバがブリッジ + デバイスと連携してイーサーネットのパケット送受信を行うことができます。 + + 以下、Raspberry Piの仮想アダプタ(TAP)のIPアドレスを「192.168.68.1」として、 + X68000側を「192.168.68.3」とするケースで説明します。 + + ・X68000の設定 + RASETHER.SYSはNeptune-X用ドライバを改造して作ったものですので使用方法は + 全く同じです。X68000をネット接続するためには他に環境設定を行う必要があり + ます。設定方法は自力で調べていただくようお願いします。 + + 以下実際に使用しているCONFIG.SYSとAUTOEXEC.BATの抜粋です。 + + [CONFIG.SYS抜粋] + PROCESS = 3 10 10 + DEVICE = \NETWORK\RASETHER.SYS + + [AUTOEXEC.BAT抜粋] + SET SYSROOT=A:/NETWORK/ + SET temp=A:\ + SET tmp=A:\ + SET HOME=A:/NETWORK/ETC/ + SET HOST=X68000 + XIP.X + IFCONFIG.X lp0 up + IFCONFIG.X en0 192.168.68.3 netmask 255.255.255.0 up + INETDCONF.X +router 192.168.68.1 -rip + INETDCONF.X + + ・Raspberry Piの設定 + TAPデバイスというものを利用していますのでTAPを有効にしてください。恐らく + 最近のJessieであれば最初から有効なはずです。確認方法は/dev/net/tunという + ファイルが存在すれば有効となっていると判断できます。 + + 仮想アダプタの作成方法は次の様に行います。 + + [/etc/rc.local等から設定] + ip tuntap add ras0 mode tap user root + ip link set ras0 up + ifconfig ras0 inet 192.168.68.1/8 up + route add -net 192.168.68.0 netmask 255.255.255.0 dev ras0 + + 上記によってRaspberry Pi(192.168.68.1)とX68000(192.168.68.3)の間で通信が + 可能になります。 + + インターネット等と接続する場合はRaspberry Pi側でブリッジやルーティングの + 設定が必要になります。ご自身の環境に合わせて設定してください。無線LANの + 場合にブリッジ構成するには色々と課題があるようなのでフォワーディングと + NAT構成等もお勧めです。作者はrc.localで次のような設定で使用しています。 + + echo 1 > /proc/sys/net/ipv4/ip_forward + iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE + +□ホストファイルシステム連携 + X68000エミュレータでよく利用されるWindrvやWindrvXMと同等の機能を提供します。 + 専用のRASDRV.SYSというデバイスドライバを組み込めばRaspberri Piのファイル + システムがX68000側のドライブに見えて操作できるということです。 + + デバイスドライバの登録は簡単です。 + 例えば + + DEVICE = \SYS\RASDRV.SYS + + この場合はデフォルトでRaspberry Piのルートディレクトリをマウントします。 + デバイスドライバ起動時にどのドライブにマウントされたか表示されます。 + ルートを以外をマウントする場合はディレクトリを指定して下さい。/home/pi等を + マウントするには + + DEVICE = \SYS\RASDRV.SYS /home/pi + + と指定します。複数のディレクトリを指定すれば別々のドライブとしてマウントする + ことが可能です。 + + SUSIEをご利用の方はSUSIEより先にRASDRV.SYSを組み込んで下さい。後に組み込むと + 正しく認識できなくなると報告があります。 + +[EOF] diff --git a/src/raspberrypi/Makefile b/src/raspberrypi/Makefile new file mode 100644 index 00000000..70eb4cef --- /dev/null +++ b/src/raspberrypi/Makefile @@ -0,0 +1,51 @@ +CC = gcc +CFLAGS = -DNDEBUG -O3 +CXX = g++ +CXXFLAGS = -DNDEBUG -O3 + +RASCSI = rascsi +RASCTL = rasctl +RASDUMP = rasdump + +BIN_ALL = $(RASCSI) $(RASCTL) $(RASDUMP) + +SRC_RASCSI = \ + rascsi.cpp \ + scsi.cpp \ + disk.cpp \ + gpiobus.cpp \ + ctapdriver.cpp \ + cfilesystem.cpp \ + filepath.cpp \ + fileio.cpp + +SRC_RASCTL = \ + rasctl.cpp + +SRC_RASDUMP = \ + rasdump.cpp \ + scsi.cpp \ + gpiobus.cpp \ + filepath.cpp \ + fileio.cpp + +OBJ_RASCSI := $(SRC_RASCSI:.cpp=.o) +OBJ_RASCTL := $(SRC_RASCTL:.c=.o) +OBJ_RASDUMP := $(SRC_RASDUMP:.c=.o) + +.cpp.o: + $(CXX) $(CXXFLAGS) -c $< + +ALL: $(BIN_ALL) + +$(RASCSI): $(OBJ_RASCSI) $ + $(CXX) -o $@ $(OBJ_RASCSI) -lpthread + +$(RASCTL): $(OBJ_RASCTL) $ + $(CXX) -o $@ $(OBJ_RASCTL) + +$(RASDUMP): $(OBJ_RASDUMP) $ + $(CXX) -o $@ $(OBJ_RASDUMP) + +clean: + rm -f *.o $(BIN_ALL) diff --git a/src/raspberrypi/cfilesystem.cpp b/src/raspberrypi/cfilesystem.cpp new file mode 100644 index 00000000..347814da --- /dev/null +++ b/src/raspberrypi/cfilesystem.cpp @@ -0,0 +1,4228 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technology. +// Copyright (C) 2016-2018 GIMONS +// +// Imported NetBSD support and some optimisation patch by Rin Okuyama. +// +// [ 繝帙せ繝医ヵ繧。繧、繝ォ繧キ繧ケ繝繝 ] +// +//--------------------------------------------------------------------------- + +#include "os.h" +#include "xm6.h" +#include "log.h" +#include "filepath.h" +#include "cfilesystem.h" + +//--------------------------------------------------------------------------- +// +// 貍「蟄励さ繝シ繝牙、画鋤 +// +//--------------------------------------------------------------------------- +#define IC_BUF_SIZE 1024 +static char convert_buf[IC_BUF_SIZE]; +#ifndef __NetBSD__ +// POSIX.1貅匁侠iconv(3)繧剃スソ逕ィ +#define CONVERT(src, dest, inbuf, outbuf, outsize) \ + convert(src, dest, (char *)inbuf, outbuf, outsize) +static void convert(char const *src, char const *dest, + char *inbuf, char *outbuf, size_t outsize) +#else +// NetBSD迚iconv(3)繧剃スソ逕ィ: 隨ャ2蠑墓焚縺ッconst char ** +#define CONVERT(src, dest, inbuf, outbuf, outsize) \ + convert(src, dest, inbuf, outbuf, outsize) +static void convert(char const *src, char const *dest, + const char *inbuf, char *outbuf, size_t outsize) +#endif +{ + iconv_t cd; + size_t in; + size_t out; + size_t ret; + + *outbuf = '\0'; + in = strlen(inbuf); + out = outsize - 1; + + cd = iconv_open(dest, src); + if (cd == (iconv_t)-1) { + return; + } + + ret = iconv(cd, &inbuf, &in, &outbuf, &out); + if (ret == (size_t)-1) { + return; + } + + iconv_close(cd); + *outbuf = '\0'; +} + +//--------------------------------------------------------------------------- +// +// SJIS->UTF8螟画鋤 +// +//--------------------------------------------------------------------------- +static char* SJIS2UTF8(const char *sjis, char *utf8, size_t bufsize) +{ + CONVERT("SJIS", "UTF-8", sjis, utf8, bufsize); + return convert_buf; +} + +//--------------------------------------------------------------------------- +// +// UTF8->SJIS螟画鋤 +// +//--------------------------------------------------------------------------- +static char* UTF82SJIS(const char *utf8, char *sjis, size_t bufsize) +{ + CONVERT("UTF-8", "SJIS", utf8, sjis, bufsize); + return convert_buf; +} + +//--------------------------------------------------------------------------- +// +// SJIS->UTF8螟画鋤(邁。譏鍋沿) +// +//--------------------------------------------------------------------------- +static char* S2U(const char *sjis) +{ + SJIS2UTF8(sjis, convert_buf, IC_BUF_SIZE); + return convert_buf; +} + +//--------------------------------------------------------------------------- +// +// UTF8->SJIS螟画鋤(邁。譏鍋沿) +// +//--------------------------------------------------------------------------- +static char* U2S(const char *utf8) +{ + UTF82SJIS(utf8, convert_buf, IC_BUF_SIZE); + return convert_buf; +} + +//--------------------------------------------------------------------------- +// +/// 繝代せ蜷榊叙蠕 +/// +/// Human68k逕ィnamests讒矩菴薙°繧峨?uman68k繝代せ蜷阪r蜿門セ励☆繧九 +/// 譖ク縺崎セシ縺ソ蜈医ヰ繝繝輔ぃ縺ッ66繝舌う繝亥ソ隕√ +// +//--------------------------------------------------------------------------- +void Human68k::namests_t::GetCopyPath(BYTE* szPath) const +{ + ASSERT(this); + ASSERT(szPath); + + BYTE* p = szPath; + for (size_t i = 0; i < 65; i++) { + BYTE c = path[i]; + if (c == '\0') + break; + if (c == 0x09) { + c = '/'; + } + *p++ = c; + } + + *p = '\0'; +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ蜷榊叙蠕 +/// +/// Human68k逕ィnamests讒矩菴薙°繧峨?uman68k繝輔ぃ繧、繝ォ蜷阪r蜿門セ励☆繧九 +/// 譖ク縺崎セシ縺ソ蜈医ヰ繝繝輔ぃ縺ッ23繝舌う繝亥ソ隕√ +// +//--------------------------------------------------------------------------- +void Human68k::namests_t::GetCopyFilename(BYTE* szFilename) const +{ + ASSERT(this); + ASSERT(szFilename); + + size_t i; + BYTE* p = szFilename; + + // 繝輔ぃ繧、繝ォ蜷肴悽菴楢サ「騾 + for (i = 0; i < 8; i++) { + BYTE c = name[i]; + if (c == ' ') { + // 繝輔ぃ繧、繝ォ蜷堺クュ縺ォ繧ケ繝壹シ繧ケ縺悟コ迴セ縺励◆蝣エ蜷医∽サ・髯阪ョ繧ィ繝ウ繝医Μ縺檎カ壹>縺ヲ縺繧九°縺ゥ縺縺狗「コ隱 + /// @todo 8+3譁蟄励→TewntyOne莠呈鋤繝「繝シ繝峨〒蜍穂ス懊r螟峨∴繧九∋縺 + // add[0] 縺梧怏蜉ケ縺ェ譁蟄励↑繧臥カ壹¢繧 + if (add[0] != '\0') + goto next_name; + // name[i] 繧医j蠕後↓遨コ逋ス莉・螟悶ョ譁蟄励′蟄伜惠縺吶k縺ェ繧臥カ壹¢繧 + for (size_t j = i + 1; j < 8; j++) { + if (name[j] != ' ') + goto next_name; + } + // 繝輔ぃ繧、繝ォ蜷咲オらォッ縺ェ繧芽サ「騾∫オゆコ + break; + } + next_name: + *p++ = c; + } + // 蜈ィ縺ヲ縺ョ譁蟄励r隱ュ縺ソ霎シ繧縺ィ縲√%縺薙〒 i >= 8 縺ィ縺ェ繧 + + // 繝輔ぃ繧、繝ォ蜷肴悽菴薙′8譁蟄嶺サ・荳翫↑繧芽ソス蜉驛ィ蛻繧ょ刈縺医k + if (i >= 8) { + // 繝輔ぃ繧、繝ォ蜷崎ソス蜉驛ィ蛻霆「騾 + for (i = 0; i < 10; i++) { + BYTE c = add[i]; + if (c == '\0') + break; + *p++ = c; + } + // 蜈ィ縺ヲ縺ョ譁蟄励r隱ュ縺ソ霎シ繧縺ィ縲√%縺薙〒 i >= 10 縺ィ縺ェ繧 + } + + // 諡。蠑オ蟄舌′蟄伜惠縺吶k蝣エ蜷医ッ霆「騾 + if (ext[0] != ' ' || ext[1] != ' ' || ext[2] != ' ') { + *p++ = '.'; + for (i = 0; i < 3; i++) { + BYTE c = ext[i]; + if (c == ' ') { + // 諡。蠑オ蟄蝉クュ縺ォ繧ケ繝壹シ繧ケ縺悟コ迴セ縺励◆蝣エ蜷医∽サ・髯阪ョ繧ィ繝ウ繝医Μ縺檎カ壹>縺ヲ縺繧九°縺ゥ縺縺狗「コ隱 + /// @todo 8+3譁蟄励→TewntyOne莠呈鋤繝「繝シ繝峨〒蜍穂ス懊r螟峨∴繧九∋縺 + // ext[i] 繧医j蠕後↓遨コ逋ス莉・螟悶ョ譁蟄励′蟄伜惠縺吶k縺ェ繧臥カ壹¢繧 + for (size_t j = i + 1; j < 3; j++) { + if (ext[j] != ' ') + goto next_ext; + } + // 諡。蠑オ蟄千オらォッ縺ェ繧芽サ「騾∫オゆコ + break; + } + next_ext: + *p++ = c; + } + // 蜈ィ縺ヲ縺ョ譁蟄励r隱ュ縺ソ霎シ繧縺ィ縲√%縺薙〒 i >= 3 縺ィ縺ェ繧 + } + + // 逡ェ蜈オ霑ス蜉 + *p = '\0'; +} + +//=========================================================================== +// +// 繝帙せ繝亥エ繝峨Λ繧、繝 +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +/// 繝繝輔か繝ォ繝医さ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +CHostDrv::CHostDrv() +{ + // 蛻晄悄蛹 + m_bWriteProtect = FALSE; + m_bEnable = FALSE; + m_capCache.sectors = 0; + m_bVolumeCache = FALSE; + m_szVolumeCache[0] = _T('\0'); + m_szBase[0] = _T('\0'); + m_nRing = 0; +} + +//--------------------------------------------------------------------------- +// +/// 繝繧ケ繝医Λ繧ッ繧ソ final +// +//--------------------------------------------------------------------------- +CHostDrv::~CHostDrv() +{ + CHostPath* p; + while ((p = (CHostPath*)m_cRing.Next()) != &m_cRing) { + delete p; + ASSERT(m_nRing); + m_nRing--; + } + + // 螳滉ス薙′蟄伜惠縺励↑縺縺薙→繧堤「コ隱 (蠢オ縺ョ縺溘a) + ASSERT(m_cRing.Next() == &m_cRing); + ASSERT(m_cRing.Prev() == &m_cRing); + ASSERT(m_nRing == 0); +} + +//--------------------------------------------------------------------------- +// +/// 蛻晄悄蛹 (繝繝舌う繧ケ襍キ蜍輔→繝ュ繝シ繝) +// +//--------------------------------------------------------------------------- +void CHostDrv::Init(const TCHAR* szBase, DWORD nFlag) +{ + ASSERT(this); + ASSERT(szBase); + ASSERT(strlen(szBase) < FILEPATH_MAX); + ASSERT(m_bWriteProtect == FALSE); + ASSERT(m_bEnable == FALSE); + ASSERT(m_capCache.sectors == 0); + ASSERT(m_bVolumeCache == FALSE); + ASSERT(m_szVolumeCache[0] == _T('\0')); + + // 螳滉ス薙′蟄伜惠縺励↑縺縺薙→繧堤「コ隱 (蠢オ縺ョ縺溘a) + ASSERT(m_cRing.Next() == &m_cRing); + ASSERT(m_cRing.Prev() == &m_cRing); + ASSERT(m_nRing == 0); + + // 繝代Λ繝。繝シ繧ソ繧貞女縺大叙繧 + if (nFlag & FSFLAG_WRITE_PROTECT) + m_bWriteProtect = TRUE; + strcpy(m_szBase, szBase); + + // 繝吶シ繧ケ繝代せ縺ョ譛蠕後ョ繝代せ蛹コ蛻繧翫槭シ繧ッ繧貞炎髯、縺吶k + /// @warning Unicode蛻ゥ逕ィ譎ゅッ菫ョ豁」縺悟ソ隕 + TCHAR* pClear = NULL; + TCHAR* p = m_szBase; + for (;;) { + TCHAR c = *p; + if (c == _T('\0')) + break; + if (c == _T('/') || c == _T('\\')) { + pClear = p; + } else { + pClear = NULL; + } + if ((0x80 <= c && c <= 0x9F) || 0xE0 <= c) { // 蜴ウ蟇縺ォ縺ッ 0x81ス0x9F 0xE0ス0xEF + p++; + if (*p == _T('\0')) + break; + } + p++; + } + if (pClear) + *pClear = _T('\0'); + + // 迥カ諷区峩譁ー + m_bEnable = TRUE; +} + +//--------------------------------------------------------------------------- +// +/// 繝。繝繧」繧「繝√ぉ繝繧ッ +// +//--------------------------------------------------------------------------- +BOOL CHostDrv::isMediaOffline() +{ + ASSERT(this); + + // 繧ェ繝輔Λ繧、繝ウ迥カ諷九メ繧ァ繝繧ッ + return m_bEnable == FALSE; +} + +//--------------------------------------------------------------------------- +// +/// 繝。繝繧」繧「繝舌う繝医ョ蜿門セ +// +//--------------------------------------------------------------------------- +BYTE CHostDrv::GetMediaByte() const +{ + ASSERT(this); + + return Human68k::MEDIA_REMOTE; +} + +//--------------------------------------------------------------------------- +// +/// 繝峨Λ繧、繝也憾諷九ョ蜿門セ +// +//--------------------------------------------------------------------------- +DWORD CHostDrv::GetStatus() const +{ + ASSERT(this); + + return 0x40 | (m_bEnable ? (m_bWriteProtect ? 0x08 : 0) | 0x02 : 0); +} + +//--------------------------------------------------------------------------- +// +/// 繝。繝繧」繧「迥カ諷玖ィュ螳 +// +//--------------------------------------------------------------------------- +void CHostDrv::SetEnable(BOOL bEnable) +{ + ASSERT(this); + + m_bEnable = bEnable; + + if (bEnable == FALSE) { + // 繧ュ繝」繝繧キ繝・豸亥悉 + m_capCache.sectors = 0; + m_bVolumeCache = FALSE; + m_szVolumeCache[0] = _T('\0'); + } +} + +//--------------------------------------------------------------------------- +// +/// 繝懊Μ繝・繝シ繝繝ゥ繝吶Ν縺ョ蜿門セ +// +//--------------------------------------------------------------------------- +void CHostDrv::GetVolume(TCHAR* szLabel) +{ + ASSERT(this); + ASSERT(szLabel); + ASSERT(m_bEnable); + + // 繝懊Μ繝・繝シ繝繝ゥ繝吶Ν縺ョ蜿門セ +#ifdef RASCSI + strcpy(m_szVolumeCache, m_szBase); +#else + m_szVolumeCache[0] = _T('\0'); +#endif + + // 繧ュ繝」繝繧キ繝・譖エ譁ー + m_bVolumeCache = TRUE; + + // 蜀螳ケ繧定サ「騾 + strcpy(szLabel, m_szVolumeCache); +} + +//--------------------------------------------------------------------------- +// +/// 繧ュ繝」繝繧キ繝・縺九i繝懊Μ繝・繝シ繝繝ゥ繝吶Ν繧貞叙蠕 +/// +/// 繧ュ繝」繝繧キ繝・縺輔l縺ヲ縺繧九懊Μ繝・繝シ繝繝ゥ繝吶Ν諠蝣ア繧定サ「騾√☆繧九 +/// 繧ュ繝」繝繧キ繝・蜀螳ケ縺梧怏蜉ケ縺ェ繧欝RUE繧偵∫┌蜉ケ縺ェ繧宇ALSE繧定ソ斐☆縲 +// +//--------------------------------------------------------------------------- +BOOL CHostDrv::GetVolumeCache(TCHAR* szLabel) const +{ + ASSERT(this); + ASSERT(szLabel); + + // 蜀螳ケ繧定サ「騾 + strcpy(szLabel, m_szVolumeCache); + + return m_bVolumeCache; +} + +//--------------------------------------------------------------------------- +// +/// 螳ケ驥上ョ蜿門セ +// +//--------------------------------------------------------------------------- +DWORD CHostDrv::GetCapacity(Human68k::capacity_t* pCapacity) +{ + ASSERT(this); + ASSERT(pCapacity); + ASSERT(m_bEnable); + + DWORD nFree = 0x7FFF8000; + DWORD freearea; + DWORD clusters; + DWORD sectors; + + freearea = 0xFFFF; + clusters = 0xFFFF; + sectors = 64; + + // 繝代Λ繝。繝シ繧ソ遽蝗イ諠ウ螳 + ASSERT(freearea <= 0xFFFF); + ASSERT(clusters <= 0xFFFF); + ASSERT(sectors <= 64); + + // 繧ュ繝」繝繧キ繝・譖エ譁ー + m_capCache.freearea = (WORD)freearea; + m_capCache.clusters = (WORD)clusters; + m_capCache.sectors = (WORD)sectors; + m_capCache.bytes = 512; + + // 蜀螳ケ繧定サ「騾 + memcpy(pCapacity, &m_capCache, sizeof(m_capCache)); + + return nFree; +} + +//--------------------------------------------------------------------------- +// +/// 繧ュ繝」繝繧キ繝・縺九i螳ケ驥上r蜿門セ +/// +/// 繧ュ繝」繝繧キ繝・縺輔l縺ヲ縺繧句ョケ驥乗ュ蝣ア繧定サ「騾√☆繧九 +/// 繧ュ繝」繝繧キ繝・蜀螳ケ縺梧怏蜉ケ縺ェ繧欝RUE繧偵∫┌蜉ケ縺ェ繧宇ALSE繧定ソ斐☆縲 +// +//--------------------------------------------------------------------------- +BOOL CHostDrv::GetCapacityCache(Human68k::capacity_t* pCapacity) const +{ + ASSERT(this); + ASSERT(pCapacity); + + // 蜀螳ケ繧定サ「騾 + memcpy(pCapacity, &m_capCache, sizeof(m_capCache)); + + return m_capCache.sectors != 0; +} + +//--------------------------------------------------------------------------- +// +/// 蜈ィ縺ヲ縺ョ繧ュ繝」繝繧キ繝・繧呈峩譁ー縺吶k +// +//--------------------------------------------------------------------------- +void CHostDrv::CleanCache() +{ + ASSERT(this); + + Lock(); + for (CHostPath* p = (CHostPath*)m_cRing.Next(); p != &m_cRing;) { + p->Release(); + p = (CHostPath*)p->Next(); + } + Unlock(); +} + +//--------------------------------------------------------------------------- +// +/// 謖螳壹&繧後◆繝代せ縺ョ繧ュ繝」繝繧キ繝・繧呈峩譁ー縺吶k +// +//--------------------------------------------------------------------------- +void CHostDrv::CleanCache(const BYTE* szHumanPath) +{ + ASSERT(this); + ASSERT(szHumanPath); + + Lock(); + CHostPath* p = FindCache(szHumanPath); + if (p) { + p->Restore(); + p->Release(); + } + Unlock(); +} + +//--------------------------------------------------------------------------- +// +/// 謖螳壹&繧後◆繝代せ莉・荳九ョ繧ュ繝」繝繧キ繝・繧貞ィ縺ヲ譖エ譁ー縺吶k +// +//--------------------------------------------------------------------------- +void CHostDrv::CleanCacheChild(const BYTE* szHumanPath) +{ + ASSERT(this); + ASSERT(szHumanPath); + + Lock(); + CHostPath* p = (CHostPath*)m_cRing.Next(); + while (p != &m_cRing) { + if (p->isSameChild(szHumanPath)) + p->Release(); + p = (CHostPath*)p->Next(); + } + Unlock(); +} + +//--------------------------------------------------------------------------- +// +/// 謖螳壹&繧後◆繝代せ縺ョ繧ュ繝」繝繧キ繝・繧貞炎髯、縺吶k +// +//--------------------------------------------------------------------------- +void CHostDrv::DeleteCache(const BYTE* szHumanPath) +{ + ASSERT(this); + ASSERT(szHumanPath); + + Lock(); + CHostPath* p = FindCache(szHumanPath); + if (p) { + delete p; + ASSERT(m_nRing); + m_nRing--; + } + Unlock(); +} + +//--------------------------------------------------------------------------- +// +/// 謖螳壹&繧後◆繝代せ縺後く繝」繝繧キ繝・縺輔l縺ヲ縺繧九°讀懃エ「縺吶k +/// +/// 謇譛峨☆繧九く繝」繧キ繝・繝舌ャ繝輔ぃ縺ョ荳ュ縺九i螳悟ィ荳閾エ縺ァ讀懃エ「縺励∬ヲ九▽縺九l縺ー縺昴ョ蜷咲ァー繧定ソ斐☆縲 +/// 繝輔ぃ繧、繝ォ蜷阪r髯、螟悶@縺ヲ縺翫¥縺薙→縲 +/// 蠢縺壻ク贋ス阪〒謗剃サ門宛蠕。繧定。後↑縺縺薙→縲 +// +//--------------------------------------------------------------------------- +CHostPath* CHostDrv::FindCache(const BYTE* szHuman) +{ + ASSERT(this); + ASSERT(szHuman); + + // 謇謖√@縺ヲ縺繧句ィ縺ヲ縺ョ繝輔ぃ繧、繝ォ蜷阪ョ荳ュ縺九i螳悟ィ荳閾エ縺吶k繧ゅョ繧呈、懃エ「 + for (CHostPath* p = (CHostPath*)m_cRing.Next(); p != &m_cRing;) { + if (p->isSameHuman(szHuman)) + return p; + p = (CHostPath*)p->Next(); + } + + return NULL; +} + +//--------------------------------------------------------------------------- +// +/// 繧ュ繝」繝繧キ繝・諠蝣ア繧貞縺ォ縲√帙せ繝亥エ縺ョ蜷咲ァー繧堤佐蠕励☆繧 +/// +/// 繝代せ縺後く繝」繝繧キ繝・縺ォ縺ゅk縺狗「コ隱阪ゅ↑縺代l縺ー繧ィ繝ゥ繝シ縲 +/// 隕九▽縺九▲縺溘く繝」繝繧キ繝・縺ョ譖エ譁ー繝√ぉ繝繧ッ縲よ峩譁ー縺悟ソ隕√↑繧峨お繝ゥ繝シ縲 +/// 蠢縺壻ク贋ス阪〒謗剃サ門宛蠕。繧定。後↑縺縺薙→縲 +// +//--------------------------------------------------------------------------- +CHostPath* CHostDrv::CopyCache(CHostFiles* pFiles) +{ + ASSERT(this); + ASSERT(pFiles); + ASSERT(strlen((const char*)pFiles->GetHumanPath()) < HUMAN68K_PATH_MAX); + + // 繧ュ繝」繝繧キ繝・讀懃エ「 + CHostPath* pPath = FindCache(pFiles->GetHumanPath()); + if (pPath == NULL) + return NULL; // 繧ィ繝ゥ繝シ: 繧ュ繝」繝繧キ繝・縺ェ縺 + + // 繝ェ繝ウ繧ー蜈磯ュ縺ク遘サ蜍 + pPath->Insert(&m_cRing); + + // 繧ュ繝」繝繧キ繝・譖エ譁ー繝√ぉ繝繧ッ + if (pPath->isRefresh()) + return NULL; // 繧ィ繝ゥ繝シ: 繧ュ繝」繝繧キ繝・譖エ譁ー縺悟ソ隕 + + // 繝帙せ繝亥エ縺ョ繝代せ蜷阪r菫晏ュ + pFiles->SetResult(pPath->GetHost()); + + return pPath; +} + +//--------------------------------------------------------------------------- +// +/// 繝帙せ繝亥エ縺ョ蜷咲ァー縺ョ讒狗ッ峨↓蠢隕√↑諠蝣ア繧偵☆縺ケ縺ヲ蜿門セ励☆繧 +/// +/// 繝輔ぃ繧、繝ォ蜷阪ッ逵∫払蜿ッ閭ス縲(譎ョ騾壹ッ謖螳壹@縺ェ縺) +/// 蠢縺壻ク贋ス阪〒謗剃サ門宛蠕。繧定。後↑縺縺薙→縲 +/// 繝吶シ繧ケ繝代せ譛ォ蟆セ縺ォ繝代せ蛹コ蛻繧頑枚蟄励r縺、縺代↑縺繧医≧豕ィ諢上 +/// 繝輔ぃ繧、繝ォ繧「繧ッ繧サ繧ケ縺悟、夂匱縺吶k蜿ッ閭ス諤ァ縺後≠繧九→縺阪ッ縲〃M繧ケ繝ャ繝繝峨ョ蜍穂ス懊r髢句ァ九&縺帙k縲 +/// +/// 菴ソ縺縺九◆: +/// CopyCache()縺励※繧ィ繝ゥ繝シ縺ョ蝣エ蜷医ッMakeCache()縺吶k縲ょソ縺壽ュ」縺励>繝帙せ繝亥エ縺ョ繝代せ縺悟叙蠕励〒縺阪k縲 +/// +/// 繝輔ぃ繧、繝ォ蜷阪→繝代せ蜷阪r縺吶∋縺ヲ蛻髮「縺吶k縲 +/// 荳贋ス阪ョ繧」繝ャ繧ッ繝医Μ縺九i鬆縺ォ縲√く繝」繝繧キ繝・縺輔l縺ヲ縺繧九°縺ゥ縺縺狗「コ隱阪 +/// 繧ュ繝」繝繧キ繝・縺輔l縺ヲ縺繧後ー遐エ譽繝√ぉ繝繧ッ縲らエ譽縺励◆蝣エ蜷域悴繧ュ繝」繝繧キ繝・謇ア縺縺ィ縺ェ繧九 +/// 繧ュ繝」繝繧キ繝・縺輔l縺ヲ縺縺ェ縺代l縺ー繧ュ繝」繝繧キ繝・繧呈ァ狗ッ峨 +/// 鬆逡ェ縺ォ縺吶∋縺ヲ縺ョ繝繧」繝ャ繧ッ繝医Μ繝サ繝輔ぃ繧、繝ォ蜷阪↓蟇セ縺励※陦後↑縺邨ゆコ縲 +/// 繧ィ繝ゥ繝シ縺檎匱逕溘@縺溷エ蜷医ッNULL縺ィ縺ェ繧九 +// +//--------------------------------------------------------------------------- +CHostPath* CHostDrv::MakeCache(CHostFiles* pFiles) +{ + ASSERT(this); + ASSERT(pFiles); + ASSERT(strlen((const char*)pFiles->GetHumanPath()) < HUMAN68K_PATH_MAX); + + ASSERT(m_szBase); + ASSERT(strlen(m_szBase) < FILEPATH_MAX); + + BYTE szHumanPath[HUMAN68K_PATH_MAX]; // 繝ォ繝シ繝医°繧蛾縺ォ繝代せ蜷阪′蜈・繧 + szHumanPath[0] = '\0'; + size_t nHumanPath = 0; + + TCHAR szHostPath[FILEPATH_MAX]; + strcpy(szHostPath, m_szBase); + size_t nHostPath = strlen(szHostPath); + + CHostPath* pPath; + const BYTE* p = pFiles->GetHumanPath(); + for (;;) { + // 繝代せ蛹コ蛻繧翫r霑ス蜉 + if (nHumanPath + 1 >= HUMAN68K_PATH_MAX) + return NULL; // 繧ィ繝ゥ繝シ: Human68k繝代せ縺碁聞縺吶℃繧 + szHumanPath[nHumanPath++] = '/'; + szHumanPath[nHumanPath] = '\0'; + if (nHostPath + 1 >= FILEPATH_MAX) + return NULL; // 繧ィ繝ゥ繝シ: 繝帙せ繝亥エ縺ョ繝代せ縺碁聞縺吶℃繧 + szHostPath[nHostPath++] = _T('/'); + szHostPath[nHostPath] = _T('\0'); + + // 繝輔ぃ繧、繝ォ縺縺」縺薙>繧後k + BYTE szHumanFilename[24]; // 繝輔ぃ繧、繝ォ蜷埼Κ蛻 + p = SeparateCopyFilename(p, szHumanFilename); + if (p == NULL) + return NULL; // 繧ィ繝ゥ繝シ: 繝輔ぃ繧、繝ォ蜷崎ェュ縺ソ霎シ縺ソ螟ア謨 + size_t n = strlen((const char*)szHumanFilename); + if (nHumanPath + n >= HUMAN68K_PATH_MAX) + return NULL; // 繧ィ繝ゥ繝シ: Human68k繝代せ縺碁聞縺吶℃繧 + + // 隧イ蠖薙ヱ繧ケ縺後く繝」繝繧キ繝・縺輔l縺ヲ縺繧九°シ + pPath = FindCache(szHumanPath); + if (pPath == NULL) { + // 繧ュ繝」繝繧キ繝・譛螟ァ謨ー繝√ぉ繝繧ッ + if (m_nRing >= XM6_HOST_DIRENTRY_CACHE_MAX) { + // 譛繧ょ商縺繧ュ繝」繝繧キ繝・繧堤エ譽縺励※蜀榊茜逕ィ + pPath = (CHostPath*)m_cRing.Prev(); + pPath->Clean(); // 蜈ィ繝輔ぃ繧、繝ォ隗」謾セ 譖エ譁ー繝√ぉ繝繧ッ逕ィ繝上Φ繝峨Ν繧りァ」謾セ + } else { + // 譁ー隕冗匳骭イ + pPath = new CHostPath; + ASSERT(pPath); + m_nRing++; + } + pPath->SetHuman(szHumanPath); + pPath->SetHost(szHostPath); + + // 迥カ諷区峩譁ー + pPath->Refresh(); + } + + // 繧ュ繝」繝繧キ繝・譖エ譁ー繝√ぉ繝繧ッ + if (pPath->isRefresh()) { + // 迥カ諷区峩譁ー + pPath->Refresh(); + } + + // 繝ェ繝ウ繧ー蜈磯ュ縺ク + pPath->Insert(&m_cRing); + + // 繝輔ぃ繧、繝ォ蜷阪′縺ェ縺代l縺ー縺薙%縺ァ邨ゆコ + if (n == 0) + break; + + // 谺。縺ョ繝代せ繧呈、懃エ「 + // 繝代せ縺ョ騾比クュ縺ェ繧峨ョ繧」繝ャ繧ッ繝医Μ縺九←縺縺狗「コ隱 + const CHostFilename* pFilename; + if (*p != '\0') + pFilename = pPath->FindFilename(szHumanFilename, Human68k::AT_DIRECTORY); + else + pFilename = pPath->FindFilename(szHumanFilename); + if (pFilename == NULL) + return NULL; // 繧ィ繝ゥ繝シ: 騾比クュ縺ョ繝代せ蜷/繝輔ぃ繧、繝ォ蜷阪′隕九▽縺九i縺ェ縺 + + // 繝代せ蜷阪r騾」邨 + strcpy((char*)szHumanPath + nHumanPath, (const char*)szHumanFilename); + nHumanPath += n; + + n = strlen(pFilename->GetHost()); + if (nHostPath + n >= FILEPATH_MAX) + return NULL; // 繧ィ繝ゥ繝シ: 繝帙せ繝亥エ縺ョ繝代せ縺碁聞縺吶℃繧 + strcpy(szHostPath + nHostPath, pFilename->GetHost()); + nHostPath += n; + + // PLEASE CONTINUE + if (*p == '\0') + break; + } + + // 繝帙せ繝亥エ縺ョ繝代せ蜷阪r菫晏ュ + pFiles->SetResult(szHostPath); + + return pPath; +} + +//--------------------------------------------------------------------------- +// +/// 繝帙せ繝亥エ縺ョ蜷咲ァー繧呈、懃エ「 (繝代せ蜷+繝輔ぃ繧、繝ォ蜷(逵∫払蜿ッ)+螻樊ァ) +/// +/// 縺ゅi縺九§繧∝ィ縺ヲ縺ョHuman68k逕ィ繝代Λ繝。繝シ繧ソ繧定ィュ螳壹@縺ヲ縺翫¥縺薙→縲 +// +//--------------------------------------------------------------------------- +BOOL CHostDrv::Find(CHostFiles* pFiles) +{ + ASSERT(this); + ASSERT(pFiles); + + // 謗剃サ門宛蠕。髢句ァ + Lock(); + + // 繝代せ蜷咲佐蠕励♀繧医ウ繧ュ繝」繝繧キ繝・讒狗ッ + CHostPath* pPath = CopyCache(pFiles); + if (pPath == NULL) { + pPath = MakeCache(pFiles); + if (pPath == NULL) { + Unlock(); + CleanCache(); + return FALSE; // 繧ィ繝ゥ繝シ: 繧ュ繝」繝繧キ繝・讒狗ッ牙、ア謨 + } + } + + // 繝帙せ繝亥エ縺ョ繝代せ蜷阪r菫晏ュ + pFiles->SetResult(pPath->GetHost()); + + // 繝代せ蜷阪ョ縺ソ縺ェ繧臥オゆコ + if (pFiles->isPathOnly()) { + Unlock(); + return TRUE; // 豁」蟶ク邨ゆコ: 繝代せ蜷阪ョ縺ソ + } + + // 繝輔ぃ繧、繝ォ蜷肴、懃エ「 + const CHostFilename* pFilename = pFiles->Find(pPath); + if (pFilename == NULL) { + Unlock(); + return FALSE; // 繧ィ繝ゥ繝シ: 繝輔ぃ繧、繝ォ蜷阪′迯イ蠕励〒縺阪∪縺帙s + } + + // Human68k蛛エ縺ョ讀懃エ「邨先棡菫晏ュ + pFiles->SetEntry(pFilename); + + // 繝帙せ繝亥エ縺ョ繝輔Ν繝代せ蜷堺ソ晏ュ + pFiles->AddResult(pFilename->GetHost()); + + // 謗剃サ門宛蠕。邨ゆコ + Unlock(); + + return TRUE; +} + +//=========================================================================== +// +// 繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ 繝輔ぃ繧、繝ォ蜷 +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +/// 繝繝輔か繝ォ繝医さ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +CHostFilename::CHostFilename() +{ +} + +//--------------------------------------------------------------------------- +// +/// 繝帙せ繝亥エ縺ョ蜷咲ァー繧定ィュ螳 +// +//--------------------------------------------------------------------------- +void CHostFilename::SetHost(const TCHAR* szHost) +{ + ASSERT(this); + ASSERT(szHost); + ASSERT(strlen(szHost) < FILEPATH_MAX); + + strcpy(m_szHost, szHost); +} + +//--------------------------------------------------------------------------- +// +/// Human68k蛛エ縺ョ繝輔ぃ繧、繝ォ蜷崎ヲ∫エ繧偵さ繝斐シ +// +//--------------------------------------------------------------------------- +BYTE* CHostFilename::CopyName(BYTE* pWrite, const BYTE* pFirst, const BYTE* pLast) // static +{ + ASSERT(pWrite); + ASSERT(pFirst); + ASSERT(pLast); + + for (const BYTE* p = pFirst; p < pLast; p++) { + *pWrite++ = *p; + } + + return pWrite; +} + +//--------------------------------------------------------------------------- +// +/// Human68k蛛エ縺ョ蜷咲ァー繧貞、画鋤 +/// +/// 縺ゅi縺九§繧ヾetHost()繧貞ョ溯。後@縺ヲ縺翫¥縺薙→縲 +/// 18+3縺ョ蜻ス蜷崎ヲ丞援縺ォ蠕薙▲縺溷錐蜑榊、画鋤繧定。後↑縺縲 +/// 繝輔ぃ繧、繝ォ蜷榊磯ュ縺翫h縺ウ譛ォ蟆セ縺ョ遨コ逋ス縺ッ縲?uman68k縺ァ謇ア縺医↑縺縺溘a閾ェ蜍慕噪縺ォ蜑企勁縺輔l繧九 +/// 繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ縺ョ蜷榊燕驛ィ蛻繧偵√ヵ繧。繧、繝ォ蜷榊、画鋤譎ゅョ諡。蠑オ蟄舌ョ菴咲スョ諠蝣ア繧剃スソ縺」縺ヲ逕滓舌☆繧九 +/// 縺昴ョ蠕後√ヵ繧。繧、繝ォ蜷阪ョ逡ー蟶ク蛻、螳壹r陦後↑縺縲(繧ケ繝壹シ繧ケ8譁蟄励□縺代ョ繝輔ぃ繧、繝ォ蜷阪↑縺ゥ) +/// 繝輔ぃ繧、繝ォ蜷阪ョ驥崎、蛻、螳壹ッ陦後↑繧上↑縺縺ョ縺ァ豕ィ諢上ゅ%繧後i縺ョ蛻、螳壹ッ荳贋ス阪け繝ゥ繧ケ縺ァ陦後↑縺縲 +/// TwentyOne version 1.36c modified +14 patchlevel9莉・髯阪ョ諡。蠑オ蟄占ヲ丞援縺ォ蟇セ蠢懊&縺帙k縲 +// +//--------------------------------------------------------------------------- +void CHostFilename::ConvertHuman(int nCount) +{ + char szHost[FILEPATH_MAX]; + + ASSERT(this); + + // 迚ケ谿翫ョ繧」繝ャ繧ッ繝医Μ蜷阪ョ蝣エ蜷医ッ螟画鋤縺励↑縺 + if (m_szHost[0] == _T('.') && + (m_szHost[1] == _T('\0') || (m_szHost[1] == _T('.') && m_szHost[2] == _T('\0')))) { + strcpy((char*)m_szHuman, m_szHost); /// @warning Unicode譎りヲ∽ソョ豁」 竊 貂 + + m_bCorrect = TRUE; + m_pszHumanLast = m_szHuman + strlen((const char*)m_szHuman); + m_pszHumanExt = m_pszHumanLast; + return; + } + + size_t nMax = 18; // 繝吶シ繧ケ驛ィ蛻(繝吶シ繧ケ蜷阪→諡。蠑オ蟄仙錐)縺ョ繝舌う繝域焚 + DWORD nOption = CFileSys::GetFileOption(); + if (nOption & WINDRV_OPT_CONVERT_LENGTH) + nMax = 8; + + // 繝吶シ繧ケ蜷埼Κ蛻縺ョ陬懈ュ」貅門y + BYTE szNumber[8]; + BYTE* pNumber = NULL; + if (nCount >= 0) { + pNumber = &szNumber[8]; + for (DWORD i = 0; i < 5; i++) { // 譛螟ァ5+1譯√∪縺ァ (繝吶シ繧ケ蜷榊磯ュ2繝舌う繝医ッ蠢縺壽ョ九☆) + int n = nCount % 36; + nMax--; + pNumber--; + *pNumber = (BYTE)(n + (n < 10 ? '0' : 'A' - 10)); + nCount /= 36; + if (nCount == 0) + break; + } + nMax--; + pNumber--; + BYTE c = (BYTE)((nOption >> 24) & 0x7F); + if (c == 0) + c = XM6_HOST_FILENAME_MARK; + *pNumber = c; + } + + // 譁蟄怜、画鋤 + /// @warning Unicode譛ェ蟇セ蠢懊ゅ>縺壹lUnicode縺ョ荳也阜縺ォ鬟ョ縺セ繧後◆譎ゅッ縺薙%縺ァ螟画鋤繧定。後↑縺 竊 貂 + BYTE szHuman[FILEPATH_MAX]; + const BYTE* pFirst = szHuman; + const BYTE* pLast; + const BYTE* pExt = NULL; + + { + strcpy(szHost, m_szHost); + const BYTE* pRead = (const BYTE*)szHost; + BYTE* pWrite = szHuman; + const BYTE* pPeriod = SeparateExt(pRead); + + for (bool bFirst = true;; bFirst = false) { + BYTE c = *pRead++; + switch (c) { + case ' ': + if (nOption & WINDRV_OPT_REDUCED_SPACE) + continue; + if (nOption & WINDRV_OPT_CONVERT_SPACE) + c = '_'; + else if (pWrite == szHuman) + continue; // 蜈磯ュ縺ョ遨コ逋ス縺ッ辟。隕 + break; + case '=': + case '+': + if (nOption & WINDRV_OPT_REDUCED_BADCHAR) + continue; + if (nOption & WINDRV_OPT_CONVERT_BADCHAR) + c = '_'; + break; + case '-': + if (bFirst) { + if (nOption & WINDRV_OPT_REDUCED_HYPHEN) + continue; + if (nOption & WINDRV_OPT_CONVERT_HYPHEN) + c = '_'; + break; + } + if (nOption & WINDRV_OPT_REDUCED_HYPHENS) + continue; + if (nOption & WINDRV_OPT_CONVERT_HYPHENS) + c = '_'; + break; + case '.': + if (pRead - 1 == pPeriod) { // Human68k諡。蠑オ蟄舌ッ萓句、悶→縺吶k + pExt = pWrite; + break; + } + if (bFirst) { + if (nOption & WINDRV_OPT_REDUCED_PERIOD) + continue; + if (nOption & WINDRV_OPT_CONVERT_PERIOD) + c = '_'; + break; + } + if (nOption & WINDRV_OPT_REDUCED_PERIODS) + continue; + if (nOption & WINDRV_OPT_CONVERT_PERIODS) + c = '_'; + break; + } + *pWrite++ = c; + if (c == '\0') + break; + } + + pLast = pWrite - 1; + } + + // 諡。蠑オ蟄占」懈ュ」 + if (pExt) { + // 譛ォ蟆セ縺ョ遨コ逋ス繧貞炎髯、縺吶k + while (pExt < pLast - 1 && *(pLast - 1) == ' ') { + pLast--; + BYTE* p = (BYTE*)pLast; + *p = '\0'; + } + + // 螟画鋤蠕後↓螳滉ス薙′縺ェ縺上↑縺」縺溷エ蜷医ッ蜑企勁 + if (pExt + 1 >= pLast) { + pLast = pExt; + BYTE* p = (BYTE*)pLast; + *p = '\0'; // 蠢オ縺ョ縺溘a + } + } else { + pExt = pLast; + } + + // 逋サ蝣エ莠コ迚ゥ邏ケ莉 + // + // pFirst: 菫コ縺ッ繝ェ繝シ繝繝シ縲ゅヵ繧。繧、繝ォ蜷榊磯ュ + // pCut: 騾夂ァー繝輔ぉ繧、繧ケ縲よ怙蛻昴ョ繝斐Μ繧ェ繝峨ョ蜃コ迴セ菴咲スョ 縺昴ョ蠕後吶シ繧ケ蜷咲オらォッ菴咲スョ縺ィ縺ェ繧 + // pSecond: 繧医♂縺翫∪縺。縺ゥ縺縲ゆソコ讒倥%縺昴槭シ繝峨ャ繧ッ縲よ僑蠑オ蟄仙錐縺ョ髢句ァ倶ス咲スョ縲ゅ□縺九i菴輔 + // pExt: B繝サA繝サ繝舌Λ繧ォ繧ケ縲Human68k諡。蠑オ蟄舌ョ螟ゥ謇阪□縲ゅ〒繧ゅ3譁蟄励h繧企聞縺蜷榊燕縺ッ蜍伜シ√↑縲 + // 譛蠕後ョ繝斐Μ繧ェ繝峨ョ蜃コ迴セ菴咲スョ 隧イ蠖薙@縺ェ縺代l縺ーpLast縺ィ蜷後§蛟、 + // + // 竊菟First 竊菟Stop 竊菟Second 竊 竊菟Ext + // T h i s _ i s _ a . V e r y . L o n g . F i l e n a m e . t x t \0 + // 竊叢Cut 竊 竊叢Cut蛻晄悄菴咲スョ 竊叢Last + // + // 荳願ィ倥ョ蝣エ蜷医∝、画鋤蠕後ッ This.Long.Filename.txt 縺ィ縺ェ繧 + + // 1譁蟄礼岼蛻、螳 + const BYTE* pCut = pFirst; + const BYTE* pStop = pExt - nMax; // 諡。蠑オ蟄仙錐縺ッ譛螟ァ17繝舌う繝医→縺吶k(繝吶シ繧ケ蜷阪r谿九☆) + if (pFirst < pExt) { + pCut++; // 蠢縺1繝舌う繝医ッ繝吶シ繧ケ蜷阪r菴ソ縺 + BYTE c = *pFirst; + if ((0x80 <= c && c <= 0x9F) || 0xE0 <= c) { // 蜴ウ蟇縺ォ縺ッ 0x81ス0x9F 0xE0ス0xEF + pCut++; // 繝吶シ繧ケ蜷 譛蟆2繝舌う繝 + pStop++; // 諡。蠑オ蟄仙錐 譛螟ァ16繝舌う繝 + } + } + if (pStop < pFirst) + pStop = pFirst; + + // 繝吶シ繧ケ蜷榊愛螳 + pCut = (BYTE*)strchr((const char*)pCut, '.'); // SJIS2繝舌う繝育岼縺ッ蠢縺0x40莉・荳翫↑縺ョ縺ァ蝠城。後↑縺 + if (pCut == NULL) + pCut = pLast; + if ((size_t)(pCut - pFirst) > nMax) + pCut = pFirst + nMax; // 蠕後⊇縺ゥSJIS2繝舌う繝亥愛螳/陬懈ュ」繧定。後↑縺 縺薙%縺ァ蛻、螳壹@縺ヲ縺ッ縺縺代↑縺 + + // 諡。蠑オ蟄仙錐蛻、螳 + const BYTE* pSecond = pExt; + const BYTE* p; + for (p = pExt - 1; pStop < p; p--) { + if (*p == '.') + pSecond = p; // SJIS2繝舌う繝育岼縺ッ蠢縺0x40莉・荳翫↑縺ョ縺ァ蝠城。後↑縺 + } + + // 繝吶シ繧ケ蜷阪r遏ュ邵ョ + size_t nExt = pExt - pSecond; // 諡。蠑オ蟄仙錐驛ィ蛻縺ョ髟キ縺 + if ((size_t)(pCut - pFirst) + nExt > nMax) + pCut = pFirst + nMax - nExt; + // 2繝舌う繝域枚蟄励ョ騾比クュ縺ェ繧峨&繧峨↓遏ュ邵ョ + for (p = pFirst; p < pCut; p++) { + BYTE c = *p; + if ((0x80 <= c && c <= 0x9F) || 0xE0 <= c) { // 蜴ウ蟇縺ォ縺ッ 0x81ス0x9F 0xE0ス0xEF + p++; + if (p >= pCut) { + pCut--; + break; + } + } + } + + // 蜷榊燕縺ョ邨仙粋 + BYTE* pWrite = m_szHuman; + pWrite = CopyName(pWrite, pFirst, pCut); // 繝吶シ繧ケ蜷阪r霆「騾 + if (pNumber) + pWrite = CopyName(pWrite, pNumber, &szNumber[8]); // 陬懈ュ」譁蟄励r霆「騾 + pWrite = CopyName(pWrite, pSecond, pExt); // 諡。蠑オ蟄仙錐繧定サ「騾 + m_pszHumanExt = pWrite; // 諡。蠑オ蟄蝉ス咲スョ菫晏ュ + pWrite = CopyName(pWrite, pExt, pLast); // Human68k諡。蠑オ蟄舌r霆「騾 + m_pszHumanLast = pWrite; // 邨らォッ菴咲スョ菫晏ュ + *pWrite = '\0'; + + // 螟画鋤邨先棡縺ョ遒コ隱 + m_bCorrect = TRUE; + + // 繝輔ぃ繧、繝ォ蜷肴悽菴薙′蟄伜惠縺励↑縺代l縺ー荳榊粋譬シ + if (m_pszHumanExt <= m_szHuman) + m_bCorrect = FALSE; + + // 繝輔ぃ繧、繝ォ蜷肴悽菴薙′1譁蟄嶺サ・荳翫〒縺九▽遨コ逋ス縺ァ邨ゆコ縺励※縺繧後ー荳榊粋譬シ + // 繝輔ぃ繧、繝ォ蜷肴悽菴薙′8譁蟄嶺サ・荳翫ョ蝣エ蜷医∫炊隲紋ク翫ッ遨コ逋ス縺ァ縺ョ邨ゆコ縺瑚。ィ迴セ蜿ッ + // 閭ス縺縺後?uman68k縺ァ縺ッ豁」縺励¥謇ア縺医↑縺縺溘a縲√%繧後b荳榊粋譬シ縺ィ縺吶k + else if (m_pszHumanExt[-1] == ' ') + m_bCorrect = FALSE; + + // 螟画鋤邨先棡縺檎音谿翫ョ繧」繝ャ繧ッ繝医Μ蜷阪→蜷後§縺ェ繧我ク榊粋譬シ + if (m_szHuman[0] == '.' && + (m_szHuman[1] == '\0' || (m_szHuman[1] == '.' && m_szHuman[2] == '\0'))) + m_bCorrect = FALSE; +} + +//--------------------------------------------------------------------------- +// +/// Human68k蛛エ縺ョ蜷咲ァー繧定、陬ス +/// +/// 繝輔ぃ繧、繝ォ蜷埼Κ蛻縺ョ諠蝣ア繧定、陬ス縺励,onvertHuman()逶ク蠖薙ョ蛻晄悄蛹門虚菴懊r陦後↑縺縲 +// +//--------------------------------------------------------------------------- +void CHostFilename::CopyHuman(const BYTE* szHuman) +{ + ASSERT(this); + ASSERT(szHuman); + ASSERT(strlen((const char*)szHuman) < 23); + + strcpy((char*)m_szHuman, (const char*)szHuman); + m_bCorrect = TRUE; + m_pszHumanLast = m_szHuman + strlen((const char*)m_szHuman); + m_pszHumanExt = (BYTE*)SeparateExt(m_szHuman); +} + +//--------------------------------------------------------------------------- +// +/// Human68k繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ繧定ィュ螳 +/// +/// ConvertHuman()縺ァ險ュ螳壽ク医∩縺ョ繝輔ぃ繧、繝ォ蜷阪r繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ縺ォ蜿肴丐縺吶k縲 +// +//--------------------------------------------------------------------------- +void CHostFilename::SetEntryName() +{ + ASSERT(this); + + // 繝輔ぃ繧、繝ォ蜷崎ィュ螳 + BYTE* p = m_szHuman; + size_t i; + for (i = 0; i < 8; i++) { + if (p < m_pszHumanExt) + m_dirHuman.name[i] = *p++; + else + m_dirHuman.name[i] = ' '; + } + + for (i = 0; i < 10; i++) { + if (p < m_pszHumanExt) + m_dirHuman.add[i] = *p++; + else + m_dirHuman.add[i] = '\0'; + } + + if (*p == '.') + p++; + for (i = 0; i < 3; i++) { + BYTE c = *p; + if (c) + p++; + m_dirHuman.ext[i] = c; + } +} + +//--------------------------------------------------------------------------- +// +/// Human68k蛛エ縺ョ蜷咲ァー縺悟刈蟾・縺輔l縺溘°隱ソ譟サ +// +//--------------------------------------------------------------------------- +BOOL CHostFilename::isReduce() const +{ + ASSERT(this); + + return strcmp((LPTSTR)m_szHost, (const char*)m_szHuman) != 0; /// @warning Unicode譎りヲ∽ソョ豁」 竊 貂 +} + +//--------------------------------------------------------------------------- +// +/// Human68k繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ縺ョ螻樊ァ蛻、螳 +// +//--------------------------------------------------------------------------- +BOOL CHostFilename::CheckAttribute(DWORD nHumanAttribute) const +{ + ASSERT(this); + + BYTE nAttribute = m_dirHuman.attr; + if ((nAttribute & (Human68k::AT_ARCHIVE | Human68k::AT_DIRECTORY | Human68k::AT_VOLUME)) == 0) + nAttribute |= Human68k::AT_ARCHIVE; + + return nAttribute & nHumanAttribute; +} + +//--------------------------------------------------------------------------- +// +/// Human68k繝輔ぃ繧、繝ォ蜷阪°繧画僑蠑オ蟄舌r蛻髮「 +// +//--------------------------------------------------------------------------- +const BYTE* CHostFilename::SeparateExt(const BYTE* szHuman) // static +{ + // 繝輔ぃ繧、繝ォ蜷阪ョ髟キ縺輔r迯イ蠕 + size_t nLength = strlen((const char*)szHuman); + const BYTE* pFirst = szHuman; + const BYTE* pLast = pFirst + nLength; + + // Human68k諡。蠑オ蟄舌ョ菴咲スョ繧堤「コ隱 + const BYTE* pExt = (BYTE*)strrchr((const char*)pFirst, '.'); // SJIS2繝舌う繝育岼縺ッ蠢縺0x40莉・荳翫↑縺ョ縺ァ蝠城。後↑縺 + if (pExt == NULL) + pExt = pLast; + // 繝輔ぃ繧、繝ォ蜷阪′20ス22譁蟄励°縺、19譁蟄礼岼縺'.'縺九▽'.'縺ァ邨ゆコ縺ィ縺縺繝代ち繝シ繝ウ繧堤音蛻・謇ア縺縺吶k + if (20 <= nLength && nLength <= 22 && pFirst[18] == '.' && pFirst[nLength - 1] == '.') + pExt = pFirst + 18; + // 諡。蠑オ蟄舌ョ譁蟄玲焚繧定ィ育ョ (-1:縺ェ縺 0:繝斐Μ繧ェ繝峨□縺 1ス3:Human68k諡。蠑オ蟄 4莉・荳:諡。蠑オ蟄仙錐) + size_t nExt = pLast - pExt - 1; + // '.' 縺梧枚蟄怜怜磯ュ莉・螟悶↓蟄伜惠縺励※縲√°縺、1ス3譁蟄励ョ蝣エ蜷医ョ縺ソ諡。蠑オ蟄舌→縺ソ縺ェ縺 + if (pExt == pFirst || nExt < 1 || nExt > 3) + pExt = pLast; + + return pExt; +} + +//=========================================================================== +// +// 繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ 繝代せ蜷 +// +//=========================================================================== + +DWORD CHostPath::g_nId; ///< 隴伜挨ID逕滓千畑繧ォ繧ヲ繝ウ繧ソ + +//--------------------------------------------------------------------------- +// +/// 繝繝輔か繝ォ繝医さ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +CHostPath::CHostPath() +{ + m_bRefresh = TRUE; + +#ifdef _DEBUG + // 蠢縺壼、縺梧峩譁ー縺輔l繧九ョ縺ァ蛻晄悄蛹紋ク崎ヲ (繝繝舌ャ繧ー譎ゅョ蛻晄悄蜍穂ス懃「コ隱咲畑) + m_nId = 0; +#endif // _DEBUG +} + +//--------------------------------------------------------------------------- +// +/// 繝繧ケ繝医Λ繧ッ繧ソ final +// +//--------------------------------------------------------------------------- +CHostPath::~CHostPath() +{ + Clean(); +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ蜷埼伜沺遒コ菫 +/// +/// 縺サ縺ィ繧薙←縺ョ繧ア繝シ繧ケ縺ァ縺ッ縲√帙せ繝亥エ繝輔ぃ繧、繝ォ蜷阪ョ髟キ縺輔ッ繝舌ャ繝輔ぃ譛螟ァ髟キ縺ォ +/// 豈斐∋縺ヲ髱槫クク縺ォ遏ュ縺縲ゅ&繧峨↓繝輔ぃ繧、繝ォ蜷阪ッ螟ァ驥上↓逕滓舌&繧後k蜿ッ閭ス諤ァ縺後≠繧九 +/// 縺昴ョ縺溘a譁蟄玲焚縺ォ蠢懊§縺溷庄螟蛾聞縺ァ遒コ菫昴☆繧九 +// +//--------------------------------------------------------------------------- +CHostPath::ring_t* CHostPath::Alloc(size_t nLength) // static +{ + ASSERT(nLength < FILEPATH_MAX); + + size_t n = offsetof(ring_t, f) + CHostFilename::Offset() + (nLength + 1) * sizeof(TCHAR); + ring_t* p = (ring_t*)malloc(n); + ASSERT(p); + + p->r.Init(); // 讎帛錐縺ッ螟ァ荳亥、ォ縺ァ縺呻シ + + return p; +} + +//--------------------------------------------------------------------------- +// +// 繝輔ぃ繧、繝ォ蜷埼伜沺隗」謾セ +// +//--------------------------------------------------------------------------- +void CHostPath::Free(ring_t* pRing) // static +{ + ASSERT(pRing); + + pRing->~ring_t(); + free(pRing); +} + +//--------------------------------------------------------------------------- +// +/// 蜀榊茜逕ィ縺ョ縺溘a縺ョ蛻晄悄蛹 +// +//--------------------------------------------------------------------------- +void CHostPath::Clean() +{ + ASSERT(this); + + Release(); + + // 蜈ィ繝輔ぃ繧、繝ォ蜷阪r隗」謾セ + ring_t* p; + while ((p = (ring_t*)m_cRing.Next()) != (ring_t*)&m_cRing) { + Free(p); + } +} + +//--------------------------------------------------------------------------- +// +/// Human68k蛛エ縺ョ蜷咲ァー繧堤峩謗・謖螳壹☆繧 +// +//--------------------------------------------------------------------------- +void CHostPath::SetHuman(const BYTE* szHuman) +{ + ASSERT(this); + ASSERT(szHuman); + ASSERT(strlen((const char*)szHuman) < HUMAN68K_PATH_MAX); + + strcpy((char*)m_szHuman, (const char*)szHuman); +} + +//--------------------------------------------------------------------------- +// +/// 繝帙せ繝亥エ縺ョ蜷咲ァー繧堤峩謗・謖螳壹☆繧 +// +//--------------------------------------------------------------------------- +void CHostPath::SetHost(const TCHAR* szHost) +{ + ASSERT(this); + ASSERT(szHost); + ASSERT(strlen(szHost) < FILEPATH_MAX); + + strcpy(m_szHost, szHost); +} + +//--------------------------------------------------------------------------- +// +/// 譁蟄怜玲ッ碑シ (繝ッ繧、繝ォ繝峨き繝シ繝牙ッセ蠢) +// +//--------------------------------------------------------------------------- +int CHostPath::Compare(const BYTE* pFirst, const BYTE* pLast, const BYTE* pBufFirst, const BYTE* pBufLast) +{ + ASSERT(pFirst); + ASSERT(pLast); + ASSERT(pBufFirst); + ASSERT(pBufLast); + + // 譁蟄玲ッ碑シ + BOOL bSkip0 = FALSE; + BOOL bSkip1 = FALSE; + for (const BYTE* p = pFirst; p < pLast; p++) { + // 1譁蟄苓ェュ縺ソ霎シ縺ソ + BYTE c = *p; + BYTE d = '\0'; + if (pBufFirst < pBufLast) + d = *pBufFirst++; + + // 豈碑シ縺ョ縺溘a縺ョ譁蟄苓」懈ュ」 + if (bSkip0 == FALSE) { + if (bSkip1 == FALSE) { // c繧E繧1繝舌う繝育岼 + if ((0x80 <= c && c <= 0x9F) || 0xE0 <= c) { // 蜴ウ蟇縺ォ縺ッ 0x81ス0x9F 0xE0ス0xEF + bSkip0 = TRUE; + } + if ((0x80 <= d && d <= 0x9F) || 0xE0 <= d) { // 蜴ウ蟇縺ォ縺ッ 0x81ス0x9F 0xE0ス0xEF + bSkip1 = TRUE; + } + if (c == d) + continue; // 鬮倡「コ邇縺ァ蛻、螳壼ョ御コ縺吶k + if ((CFileSys::GetFileOption() & WINDRV_OPT_ALPHABET) == 0) { + if ('A' <= c && c <= 'Z') + c += 'a' - 'A'; // 蟆乗枚蟄怜喧 + if ('A' <= d && d <= 'Z') + d += 'a' - 'A'; // 蟆乗枚蟄怜喧 + } + } else { // c縺縺代′1繝舌う繝育岼 + if ((0x80 <= c && c <= 0x9F) || 0xE0 <= c) { // 蜴ウ蟇縺ォ縺ッ 0x81ス0x9F 0xE0ス0xEF + bSkip0 = TRUE; + } + bSkip1 = FALSE; + } + } else { + if (bSkip1 == FALSE) { // d縺縺代′1繝舌う繝育岼 + bSkip0 = FALSE; + if ((0x80 <= d && d <= 0x9F) || 0xE0 <= d) { // 蜴ウ蟇縺ォ縺ッ 0x81ス0x9F 0xE0ス0xEF + bSkip1 = TRUE; + } + } else { // c繧E繧2繝舌う繝育岼 + bSkip0 = FALSE; + bSkip1 = FALSE; + } + } + + // 豈碑シ + if (c == d) + continue; + if (c == '?') + continue; + return 1; + } + if (pBufFirst < pBufLast) + return 2; + + return 0; +} + +//--------------------------------------------------------------------------- +// +/// Human68k蛛エ縺ョ蜷咲ァー繧呈ッ碑シ縺吶k +// +//--------------------------------------------------------------------------- +BOOL CHostPath::isSameHuman(const BYTE* szHuman) const +{ + ASSERT(this); + ASSERT(szHuman); + + // 譁蟄玲焚險育ョ + size_t nLength = strlen((const char*)m_szHuman); + size_t n = strlen((const char*)szHuman); + + // 譁蟄玲焚繝√ぉ繝繧ッ + if (nLength != n) + return FALSE; + + // Human68k繝代せ蜷阪ョ豈碑シ + return Compare(m_szHuman, m_szHuman + nLength, szHuman, szHuman + n) == 0; +} + +//--------------------------------------------------------------------------- +// +/// Human68k蛛エ縺ョ蜷咲ァー繧呈ッ碑シ縺吶k +// +//--------------------------------------------------------------------------- +BOOL CHostPath::isSameChild(const BYTE* szHuman) const +{ + ASSERT(this); + ASSERT(szHuman); + + // 譁蟄玲焚險育ョ + size_t nLength = strlen((const char*)m_szHuman); + size_t n = strlen((const char*)szHuman); + + // 譁蟄玲焚繝√ぉ繝繧ッ + if (nLength < n) + return FALSE; + + // Human68k繝代せ蜷阪ョ豈碑シ + return Compare(m_szHuman, m_szHuman + n, szHuman, szHuman + n) == 0; +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ蜷阪r讀懃エ「 +/// +/// 謇譛峨☆繧九く繝」繧キ繝・繝舌ャ繝輔ぃ縺ョ荳ュ縺九i讀懃エ「縺励∬ヲ九▽縺九l縺ー縺昴ョ蜷咲ァー繧定ソ斐☆縲 +/// 繝代せ蜷阪r髯、螟悶@縺ヲ縺翫¥縺薙→縲 +/// 蠢縺壻ク贋ス阪〒謗剃サ門宛蠕。繧定。後↑縺縺薙→縲 +// +//--------------------------------------------------------------------------- +const CHostFilename* CHostPath::FindFilename(const BYTE* szHuman, DWORD nHumanAttribute) const +{ + ASSERT(this); + ASSERT(szHuman); + + // 譁蟄玲焚險育ョ + const BYTE* pFirst = szHuman; + size_t nLength = strlen((const char*)pFirst); + const BYTE* pLast = pFirst + nLength; + + // 謇謖√@縺ヲ縺繧句ィ縺ヲ縺ョ繝輔ぃ繧、繝ォ蜷阪ョ荳ュ縺九i螳悟ィ荳閾エ縺吶k繧ゅョ繧呈、懃エ「 + const ring_t* p = (ring_t*)m_cRing.Next(); + for (; p != (ring_t*)&m_cRing; p = (ring_t*)p->r.Next()) { + // 螻樊ァ繝√ぉ繝繧ッ + if (p->f.CheckAttribute(nHumanAttribute) == 0) + continue; + // 譁蟄玲焚險育ョ + const BYTE* pBufFirst = p->f.GetHuman(); + const BYTE* pBufLast = p->f.GetHumanLast(); + size_t nBufLength = pBufLast - pBufFirst; + // 譁蟄玲焚繝√ぉ繝繧ッ + if (nLength != nBufLength) + continue; + // 繝輔ぃ繧、繝ォ蜷阪メ繧ァ繝繧ッ + if (Compare(pFirst, pLast, pBufFirst, pBufLast) == 0) + return &p->f; + } + + return NULL; +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ蜷阪r讀懃エ「 (繝ッ繧、繝ォ繝峨き繝シ繝牙ッセ蠢) +/// +/// 謇譛峨☆繧九ヰ繝繝輔ぃ縺ョ荳ュ縺九i讀懃エ「縺励∬ヲ九▽縺九l縺ー縺昴ョ蜷咲ァー繧定ソ斐☆縲 +/// 繝代せ蜷阪r髯、螟悶@縺ヲ縺翫¥縺薙→縲 +/// 蠢縺壻ク贋ス阪〒謗剃サ門宛蠕。繧定。後↑縺縺薙→縲 +// +//--------------------------------------------------------------------------- +const CHostFilename* CHostPath::FindFilenameWildcard(const BYTE* szHuman, DWORD nHumanAttribute, find_t* pFind) const +{ + ASSERT(this); + ASSERT(szHuman); + ASSERT(pFind); + + // 讀懃エ「繝輔ぃ繧、繝ォ蜷阪r譛ャ菴薙→Human68k諡。蠑オ蟄舌↓蛻縺代k + const BYTE* pFirst = szHuman; + const BYTE* pLast = pFirst + strlen((const char*)pFirst); + const BYTE* pExt = CHostFilename::SeparateExt(pFirst); + + // 髢句ァ句慍轤ケ縺ク遘サ蜍 + const ring_t* p = (ring_t*)m_cRing.Next(); + if (pFind->count > 0) { + if (pFind->id == m_nId) { + // 繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ縺悟酔荳縺ェ繧峨∝燕蝗槭ョ菴咲スョ縺九i蜊ウ邯咏カ + p = pFind->pos; + } else { + // 髢句ァ句慍轤ケ繧偵ョ繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ蜀螳ケ縺九i讀懃エ「縺吶k + DWORD n = 0; + for (;; p = (ring_t*)p->r.Next()) { + if (p == (ring_t*)&m_cRing) { + // 蜷御ク繧ィ繝ウ繝医Μ縺瑚ヲ九▽縺九i縺ェ縺九▲縺溷エ蜷医∝屓謨ー縺九i謗ィ螳 (蠢オ縺ョ縺溘a) + p = (ring_t*)m_cRing.Next(); + n = 0; + for (; p != (ring_t*)&m_cRing; p = (ring_t*)p->r.Next()) { + if (n >= pFind->count) + break; + n++; + } + break; + } + if (p->f.isSameEntry(&pFind->entry)) { + // 蜷御ク繧ィ繝ウ繝医Μ繧堤匱隕 + pFind->count = n; + break; + } + n++; + } + } + } + + // 繝輔ぃ繧、繝ォ讀懃エ「 + for (; p != (ring_t*)&m_cRing; p = (ring_t*)p->r.Next()) { + pFind->count++; + + // 螻樊ァ繝√ぉ繝繧ッ + if (p->f.CheckAttribute(nHumanAttribute) == 0) + continue; + + // 繝輔ぃ繧、繝ォ蜷阪r譛ャ菴薙→Human68k諡。蠑オ蟄舌↓蛻縺代k + const BYTE* pBufFirst = p->f.GetHuman(); + const BYTE* pBufLast = p->f.GetHumanLast(); + const BYTE* pBufExt = p->f.GetHumanExt(); + + // 譛ャ菴捺ッ碑シ + if (Compare(pFirst, pExt, pBufFirst, pBufExt)) + continue; + + // Human68k諡。蠑オ蟄先ッ碑シ + // 諡。蠑オ蟄.???縺ョ蝣エ蜷医ッ縲?uman68k諡。蠑オ蟄舌ョ繝斐Μ繧ェ繝峨↑縺励↓繧ゅ槭ャ繝√&縺帙k + if (strcmp((const char*)pExt, ".???") == 0 || + Compare(pExt, pLast, pBufExt, pBufLast) == 0) { + // 谺。縺ョ蛟呵」懊ョ繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ蜀螳ケ繧定ィ倬鹸 + const ring_t* pNext = (ring_t*)p->r.Next(); + pFind->id = m_nId; + pFind->pos = pNext; + if (pNext != (ring_t*)&m_cRing) + memcpy(&pFind->entry, pNext->f.GetEntry(), sizeof(pFind->entry)); + else + memset(&pFind->entry, 0, sizeof(pFind->entry)); + return &p->f; + } + } + + pFind->id = m_nId; + pFind->pos = p; + memset(&pFind->entry, 0, sizeof(pFind->entry)); + return NULL; +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ螟画峩縺瑚。後↑繧上l縺溘°遒コ隱 +// +//--------------------------------------------------------------------------- +BOOL CHostPath::isRefresh() +{ + ASSERT(this); + + return m_bRefresh; +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ蜀肴ァ区 +/// +/// 縺薙%縺ァ蛻昴a縺ヲ縲√帙せ繝亥エ縺ョ繝輔ぃ繧、繝ォ繧キ繧ケ繝繝縺ョ隕ウ貂ャ縺瑚。後↑繧上l繧九 +/// 蠢縺壻ク贋ス阪〒謗剃サ門宛蠕。繧定。後↑縺縺薙→縲 +// +//--------------------------------------------------------------------------- +void CHostPath::Refresh() +{ + ASSERT(this); + ASSERT(strlen(m_szHost) + 22 < FILEPATH_MAX); + + // 繧ソ繧、繝繧ケ繧ソ繝ウ繝嶺ソ晏ュ + Backup(); + + TCHAR szPath[FILEPATH_MAX]; + strcpy(szPath, m_szHost); + + // 譖エ譁ー繝輔Λ繧ー螟画峩 + m_bRefresh = FALSE; + + // 莉・蜑阪ョ繧ュ繝」繝繧キ繝・蜀螳ケ繧剃ソ晏ュ + CRing cRingBackup; + m_cRing.InsertRing(&cRingBackup); + + // 繝輔ぃ繧、繝ォ蜷咲匳骭イ + /// @todo 繝輔ぃ繧、繝ォ驥崎、蜃ヲ逅繧偵帙せ繝亥エAPI繧堤オ檎罰縺帙★縺ォ蜈ィ縺ヲ閾ェ蜑阪〒蜃ヲ逅縺吶k縲 + BOOL bUpdate = FALSE; + DIR* pd = NULL; + for (DWORD i = 0; i < XM6_HOST_DIRENTRY_FILE_MAX; i++) { + TCHAR szFilename[FILEPATH_MAX]; + if (pd == NULL) { + pd = opendir(S2U(szPath)); + if (pd == NULL) + break; + } + // 繝輔ぃ繧、繝ォ蜷阪r迯イ蠕 + struct dirent* pe = readdir(pd); + if (pe == NULL) + break; + strcpy(szFilename, U2S(pe->d_name)); + + // 繝輔ぃ繧、繝ォ蜷埼伜沺遒コ菫 + ring_t* pRing = Alloc(strlen(szFilename)); + CHostFilename* pFilename = &pRing->f; + pFilename->SetHost(szFilename); + + // 莉・蜑阪ョ繧ュ繝」繝繧キ繝・蜀螳ケ縺ォ隧イ蠖薙☆繧九ヵ繧。繧、繝ォ蜷阪′縺ゅl縺ー縺昴ョHuman68k蜷咲ァー繧貞━蜈医☆繧 + ring_t* pCache = (ring_t*)cRingBackup.Next(); + for (;;) { + if (pCache == (ring_t*)&cRingBackup) { + pCache = NULL; // 隧イ蠖薙☆繧九お繝ウ繝医Μ縺ェ縺 + bUpdate = TRUE; // 譁ー隕上お繝ウ繝医Μ縺ィ遒コ螳 + pFilename->ConvertHuman(); + break; + } + if (strcmp(pFilename->GetHost(), pCache->f.GetHost()) == 0) { + pFilename->CopyHuman(pCache->f.GetHuman()); // Human68k蜷咲ァー縺ョ繧ウ繝斐シ + break; + } + pCache = (ring_t*)pCache->r.Next(); + } + + // 譁ー隕上お繝ウ繝医Μ縺ョ蝣エ蜷医ッ繝輔ぃ繧、繝ォ蜷埼崎、繧偵メ繧ァ繝繧ッ縺吶k + // 繝帙せ繝亥エ縺ョ繝輔ぃ繧、繝ォ蜷阪°繧牙、画峩縺後≠縺」縺溘°縲?uman68k縺ァ陦ィ迴セ縺ァ縺阪↑縺繝輔ぃ繧、繝ォ蜷阪ョ蝣エ蜷医ッ + // 莉・荳九ョ繝√ぉ繝繧ッ繧貞ィ縺ヲ繝代せ縺吶k繝輔ぃ繧、繝ォ蜷阪r譁ー縺溘↓逕滓舌☆繧 + // 繝サ豁」縺励>繝輔ぃ繧、繝ォ蜷阪〒縺ゅk縺薙→ + // 繝サ驕主悉縺ョ繧ィ繝ウ繝医Μ縺ォ蜷悟錐縺ョ繧ゅョ縺悟ュ伜惠縺励↑縺縺薙→ + // 繝サ蜷悟錐縺ョ螳溘ヵ繧。繧、繝ォ蜷阪′蟄伜惠縺励↑縺縺薙→ + if (pFilename->isReduce() || !pFilename->isCorrect()) { // 繝輔ぃ繧、繝ォ蜷榊、画峩縺悟ソ隕√°遒コ隱 + for (DWORD n = 0; n < XM6_HOST_FILENAME_PATTERN_MAX; n++) { + // 豁」縺励>繝輔ぃ繧、繝ォ蜷阪°縺ゥ縺縺狗「コ隱 + if (pFilename->isCorrect()) { + // 驕主悉縺ョ繧ィ繝ウ繝医Μ縺ィ荳閾エ縺吶k縺狗「コ隱 + const CHostFilename* pCheck = FindFilename(pFilename->GetHuman()); + if (pCheck == NULL) { + // 荳閾エ縺吶k繧ゅョ縺後↑縺代l縺ー縲∝ョ溘ヵ繧。繧、繝ォ縺悟ュ伜惠縺吶k縺狗「コ隱 + strcpy(szPath, m_szHost); + strcat(szPath, (const char*)pFilename->GetHuman()); /// @warning Unicode譎りヲ∽ソョ豁」 竊 貂 + struct stat sb; + if (stat(S2U(szPath), &sb)) + break; // 蛻ゥ逕ィ蜿ッ閭ス繝代ち繝シ繝ウ繧堤匱隕 + } + } + // 譁ー縺励>蜷榊燕繧堤函謌 + pFilename->ConvertHuman(n); + } + } + + // 繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ蜷咲ァー + pFilename->SetEntryName(); + + // 諠蝣ア蜿門セ + strcpy(szPath, m_szHost); + strcat(szPath, U2S(pe->d_name)); + + struct stat sb; + if (stat(S2U(szPath), &sb)) + continue; + + // 螻樊ァ + BYTE nHumanAttribute = Human68k::AT_ARCHIVE; + if (S_ISDIR(sb.st_mode)) + nHumanAttribute = Human68k::AT_DIRECTORY; + if ((sb.st_mode & 0200) == 0) + nHumanAttribute |= Human68k::AT_READONLY; + pFilename->SetEntryAttribute(nHumanAttribute); + + // 繧オ繧、繧コ + DWORD nHumanSize = (DWORD)sb.st_size; + pFilename->SetEntrySize(nHumanSize); + + // 譌・莉俶凾蛻サ + WORD nHumanDate = 0; + WORD nHumanTime = 0; + struct tm* pt = localtime(&sb.st_mtime); + if (pt) { + nHumanDate = (WORD)(((pt->tm_year - 80) << 9) | ((pt->tm_mon + 1) << 5) | pt->tm_mday); + nHumanTime = (WORD)((pt->tm_hour << 11) | (pt->tm_min << 5) | (pt->tm_sec >> 1)); + } + pFilename->SetEntryDate(nHumanDate); + pFilename->SetEntryTime(nHumanTime); + + // 繧ッ繝ゥ繧ケ繧ソ逡ェ蜿キ險ュ螳 + pFilename->SetEntryCluster(0); + + // 莉・蜑阪ョ繧ュ繝」繝繧キ繝・蜀螳ケ縺ィ豈碑シ + if (pCache) { + if (pCache->f.isSameEntry(pFilename->GetEntry())) { + Free(pRing); // 莉雁屓菴懈舌@縺溘お繝ウ繝医Μ縺ッ遐エ譽縺 + pRing = pCache; // 莉・蜑阪ョ繧ュ繝」繝繧キ繝・蜀螳ケ繧剃スソ縺 + } else { + Free(pCache); // 谺。蝗槭ョ讀懃エ「蟇セ雎。縺九i髯、螟 + bUpdate = TRUE; // 荳閾エ縺励↑縺代l縺ー譖エ譁ー縺ゅj + } + } + + // 繝ェ繝ウ繧ー譛ォ蟆セ縺ク霑ス蜉 + pRing->r.InsertTail(&m_cRing); + } + + closedir(pd); + + // 谿句ュ倥☆繧九く繝」繝繧キ繝・蜀螳ケ繧貞炎髯、 + ring_t* p; + while ((p = (ring_t*)cRingBackup.Next()) != (ring_t*)&cRingBackup) { + bUpdate = TRUE; // 蜑企勁縺ォ繧医▲縺ヲ繧ィ繝ウ繝医Μ謨ー縺ョ貂帛ー代′蛻、譏 + Free(p); + } + + // 譖エ譁ー縺瑚。後↑繧上l縺溘i隴伜挨ID繧貞、画峩 + if (bUpdate) + m_nId = ++g_nId; + // ASSERT(m_nId); +} + +//--------------------------------------------------------------------------- +// +/// 繝帙せ繝亥エ縺ョ繧ソ繧、繝繧ケ繧ソ繝ウ繝励r菫晏ュ +// +//--------------------------------------------------------------------------- +void CHostPath::Backup() +{ + ASSERT(this); + ASSERT(m_szHost); + ASSERT(strlen(m_szHost) < FILEPATH_MAX); + + TCHAR szPath[FILEPATH_MAX]; + strcpy(szPath, m_szHost); + size_t len = strlen(szPath); + + m_tBackup = 0; + if (len > 1) { // 繝ォ繝シ繝医ョ繧」繝ャ繧ッ繝医Μ縺ョ蝣エ蜷医ッ菴輔b縺励↑縺 + len--; + ASSERT(szPath[len] == _T('/')); + szPath[len] = _T('\0'); + struct stat sb; + if (stat(S2U(szPath), &sb) == 0) + m_tBackup = sb.st_mtime; + } +} + +//--------------------------------------------------------------------------- +// +/// 繝帙せ繝亥エ縺ョ繧ソ繧、繝繧ケ繧ソ繝ウ繝励r蠕ゥ蜈 +// +//--------------------------------------------------------------------------- +void CHostPath::Restore() const +{ + ASSERT(this); + ASSERT(m_szHost); + ASSERT(strlen(m_szHost) < FILEPATH_MAX); + + TCHAR szPath[FILEPATH_MAX]; + strcpy(szPath, m_szHost); + size_t len = strlen(szPath); + + if (m_tBackup) { + ASSERT(len); + len--; + ASSERT(szPath[len] == _T('/')); + szPath[len] = _T('\0'); + + struct utimbuf ut; + ut.actime = m_tBackup; + ut.modtime = m_tBackup; + utime(szPath, &ut); + } +} + +//--------------------------------------------------------------------------- +// +/// 譖エ譁ー +// +//--------------------------------------------------------------------------- +void CHostPath::Release() +{ + ASSERT(this); + + m_bRefresh = TRUE; +} + +//=========================================================================== +// +// 繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ邂。逅 +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +/// 繝繝輔か繝ォ繝医さ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +CHostEntry::CHostEntry() +{ + for (size_t n = 0; n < DriveMax; n++) { + m_pDrv[n] = NULL; + } + + m_nTimeout = 0; +} + +//--------------------------------------------------------------------------- +// +/// 繝繧ケ繝医Λ繧ッ繧ソ final +// +//--------------------------------------------------------------------------- +CHostEntry::~CHostEntry() +{ + Clean(); + +#ifdef _DEBUG + // 繧ェ繝悶ず繧ァ繧ッ繝育「コ隱 + for (size_t n = 0; n < DriveMax; n++) { + ASSERT(m_pDrv[n] == NULL); + } +#endif // _DEBUG +} + +//--------------------------------------------------------------------------- +// +/// 蛻晄悄蛹 (繝峨Λ繧、繝千オ霎シ縺ソ譎) +// +//--------------------------------------------------------------------------- +void CHostEntry::Init() +{ + ASSERT(this); + +#ifdef _DEBUG + // 繧ェ繝悶ず繧ァ繧ッ繝育「コ隱 + for (size_t n = 0; n < DriveMax; n++) { + ASSERT(m_pDrv[n] == NULL); + } +#endif // _DEBUG +} + +//--------------------------------------------------------------------------- +// +/// 隗」謾セ (襍キ蜍輔サ繝ェ繧サ繝繝域凾) +// +//--------------------------------------------------------------------------- +void CHostEntry::Clean() +{ + ASSERT(this); + + // 繧ェ繝悶ず繧ァ繧ッ繝亥炎髯、 + for (size_t n = 0; n < DriveMax; n++) { + delete m_pDrv[n]; + m_pDrv[n] = NULL; + } +} + +//--------------------------------------------------------------------------- +// +/// 蜈ィ縺ヲ縺ョ繧ュ繝」繝繧キ繝・繧呈峩譁ー縺吶k +// +//--------------------------------------------------------------------------- +void CHostEntry::CleanCache() +{ + ASSERT(this); + + for (size_t i = 0; i < DriveMax; i++) { + if (m_pDrv[i]) + m_pDrv[i]->CleanCache(); + } + + CHostPath::InitId(); +} + +//--------------------------------------------------------------------------- +// +/// 謖螳壹&繧後◆繝ヲ繝九ャ繝医ョ繧ュ繝」繝繧キ繝・繧呈峩譁ー縺吶k +// +//--------------------------------------------------------------------------- +void CHostEntry::CleanCache(DWORD nUnit) +{ + ASSERT(this); + ASSERT(nUnit < DriveMax); + ASSERT(m_pDrv[nUnit]); + + m_pDrv[nUnit]->CleanCache(); +} + +//--------------------------------------------------------------------------- +// +/// 謖螳壹&繧後◆繝代せ縺ョ繧ュ繝」繝繧キ繝・繧呈峩譁ー縺吶k +// +//--------------------------------------------------------------------------- +void CHostEntry::CleanCache(DWORD nUnit, const BYTE* szHumanPath) +{ + ASSERT(this); + ASSERT(szHumanPath); + ASSERT(nUnit < DriveMax); + ASSERT(m_pDrv[nUnit]); + + m_pDrv[nUnit]->CleanCache(szHumanPath); +} + +//--------------------------------------------------------------------------- +// +/// 謖螳壹&繧後◆繝代せ莉・荳九ョ繧ュ繝」繝繧キ繝・繧貞ィ縺ヲ譖エ譁ー縺吶k +// +//--------------------------------------------------------------------------- +void CHostEntry::CleanCacheChild(DWORD nUnit, const BYTE* szHumanPath) +{ + ASSERT(this); + ASSERT(szHumanPath); + ASSERT(nUnit < DriveMax); + ASSERT(m_pDrv[nUnit]); + + m_pDrv[nUnit]->CleanCacheChild(szHumanPath); +} + +//--------------------------------------------------------------------------- +// +/// 謖螳壹&繧後◆繝代せ縺ョ繧ュ繝」繝繧キ繝・繧貞炎髯、縺吶k +// +//--------------------------------------------------------------------------- +void CHostEntry::DeleteCache(DWORD nUnit, const BYTE* szHumanPath) +{ + ASSERT(this); + ASSERT(szHumanPath); + ASSERT(nUnit < DriveMax); + ASSERT(m_pDrv[nUnit]); + + m_pDrv[nUnit]->DeleteCache(szHumanPath); +} + +//--------------------------------------------------------------------------- +// +/// 繝帙せ繝亥エ縺ョ蜷咲ァー繧呈、懃エ「 (繝代せ蜷+繝輔ぃ繧、繝ォ蜷(逵∫払蜿ッ)+螻樊ァ) +// +//--------------------------------------------------------------------------- +BOOL CHostEntry::Find(DWORD nUnit, CHostFiles* pFiles) +{ + ASSERT(this); + ASSERT(pFiles); + ASSERT(nUnit < DriveMax); + ASSERT(m_pDrv[nUnit]); + + return m_pDrv[nUnit]->Find(pFiles); +} + +void CHostEntry::ShellNotify(DWORD, const TCHAR*) {} + +//--------------------------------------------------------------------------- +// +/// 繝峨Λ繧、繝冶ィュ螳 +// +//--------------------------------------------------------------------------- +void CHostEntry::SetDrv(DWORD nUnit, CHostDrv* pDrv) +{ + ASSERT(this); + ASSERT(nUnit < DriveMax); + ASSERT(m_pDrv[nUnit] == NULL); + + m_pDrv[nUnit] = pDrv; +} + +//--------------------------------------------------------------------------- +// +/// 譖ク縺崎セシ縺ソ遖∵ュ「縺具シ +// +//--------------------------------------------------------------------------- +BOOL CHostEntry::isWriteProtect(DWORD nUnit) const +{ + ASSERT(this); + ASSERT(nUnit < DriveMax); + ASSERT(m_pDrv[nUnit]); + + return m_pDrv[nUnit]->isWriteProtect(); +} + +//--------------------------------------------------------------------------- +// +/// 繧「繧ッ繧サ繧ケ蜿ッ閭ス縺具シ +// +//--------------------------------------------------------------------------- +BOOL CHostEntry::isEnable(DWORD nUnit) const +{ + ASSERT(this); + ASSERT(nUnit < DriveMax); + ASSERT(m_pDrv[nUnit]); + + return m_pDrv[nUnit]->isEnable(); +} + +//--------------------------------------------------------------------------- +// +/// 繝。繝繧」繧「繝√ぉ繝繧ッ +// +//--------------------------------------------------------------------------- +BOOL CHostEntry::isMediaOffline(DWORD nUnit) +{ + ASSERT(this); + ASSERT(nUnit < DriveMax); + ASSERT(m_pDrv[nUnit]); + + return m_pDrv[nUnit]->isMediaOffline(); +} + +//--------------------------------------------------------------------------- +// +/// 繝。繝繧」繧「繝舌う繝医ョ蜿門セ +// +//--------------------------------------------------------------------------- +BYTE CHostEntry::GetMediaByte(DWORD nUnit) const +{ + ASSERT(this); + ASSERT(nUnit < DriveMax); + ASSERT(m_pDrv[nUnit]); + + return m_pDrv[nUnit]->GetMediaByte(); +} + +//--------------------------------------------------------------------------- +// +/// 繝峨Λ繧、繝也憾諷九ョ蜿門セ +// +//--------------------------------------------------------------------------- +DWORD CHostEntry::GetStatus(DWORD nUnit) const +{ + ASSERT(this); + ASSERT(nUnit < DriveMax); + ASSERT(m_pDrv[nUnit]); + + return m_pDrv[nUnit]->GetStatus(); +} + +//--------------------------------------------------------------------------- +// +/// 繝懊Μ繝・繝シ繝繝ゥ繝吶Ν縺ョ蜿門セ +// +//--------------------------------------------------------------------------- +void CHostEntry::GetVolume(DWORD nUnit, TCHAR* szLabel) +{ + ASSERT(this); + ASSERT(nUnit < DriveMax); + ASSERT(m_pDrv[nUnit]); + + m_pDrv[nUnit]->GetVolume(szLabel); +} + +//--------------------------------------------------------------------------- +// +/// 繧ュ繝」繝繧キ繝・縺九i繝懊Μ繝・繝シ繝繝ゥ繝吶Ν繧貞叙蠕 +// +//--------------------------------------------------------------------------- +BOOL CHostEntry::GetVolumeCache(DWORD nUnit, TCHAR* szLabel) const +{ + ASSERT(this); + ASSERT(nUnit < DriveMax); + ASSERT(m_pDrv[nUnit]); + + return m_pDrv[nUnit]->GetVolumeCache(szLabel); +} + +//--------------------------------------------------------------------------- +// +/// 螳ケ驥上ョ蜿門セ +// +//--------------------------------------------------------------------------- +DWORD CHostEntry::GetCapacity(DWORD nUnit, Human68k::capacity_t* pCapacity) +{ + ASSERT(this); + ASSERT(nUnit < DriveMax); + ASSERT(m_pDrv[nUnit]); + + return m_pDrv[nUnit]->GetCapacity(pCapacity); +} + +//--------------------------------------------------------------------------- +// +/// 繧ュ繝」繝繧キ繝・縺九i繧ッ繝ゥ繧ケ繧ソ繧オ繧、繧コ繧貞叙蠕 +// +//--------------------------------------------------------------------------- +BOOL CHostEntry::GetCapacityCache(DWORD nUnit, Human68k::capacity_t* pCapacity) const +{ + ASSERT(this); + ASSERT(nUnit < DriveMax); + ASSERT(m_pDrv[nUnit]); + + return m_pDrv[nUnit]->GetCapacityCache(pCapacity); +} + +//--------------------------------------------------------------------------- +// +/// Human68k繝輔Ν繝代せ蜷阪°繧牙磯ュ縺ョ隕∫エ繧貞髮「繝サ繧ウ繝斐シ +/// +/// Human68k繝輔Ν繝代せ蜷阪ョ蜈磯ュ縺ョ隕∫エ繧偵ヱ繧ケ蛹コ蛻繧頑枚蟄励r髯、螟悶@縺ヲ蜿門セ励☆繧九 +/// 譖ク縺崎セシ縺ソ蜈医ヰ繝繝輔ぃ縺ッ23繝舌う繝亥ソ隕√ +/// Human68k繝代せ縺ッ蠢縺/縺ァ髢句ァ九☆繧九%縺ィ縲 +/// 騾比クュ/縺2縺、莉・荳企」邯壹@縺ヲ蜃コ迴セ縺励◆蝣エ蜷医ッ繧ィ繝ゥ繝シ縺ィ縺吶k縲 +/// 譁蟄怜礼オらォッ縺/縺縺代ョ蝣エ蜷医ッ遨コ縺ョ譁蟄怜励→縺励※蜃ヲ逅縺励√お繝ゥ繝シ縺ォ縺ッ縺励↑縺縲 +// +//--------------------------------------------------------------------------- +const BYTE* CHostDrv::SeparateCopyFilename(const BYTE* szHuman, BYTE* szBuffer) // static +{ + ASSERT(szHuman); + ASSERT(szBuffer); + + const size_t nMax = 22; + const BYTE* p = szHuman; + + BYTE c = *p++; // 隱ュ縺ソ霎シ縺ソ + if (c != '/' && c != '\\') + return NULL; // 繧ィ繝ゥ繝シ: 荳肴ュ」縺ェ繝代せ蜷 + + // 繝輔ぃ繧、繝ォ縺縺」縺薙>繧後k + size_t i = 0; + for (;;) { + c = *p; // 隱ュ縺ソ霎シ縺ソ + if (c == '\0') + break; // 譁蟄怜礼オらォッ縺ェ繧臥オゆコ (邨らォッ菴咲スョ繧定ソ斐☆) + if (c == '/' || c == '\\') { + if (i == 0) + return NULL; // 繧ィ繝ゥ繝シ: 繝代せ蛹コ蛻繧頑枚蟄励′騾」邯壹@縺ヲ縺繧 + break; // 繝代せ縺ョ蛹コ蛻繧翫r隱ュ繧薙□繧臥オゆコ (譁蟄励ョ菴咲スョ繧定ソ斐☆) + } + p++; + + if (i >= nMax) + return NULL; // 繧ィ繝ゥ繝シ: 1繝舌う繝育岼縺後ヰ繝繝輔ぃ邨らォッ縺ォ縺九°繧 + szBuffer[i++] = c; // 譖ク縺崎セシ縺ソ + + if ((0x80 <= c && c <= 0x9F) || 0xE0 <= c) { // 蜴ウ蟇縺ォ縺ッ0x81ス0x9F縺ィ0xE0ス0xEF + c = *p++; // 隱ュ縺ソ霎シ縺ソ + if (c < 0x40) + return NULL; // 繧ィ繝ゥ繝シ: 荳肴ュ」縺ェSJIS2繝舌う繝育岼 + + if (i >= nMax) + return NULL; // 繧ィ繝ゥ繝シ: 2繝舌う繝育岼縺後ヰ繝繝輔ぃ邨らォッ縺ォ縺九°繧 + szBuffer[i++] = c; // 譖ク縺崎セシ縺ソ + } + } + szBuffer[i] = '\0'; // 譖ク縺崎セシ縺ソ + + return p; +} + +//=========================================================================== +// +// 繝輔ぃ繧、繝ォ讀懃エ「蜃ヲ逅 +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +/// 蛻晄悄蛹 +// +//--------------------------------------------------------------------------- +void CHostFiles::Init() +{ + ASSERT(this); +} + +//--------------------------------------------------------------------------- +// +/// 繝代せ蜷阪サ繝輔ぃ繧、繝ォ蜷阪r蜀驛ィ縺ァ逕滓 +// +//--------------------------------------------------------------------------- +void CHostFiles::SetPath(const Human68k::namests_t* pNamests) +{ + ASSERT(this); + ASSERT(pNamests); + + pNamests->GetCopyPath(m_szHumanPath); + pNamests->GetCopyFilename(m_szHumanFilename); + m_nHumanWildcard = 0; + m_nHumanAttribute = Human68k::AT_ARCHIVE; + m_findNext.Clear(); +} + +//--------------------------------------------------------------------------- +// +/// Human68k蛛エ縺ァ繝輔ぃ繧、繝ォ繧呈、懃エ「縺励帙せ繝亥エ縺ョ諠蝣ア繧堤函謌 +// +//--------------------------------------------------------------------------- +BOOL CHostFiles::Find(DWORD nUnit, CHostEntry* pEntry) +{ + ASSERT(this); + ASSERT(pEntry); + + return pEntry->Find(nUnit, this); +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ蜷肴、懃エ「 +// +//--------------------------------------------------------------------------- +const CHostFilename* CHostFiles::Find(CHostPath* pPath) +{ + ASSERT(this); + ASSERT(pPath); + + if (m_nHumanWildcard) + return pPath->FindFilenameWildcard(m_szHumanFilename, m_nHumanAttribute, &m_findNext); + + return pPath->FindFilename(m_szHumanFilename, m_nHumanAttribute); +} + +//--------------------------------------------------------------------------- +// +/// Human68k蛛エ縺ョ讀懃エ「邨先棡菫晏ュ +// +//--------------------------------------------------------------------------- +void CHostFiles::SetEntry(const CHostFilename* pFilename) +{ + ASSERT(this); + ASSERT(pFilename); + + // Human68k繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ菫晏ュ + memcpy(&m_dirHuman, pFilename->GetEntry(), sizeof(m_dirHuman)); + + // Human68k繝輔ぃ繧、繝ォ蜷堺ソ晏ュ + strcpy((char*)m_szHumanResult, (const char*)pFilename->GetHuman()); +} + +//--------------------------------------------------------------------------- +// +/// 繝帙せ繝亥エ縺ョ蜷咲ァー繧定ィュ螳 +// +//--------------------------------------------------------------------------- +void CHostFiles::SetResult(const TCHAR* szPath) +{ + ASSERT(this); + ASSERT(szPath); + ASSERT(strlen(szPath) < FILEPATH_MAX); + + strcpy(m_szHostResult, szPath); +} + +//--------------------------------------------------------------------------- +// +/// 繝帙せ繝亥エ縺ョ蜷咲ァー縺ォ繝輔ぃ繧、繝ォ蜷阪r霑ス蜉 +// +//--------------------------------------------------------------------------- +void CHostFiles::AddResult(const TCHAR* szPath) +{ + ASSERT(this); + ASSERT(szPath); + ASSERT(strlen(m_szHostResult) + strlen(szPath) < FILEPATH_MAX); + + strcat(m_szHostResult, szPath); +} + +//--------------------------------------------------------------------------- +// +/// 繝帙せ繝亥エ縺ョ蜷咲ァー縺ォHuman68k縺ョ譁ー隕上ヵ繧。繧、繝ォ蜷阪r霑ス蜉 +// +//--------------------------------------------------------------------------- +void CHostFiles::AddFilename() +{ + ASSERT(this); + ASSERT(strlen(m_szHostResult) + strlen((const char*)m_szHumanFilename) < FILEPATH_MAX); + + /// @warning Unicode譛ェ蟇セ蠢懊ゅ>縺壹lUnicode縺ョ荳也阜縺ォ鬟ョ縺セ繧後◆譎ゅッ縺薙%縺ァ螟画鋤繧定。後↑縺 竊 貂 + strcat(m_szHostResult, (const char*)m_szHumanFilename); +} + +//=========================================================================== +// +// 繝輔ぃ繧、繝ォ讀懃エ「鬆伜沺 繝槭ロ繝シ繧ク繝」 +// +//=========================================================================== + +#ifdef _DEBUG +//--------------------------------------------------------------------------- +// +/// 繝繧ケ繝医Λ繧ッ繧ソ final +// +//--------------------------------------------------------------------------- +CHostFilesManager::~CHostFilesManager() +{ + // 螳滉ス薙′蟄伜惠縺励↑縺縺薙→繧堤「コ隱 (蠢オ縺ョ縺溘a) + ASSERT(m_cRing.Next() == &m_cRing); + ASSERT(m_cRing.Prev() == &m_cRing); +} +#endif // _DEBUG + +//--------------------------------------------------------------------------- +// +/// 蛻晄悄蛹 (繝峨Λ繧、繝千オ霎シ縺ソ譎) +// +//--------------------------------------------------------------------------- +void CHostFilesManager::Init() +{ + ASSERT(this); + + // 螳滉ス薙′蟄伜惠縺励↑縺縺薙→繧堤「コ隱 (蠢オ縺ョ縺溘a) + ASSERT(m_cRing.Next() == &m_cRing); + ASSERT(m_cRing.Prev() == &m_cRing); + + // 繝。繝「繝ェ遒コ菫 + for (DWORD i = 0; i < XM6_HOST_FILES_MAX; i++) { + ring_t* p = new ring_t; + ASSERT(p); + p->r.Insert(&m_cRing); + } +} + +//--------------------------------------------------------------------------- +// +/// 隗」謾セ (襍キ蜍輔サ繝ェ繧サ繝繝域凾) +// +//--------------------------------------------------------------------------- +void CHostFilesManager::Clean() +{ + ASSERT(this); + + // 繝。繝「繝ェ隗」謾セ + CRing* p; + while ((p = m_cRing.Next()) != &m_cRing) { + delete (ring_t*)p; + } +} + +//--------------------------------------------------------------------------- +// +/// 遒コ菫 +// +//--------------------------------------------------------------------------- +CHostFiles* CHostFilesManager::Alloc(DWORD nKey) +{ + ASSERT(this); + ASSERT(nKey); + + // 譛ォ蟆セ縺九i驕ク謚 + ring_t* p = (ring_t*)m_cRing.Prev(); + + // 繝ェ繝ウ繧ー蜈磯ュ縺ク遘サ蜍 + p->r.Insert(&m_cRing); + + // 繧ュ繝シ繧定ィュ螳 + p->f.SetKey(nKey); + + return &p->f; +} + +//--------------------------------------------------------------------------- +// +/// 讀懃エ「 +// +//--------------------------------------------------------------------------- +CHostFiles* CHostFilesManager::Search(DWORD nKey) +{ + ASSERT(this); + // ASSERT(nKey); // DPB遐エ謳阪↓繧医j讀懃エ「繧ュ繝シ縺0縺ォ縺ェ繧九%縺ィ繧ゅ≠繧 + + // 隧イ蠖薙☆繧九が繝悶ず繧ァ繧ッ繝医r讀懃エ「 + ring_t* p = (ring_t*)m_cRing.Next(); + for (; p != (ring_t*)&m_cRing; p = (ring_t*)p->r.Next()) { + if (p->f.isSameKey(nKey)) { + // 繝ェ繝ウ繧ー蜈磯ュ縺ク遘サ蜍 + p->r.Insert(&m_cRing); + return &p->f; + } + } + + return NULL; +} + +//--------------------------------------------------------------------------- +// +/// 隗」謾セ +// +//--------------------------------------------------------------------------- +void CHostFilesManager::Free(CHostFiles* pFiles) +{ + ASSERT(this); + ASSERT(pFiles); + + // 隗」謾セ + pFiles->SetKey(0); + pFiles->Init(); + + // 繝ェ繝ウ繧ー譛ォ蟆セ縺ク遘サ蜍 + ring_t* p = (ring_t*)((size_t)pFiles - offsetof(ring_t, f)); + p->r.InsertTail(&m_cRing); +} + +//=========================================================================== +// +// FCB蜃ヲ逅 +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +/// 蛻晄悄蛹 +// +//--------------------------------------------------------------------------- +void CHostFcb::Init() +{ + ASSERT(this); + + m_bUpdate = FALSE; + m_pFile = NULL; +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ繧ェ繝シ繝励Φ繝「繝シ繝峨r險ュ螳 +// +//--------------------------------------------------------------------------- +BOOL CHostFcb::SetMode(DWORD nHumanMode) +{ + ASSERT(this); + + switch (nHumanMode & Human68k::OP_MASK) { + case Human68k::OP_READ: + m_pszMode = "rb"; + break; + case Human68k::OP_WRITE: + m_pszMode = "wb"; + break; + case Human68k::OP_FULL: + m_pszMode = "r+b"; + break; + default: + return FALSE; + } + + m_bFlag = (nHumanMode & Human68k::OP_SPECIAL) != 0; + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ蜷阪r險ュ螳 +// +//--------------------------------------------------------------------------- +void CHostFcb::SetFilename(const TCHAR* szFilename) +{ + ASSERT(this); + ASSERT(szFilename); + ASSERT(strlen(szFilename) < FILEPATH_MAX); + + strcpy(m_szFilename, szFilename); +} + +//--------------------------------------------------------------------------- +// +/// Human68k繝代せ蜷阪r險ュ螳 +// +//--------------------------------------------------------------------------- +void CHostFcb::SetHumanPath(const BYTE* szHumanPath) +{ + ASSERT(this); + ASSERT(szHumanPath); + ASSERT(strlen((const char*)szHumanPath) < HUMAN68K_PATH_MAX); + + strcpy((char*)m_szHumanPath, (const char*)szHumanPath); +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ菴懈 +/// +/// 繧ィ繝ゥ繝シ縺ョ譎ゅッFALSE繧定ソ斐☆縲 +// +//--------------------------------------------------------------------------- +BOOL CHostFcb::Create(DWORD nHumanAttribute, BOOL bForce) +{ + ASSERT(this); + ASSERT((nHumanAttribute & (Human68k::AT_DIRECTORY | Human68k::AT_VOLUME)) == 0); + ASSERT(strlen(m_szFilename) > 0); + ASSERT(m_pFile == NULL); + + // 驥崎、繝√ぉ繝繧ッ + if (bForce == FALSE) { + struct stat sb; + if (stat(S2U(m_szFilename), &sb) == 0) + return FALSE; + } + + // 繝輔ぃ繧、繝ォ菴懈 + m_pFile = fopen(S2U(m_szFilename), "w+b"); /// @warning 逅諠ウ蜍穂ス懊ッ螻樊ァ縺斐→荳頑嶌縺 + + return m_pFile != NULL; +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ繧ェ繝シ繝励Φ +/// +/// 繧ィ繝ゥ繝シ縺ョ譎ゅッFALSE繧定ソ斐☆縲 +// +//--------------------------------------------------------------------------- +BOOL CHostFcb::Open() +{ + struct stat st; + + ASSERT(this); + ASSERT(strlen(m_szFilename) > 0); + + // 繝繧」繝ャ繧ッ繝医Μ縺ェ繧牙、ア謨 + if (stat(S2U(m_szFilename), &st) == 0) { + if ((st.st_mode & S_IFMT) == S_IFDIR) { + return FALSE || m_bFlag; + } + } + + // 繝輔ぃ繧、繝ォ繧ェ繝シ繝励Φ + if (m_pFile == NULL) + m_pFile = fopen(S2U(m_szFilename), m_pszMode); + + return m_pFile != NULL || m_bFlag; +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ繧キ繝シ繧ッ +/// +/// 繧ィ繝ゥ繝シ縺ョ譎ゅッFALSE繧定ソ斐☆縲 +// +//--------------------------------------------------------------------------- +BOOL CHostFcb::Rewind(DWORD nOffset) +{ + ASSERT(this); + ASSERT(m_pFile); + + if (fseek(m_pFile, nOffset, SEEK_SET)) + return FALSE; + + return ftell(m_pFile) != -1L; +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ隱ュ縺ソ霎シ縺ソ +/// +/// 0繝舌う繝郁ェュ縺ソ霎シ縺ソ縺ァ繧よュ」蟶ク蜍穂ス懊→縺吶k縲 +/// 繧ィ繝ゥ繝シ縺ョ譎ゅッ-1繧定ソ斐☆縲 +// +//--------------------------------------------------------------------------- +DWORD CHostFcb::Read(BYTE* pBuffer, DWORD nSize) +{ + ASSERT(this); + ASSERT(pBuffer); + ASSERT(m_pFile); + + size_t nResult = fread(pBuffer, sizeof(BYTE), nSize, m_pFile); + if (ferror(m_pFile)) + nResult = (size_t)-1; + + return (DWORD)nResult; +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ譖ク縺崎セシ縺ソ +/// +/// 0繝舌う繝域嶌縺崎セシ縺ソ縺ァ繧よュ」蟶ク蜍穂ス懊→縺吶k縲 +/// 繧ィ繝ゥ繝シ縺ョ譎ゅッ-1繧定ソ斐☆縲 +// +//--------------------------------------------------------------------------- +DWORD CHostFcb::Write(const BYTE* pBuffer, DWORD nSize) +{ + ASSERT(this); + ASSERT(pBuffer); + ASSERT(m_pFile); + + size_t nResult = fwrite(pBuffer, sizeof(BYTE), nSize, m_pFile); + if (ferror(m_pFile)) + nResult = (size_t)-1; + + return (DWORD)nResult; +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ蛻繧願ゥー繧 +/// +/// 繧ィ繝ゥ繝シ縺ョ譎ゅッFALSE繧定ソ斐☆縲 +// +//--------------------------------------------------------------------------- +BOOL CHostFcb::Truncate() +{ + ASSERT(this); + ASSERT(m_pFile); + + return ftruncate(fileno(m_pFile), ftell(m_pFile)) == 0; +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ繧キ繝シ繧ッ +/// +/// 繧ィ繝ゥ繝シ縺ョ譎ゅッ-1繧定ソ斐☆縲 +// +//--------------------------------------------------------------------------- +DWORD CHostFcb::Seek(DWORD nOffset, DWORD nHumanSeek) +{ + ASSERT(this); + ASSERT(nHumanSeek == Human68k::SK_BEGIN || + nHumanSeek == Human68k::SK_CURRENT || nHumanSeek == Human68k::SK_END); + ASSERT(m_pFile); + + int nSeek; + switch (nHumanSeek) { + case Human68k::SK_BEGIN: + nSeek = SEEK_SET; + break; + case Human68k::SK_CURRENT: + nSeek = SEEK_CUR; + break; + // case SK_END: + default: + nSeek = SEEK_END; + break; + } + if (fseek(m_pFile, nOffset, nSeek)) + return (DWORD)-1; + + return (DWORD)ftell(m_pFile); +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ譎ょ綾險ュ螳 +/// +/// 繧ィ繝ゥ繝シ縺ョ譎ゅッFALSE繧定ソ斐☆縲 +// +//--------------------------------------------------------------------------- +BOOL CHostFcb::TimeStamp(DWORD nHumanTime) +{ + ASSERT(this); + ASSERT(m_pFile || m_bFlag); + + struct tm t = { 0 }; + t.tm_year = (nHumanTime >> 25) + 80; + t.tm_mon = ((nHumanTime >> 21) - 1) & 15; + t.tm_mday = (nHumanTime >> 16) & 31; + t.tm_hour = (nHumanTime >> 11) & 15; + t.tm_min = (nHumanTime >> 5) & 63; + t.tm_sec = (nHumanTime & 31) << 1; + time_t ti = mktime(&t); + if (ti == (time_t)-1) + return FALSE; + struct utimbuf ut; + ut.actime = ti; + ut.modtime = ti; + + // 繧ッ繝ュ繝シ繧コ譎ゅ↓譖エ譁ー譎ょ綾縺御ク頑嶌縺阪&繧後k縺ョ繧帝亟豁「縺吶k縺溘a + // 繧ソ繧、繝繧ケ繧ソ繝ウ繝励ョ譖エ譁ー蜑阪↓繝輔Λ繝繧キ繝・縺励※蜷梧悄縺輔○繧 + fflush(m_pFile); + + return utime(S2U(m_szFilename), &ut) == 0 || m_bFlag; +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ繧ッ繝ュ繝シ繧コ +/// +/// 繧ィ繝ゥ繝シ縺ョ譎ゅッFALSE繧定ソ斐☆縲 +// +//--------------------------------------------------------------------------- +BOOL CHostFcb::Close() +{ + ASSERT(this); + + BOOL bResult = TRUE; + + // 繝輔ぃ繧、繝ォ繧ッ繝ュ繝シ繧コ + // Close竊巽ree(蜀驛ィ縺ァ蜀榊コヲClose)縺ィ縺縺豬√l繧ゅ≠繧九ョ縺ァ蠢縺壼晄悄蛹悶☆繧九%縺ィ縲 + if (m_pFile) { + fclose(m_pFile); + m_pFile = NULL; + } + + return bResult; +} + +//=========================================================================== +// +// FCB蜃ヲ逅 繝槭ロ繝シ繧ク繝」 +// +//=========================================================================== + +#ifdef _DEBUG +//--------------------------------------------------------------------------- +// +/// 繝繧ケ繝医Λ繧ッ繧ソ final +// +//--------------------------------------------------------------------------- +CHostFcbManager::~CHostFcbManager() +{ + // 螳滉ス薙′蟄伜惠縺励↑縺縺薙→繧堤「コ隱 (蠢オ縺ョ縺溘a) + ASSERT(m_cRing.Next() == &m_cRing); + ASSERT(m_cRing.Prev() == &m_cRing); +} +#endif // _DEBUG + +//--------------------------------------------------------------------------- +// +/// 蛻晄悄蛹 (繝峨Λ繧、繝千オ霎シ縺ソ譎) +// +//--------------------------------------------------------------------------- +void CHostFcbManager::Init() +{ + ASSERT(this); + + // 螳滉ス薙′蟄伜惠縺励↑縺縺薙→繧堤「コ隱 (蠢オ縺ョ縺溘a) + ASSERT(m_cRing.Next() == &m_cRing); + ASSERT(m_cRing.Prev() == &m_cRing); + + // 繝。繝「繝ェ遒コ菫 + for (DWORD i = 0; i < XM6_HOST_FCB_MAX; i++) { + ring_t* p = new ring_t; + ASSERT(p); + p->r.Insert(&m_cRing); + } +} + +//--------------------------------------------------------------------------- +// +/// 隗」謾セ (襍キ蜍輔サ繝ェ繧サ繝繝域凾) +// +//--------------------------------------------------------------------------- +void CHostFcbManager::Clean() +{ + ASSERT(this); + + // 繝。繝「繝ェ隗」謾セ + CRing* p; + while ((p = m_cRing.Next()) != &m_cRing) { + delete (ring_t*)p; + } +} + +//--------------------------------------------------------------------------- +// +/// 遒コ菫 +// +//--------------------------------------------------------------------------- +CHostFcb* CHostFcbManager::Alloc(DWORD nKey) +{ + ASSERT(this); + ASSERT(nKey); + + // 譛ォ蟆セ縺九i驕ク謚 + ring_t* p = (ring_t*)m_cRing.Prev(); + + // 菴ソ逕ィ荳ュ縺ェ繧峨お繝ゥ繝シ (蠢オ縺ョ縺溘a) + if (p->f.isSameKey(0) == FALSE) { + ASSERT(0); + return NULL; + } + + // 繝ェ繝ウ繧ー蜈磯ュ縺ク遘サ蜍 + p->r.Insert(&m_cRing); + + // 繧ュ繝シ繧定ィュ螳 + p->f.SetKey(nKey); + + return &p->f; +} + +//--------------------------------------------------------------------------- +// +/// 讀懃エ「 +// +//--------------------------------------------------------------------------- +CHostFcb* CHostFcbManager::Search(DWORD nKey) +{ + ASSERT(this); + ASSERT(nKey); + + // 隧イ蠖薙☆繧九が繝悶ず繧ァ繧ッ繝医r讀懃エ「 + ring_t* p = (ring_t*)m_cRing.Next(); + while (p != (ring_t*)&m_cRing) { + if (p->f.isSameKey(nKey)) { + // 繝ェ繝ウ繧ー蜈磯ュ縺ク遘サ蜍 + p->r.Insert(&m_cRing); + return &p->f; + } + p = (ring_t*)p->r.Next(); + } + + return NULL; +} + +//--------------------------------------------------------------------------- +// +/// 隗」謾セ +// +//--------------------------------------------------------------------------- +void CHostFcbManager::Free(CHostFcb* pFcb) +{ + ASSERT(this); + ASSERT(pFcb); + + // 隗」謾セ + pFcb->SetKey(0); + pFcb->Close(); + + // 繝ェ繝ウ繧ー譛ォ蟆セ縺ク遘サ蜍 + ring_t* p = (ring_t*)((size_t)pFcb - offsetof(ring_t, f)); + p->r.InsertTail(&m_cRing); +} + +//=========================================================================== +// +// 繝帙せ繝亥エ繝輔ぃ繧、繝ォ繧キ繧ケ繝繝 +// +//=========================================================================== + +DWORD CFileSys::g_nOption; ///< 繝輔ぃ繧、繝ォ蜷榊、画鋤繝輔Λ繧ー + +//--------------------------------------------------------------------------- +// +/// 繝繝輔か繝ォ繝医さ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +CFileSys::CFileSys() +{ + // 繧ウ繝ウ繝輔ぅ繧ー繝繝シ繧ソ蛻晄悄蛹 + m_nDrives = 0; + + for (size_t n = 0; n < DriveMax; n++) { + m_nFlag[n] = 0; + m_szBase[n][0] = _T('\0'); + } + + // TwentyOne繧ェ繝励す繝ァ繝ウ逶」隕門晄悄蛹 + m_nKernel = 0; + m_nKernelSearch = 0; + + // 蜍穂ス懊ヵ繝ゥ繧ー蛻晄悄蛹 + m_nOptionDefault = 0; + m_nOption = 0; + ASSERT(g_nOption == 0); +} + +//--------------------------------------------------------------------------- +// +/// 繝ェ繧サ繝繝 (蜈ィ繧ッ繝ュ繝シ繧コ) +// +//--------------------------------------------------------------------------- +void CFileSys::Reset() +{ + ASSERT(this); + + // 莉ョ諠ウ繧サ繧ッ繧ソ鬆伜沺蛻晄悄蛹 + m_nHostSectorCount = 0; + memset(m_nHostSectorBuffer, 0, sizeof(m_nHostSectorBuffer)); + + // 繝輔ぃ繧、繝ォ讀懃エ「鬆伜沺 隗」謾セ (襍キ蜍輔サ繝ェ繧サ繝繝域凾) + m_cFiles.Clean(); + + // FCB謫堺ス憺伜沺 隗」謾セ (襍キ蜍輔サ繝ェ繧サ繝繝域凾) + m_cFcb.Clean(); + + // 繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ 隗」謾セ (襍キ蜍輔サ繝ェ繧サ繝繝域凾) + m_cEntry.Clean(); + + // TwentyOne繧ェ繝励す繝ァ繝ウ逶」隕門晄悄蛹 + m_nKernel = 0; + m_nKernelSearch = 0; + + // 蜍穂ス懊ヵ繝ゥ繧ー蛻晄悄蛹 + SetOption(m_nOptionDefault); +} + +//--------------------------------------------------------------------------- +// +/// 蛻晄悄蛹 (繝繝舌う繧ケ襍キ蜍輔→繝ュ繝シ繝) +// +//--------------------------------------------------------------------------- +void CFileSys::Init() +{ + ASSERT(this); + + // 繝輔ぃ繧、繝ォ讀懃エ「鬆伜沺 蛻晄悄蛹 (繝繝舌う繧ケ襍キ蜍輔サ繝ュ繝シ繝画凾) + m_cFiles.Init(); + + // FCB謫堺ス憺伜沺 蛻晄悄蛹 (繝繝舌う繧ケ襍キ蜍輔サ繝ュ繝シ繝画凾) + m_cFcb.Init(); + + // 繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ 蛻晄悄蛹 (繝繝舌う繧ケ襍キ蜍輔サ繝ュ繝シ繝画凾) + m_cEntry.Init(); + + // 繝代せ蛟句挨險ュ螳壹ョ譛臥┌繧貞愛螳 + DWORD nDrives = m_nDrives; + if (nDrives == 0) { + // 蛟句挨險ュ螳壹r菴ソ繧上★縺ォ繝ォ繝シ繝医ョ繧」繝ャ繧ッ繝医Μ繧剃スソ逕ィ縺吶k + strcpy(m_szBase[0], _T("/")); + m_nFlag[0] = 0; + nDrives++; + } + + // 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝繧堤匳骭イ + DWORD nUnit = 0; + for (DWORD n = 0; n < nDrives; n++) { + // 繝吶シ繧ケ繝代せ縺悟ュ伜惠縺励↑縺繧ィ繝ウ繝医Μ縺ッ逋サ骭イ縺励↑縺 + if (m_szBase[n][0] == _T('\0')) + continue; + + // 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝繧1繝ヲ繝九ャ繝育函謌 + CHostDrv* p = new CHostDrv; // std::nothrow + if (p) { + m_cEntry.SetDrv(nUnit, p); + p->Init(m_szBase[n], m_nFlag[n]); + + // 谺。縺ョ繝ヲ繝九ャ繝医∈ + nUnit++; + } + } + + // 逋サ骭イ縺励◆繝峨Λ繧、繝匁焚繧剃ソ晏ュ + m_nUnits = nUnit; +} + +//--------------------------------------------------------------------------- +// +/// $40 - 繝繝舌う繧ケ襍キ蜍 +// +//--------------------------------------------------------------------------- +DWORD CFileSys::InitDevice(const Human68k::argument_t* pArgument) +{ + ASSERT(this); + + // 繧ェ繝励す繝ァ繝ウ蛻晄悄蛹 + InitOption(pArgument); + + // 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝蛻晄悄蛹 + Init(); + + return m_nUnits; +} + +//--------------------------------------------------------------------------- +// +/// $41 - 繝繧」繝ャ繧ッ繝医Μ繝√ぉ繝繧ッ +// +//--------------------------------------------------------------------------- +int CFileSys::CheckDir(DWORD nUnit, const Human68k::namests_t* pNamests) +{ + ASSERT(this); + ASSERT(pNamests); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + if (nUnit >= m_nUnits) + return FS_INVALIDFUNC; // 繝ャ繧ク繝・繝シ繝蠕後↓辟。蜉ケ縺ェ繝峨Λ繧、繝悶〒mint謫堺ス懈凾縺ォ逋ス蟶ッ繧貞コ縺輔↑縺繧医≧謾ケ濶ッ + + // 繝代せ蜷咲函謌 + CHostFiles f; + f.SetPath(pNamests); + if (f.isRootPath()) + return 0; + f.SetPathOnly(); + if (f.Find(nUnit, &m_cEntry) == FALSE) + return FS_DIRNOTFND; + + return 0; +} + +//--------------------------------------------------------------------------- +// +/// $42 - 繝繧」繝ャ繧ッ繝医Μ菴懈 +// +//--------------------------------------------------------------------------- +int CFileSys::MakeDir(DWORD nUnit, const Human68k::namests_t* pNamests) +{ + ASSERT(this); + ASSERT(pNamests); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + ASSERT(nUnit < m_nUnits); + if (nUnit >= m_nUnits) + return FS_FATAL_MEDIAOFFLINE; // 蠢オ縺ョ縺溘a + + // 繝。繝繧」繧「繝√ぉ繝繧ッ + if (m_cEntry.isMediaOffline(nUnit)) + return FS_FATAL_MEDIAOFFLINE; + + // 譖ク縺崎セシ縺ソ遖∵ュ「繝√ぉ繝繧ッ + if (m_cEntry.isWriteProtect(nUnit)) + return FS_FATAL_WRITEPROTECT; + + // 繝代せ蜷咲函謌 + CHostFiles f; + f.SetPath(pNamests); + f.SetPathOnly(); + if (f.Find(nUnit, &m_cEntry) == FALSE) + return FS_INVALIDPATH; + f.AddFilename(); + + // 繝繧」繝ャ繧ッ繝医Μ菴懈 + if (mkdir(S2U(f.GetPath()), 0777)) + return FS_INVALIDPATH; + + // 繧ュ繝」繝繧キ繝・譖エ譁ー + m_cEntry.CleanCache(nUnit, f.GetHumanPath()); + + return 0; +} + +//--------------------------------------------------------------------------- +// +/// $43 - 繝繧」繝ャ繧ッ繝医Μ蜑企勁 +// +//--------------------------------------------------------------------------- +int CFileSys::RemoveDir(DWORD nUnit, const Human68k::namests_t* pNamests) +{ + ASSERT(this); + ASSERT(pNamests); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + ASSERT(nUnit < m_nUnits); + if (nUnit >= m_nUnits) + return FS_FATAL_MEDIAOFFLINE; // 蠢オ縺ョ縺溘a + + // 繝。繝繧」繧「繝√ぉ繝繧ッ + if (m_cEntry.isMediaOffline(nUnit)) + return FS_FATAL_MEDIAOFFLINE; + + // 譖ク縺崎セシ縺ソ遖∵ュ「繝√ぉ繝繧ッ + if (m_cEntry.isWriteProtect(nUnit)) + return FS_FATAL_WRITEPROTECT; + + // 繝代せ蜷咲函謌 + CHostFiles f; + f.SetPath(pNamests); + f.SetAttribute(Human68k::AT_DIRECTORY); + if (f.Find(nUnit, &m_cEntry) == FALSE) + return FS_DIRNOTFND; + + // 繧ュ繝」繝繧キ繝・蜑企勁 + BYTE szHuman[HUMAN68K_PATH_MAX + 24]; + ASSERT(strlen((const char*)f.GetHumanPath()) + + strlen((const char*)f.GetHumanFilename()) < HUMAN68K_PATH_MAX + 24); + strcpy((char*)szHuman, (const char*)f.GetHumanPath()); + strcat((char*)szHuman, (const char*)f.GetHumanFilename()); + strcat((char*)szHuman, "/"); + m_cEntry.DeleteCache(nUnit, szHuman); + + // 繝繧」繝ャ繧ッ繝医Μ蜑企勁 + if (rmdir(S2U(f.GetPath()))) + return FS_CANTDELETE; + + // 繧ュ繝」繝繧キ繝・譖エ譁ー + m_cEntry.CleanCache(nUnit, f.GetHumanPath()); + + return 0; +} + +//--------------------------------------------------------------------------- +// +/// $44 - 繝輔ぃ繧、繝ォ蜷榊、画峩 +// +//--------------------------------------------------------------------------- +int CFileSys::Rename(DWORD nUnit, const Human68k::namests_t* pNamests, const Human68k::namests_t* pNamestsNew) +{ + ASSERT(this); + ASSERT(pNamests); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + ASSERT(nUnit < m_nUnits); + if (nUnit >= m_nUnits) + return FS_FATAL_MEDIAOFFLINE; // 蠢オ縺ョ縺溘a + + // 繝。繝繧」繧「繝√ぉ繝繧ッ + if (m_cEntry.isMediaOffline(nUnit)) + return FS_FATAL_MEDIAOFFLINE; + + // 譖ク縺崎セシ縺ソ遖∵ュ「繝√ぉ繝繧ッ + if (m_cEntry.isWriteProtect(nUnit)) + return FS_FATAL_WRITEPROTECT; + + // 繝代せ蜷咲函謌 + CHostFiles f; + f.SetPath(pNamests); + f.SetAttribute(Human68k::AT_ALL); + if (f.Find(nUnit, &m_cEntry) == FALSE) + return FS_FILENOTFND; + + CHostFiles fNew; + fNew.SetPath(pNamestsNew); + fNew.SetPathOnly(); + if (fNew.Find(nUnit, &m_cEntry) == FALSE) + return FS_INVALIDPATH; + fNew.AddFilename(); + + // 繧ュ繝」繝繧キ繝・譖エ譁ー + if (f.GetAttribute() & Human68k::AT_DIRECTORY) + m_cEntry.CleanCacheChild(nUnit, f.GetHumanPath()); + + // 繝輔ぃ繧、繝ォ蜷榊、画峩 + char szFrom[FILENAME_MAX]; + char szTo[FILENAME_MAX]; + SJIS2UTF8(f.GetPath(), szFrom, FILENAME_MAX); + SJIS2UTF8(fNew.GetPath(), szTo, FILENAME_MAX); + if (rename(szFrom, szTo)) { + return FS_FILENOTFND; + } + + // 繧ュ繝」繝繧キ繝・譖エ譁ー + m_cEntry.CleanCache(nUnit, f.GetHumanPath()); + m_cEntry.CleanCache(nUnit, fNew.GetHumanPath()); + + return 0; +} + +//--------------------------------------------------------------------------- +// +/// $45 - 繝輔ぃ繧、繝ォ蜑企勁 +// +//--------------------------------------------------------------------------- +int CFileSys::Delete(DWORD nUnit, const Human68k::namests_t* pNamests) +{ + ASSERT(this); + ASSERT(pNamests); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + ASSERT(nUnit < m_nUnits); + if (nUnit >= m_nUnits) + return FS_FATAL_MEDIAOFFLINE; // 蠢オ縺ョ縺溘a + + // 繝。繝繧」繧「繝√ぉ繝繧ッ + if (m_cEntry.isMediaOffline(nUnit)) + return FS_FATAL_MEDIAOFFLINE; + + // 譖ク縺崎セシ縺ソ遖∵ュ「繝√ぉ繝繧ッ + if (m_cEntry.isWriteProtect(nUnit)) + return FS_FATAL_WRITEPROTECT; + + // 繝代せ蜷咲函謌 + CHostFiles f; + f.SetPath(pNamests); + if (f.Find(nUnit, &m_cEntry) == FALSE) + return FS_FILENOTFND; + + // 繝輔ぃ繧、繝ォ蜑企勁 + if (unlink(S2U(f.GetPath()))) + return FS_CANTDELETE; + + // 繧ュ繝」繝繧キ繝・譖エ譁ー + m_cEntry.CleanCache(nUnit, f.GetHumanPath()); + + return 0; +} + +//--------------------------------------------------------------------------- +// +/// $46 - 繝輔ぃ繧、繝ォ螻樊ァ蜿門セ/險ュ螳 +// +//--------------------------------------------------------------------------- +int CFileSys::Attribute(DWORD nUnit, const Human68k::namests_t* pNamests, DWORD nHumanAttribute) +{ + ASSERT(this); + ASSERT(pNamests); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + if (nUnit >= m_nUnits) + return FS_FATAL_MEDIAOFFLINE; // 繝ャ繧ク繝・繝シ繝蠕後↓辟。蜉ケ縺ェ繝峨Λ繧、繝紋ク翫〒逋コ逕 + + // 繝。繝繧」繧「繝√ぉ繝繧ッ + if (m_cEntry.isMediaOffline(nUnit)) + return FS_FATAL_MEDIAOFFLINE; + + // 繝代せ蜷咲函謌 + CHostFiles f; + f.SetPath(pNamests); + f.SetAttribute(Human68k::AT_ALL); + if (f.Find(nUnit, &m_cEntry) == FALSE) + return FS_FILENOTFND; + + // 螻樊ァ蜿門セ励↑繧臥オゆコ + if (nHumanAttribute == 0xFF) + return f.GetAttribute(); + + // 螻樊ァ繝√ぉ繝繧ッ + if (nHumanAttribute & Human68k::AT_VOLUME) + return FS_CANTACCESS; + + // 譖ク縺崎セシ縺ソ遖∵ュ「繝√ぉ繝繧ッ + if (m_cEntry.isWriteProtect(nUnit)) + return FS_FATAL_WRITEPROTECT; + + // 螻樊ァ逕滓 + DWORD nAttribute = (nHumanAttribute & Human68k::AT_READONLY) | + (f.GetAttribute() & ~Human68k::AT_READONLY); + if (f.GetAttribute() != nAttribute) { + struct stat sb; + if (stat(S2U(f.GetPath()), &sb)) + return FS_FILENOTFND; + mode_t m = sb.st_mode & 0777; + if (nAttribute & Human68k::AT_READONLY) + m &= 0555; // ugo-w + else + m |= 0200; // u+w + + // 螻樊ァ險ュ螳 + if (chmod(S2U(f.GetPath()), m)) + return FS_FILENOTFND; + } + + // 繧ュ繝」繝繧キ繝・譖エ譁ー + m_cEntry.CleanCache(nUnit, f.GetHumanPath()); + + // 螟画峩蠕後ョ螻樊ァ蜿門セ + if (f.Find(nUnit, &m_cEntry) == FALSE) + return FS_FILENOTFND; + + return f.GetAttribute(); +} + +//--------------------------------------------------------------------------- +// +/// $47 - 繝輔ぃ繧、繝ォ讀懃エ「 +// +//--------------------------------------------------------------------------- +int CFileSys::Files(DWORD nUnit, DWORD nKey, const Human68k::namests_t* pNamests, Human68k::files_t* pFiles) +{ + ASSERT(this); + ASSERT(pNamests); + ASSERT(nKey); + ASSERT(pFiles); + + // 譌「縺ォ蜷後§繧ュ繝シ繧呈戟縺、鬆伜沺縺後≠繧後ー隗」謾セ縺励※縺翫¥ + CHostFiles* pHostFiles = m_cFiles.Search(nKey); + if (pHostFiles != NULL) { + m_cFiles.Free(pHostFiles); + } + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + if (nUnit >= m_nUnits) + return FS_FATAL_MEDIAOFFLINE; // 繝ャ繧ク繝・繝シ繝蠕後↓辟。蜉ケ縺ェ繝峨Λ繧、繝紋ク翫〒逋コ逕 + + // 繝懊Μ繝・繝シ繝繝ゥ繝吶Ν縺ョ蜿門セ + /** @note + 逶エ蜑阪ョ繝。繝繧」繧「莠、謠帙メ繧ァ繝繧ッ縺ァ豁」縺励¥繧ィ繝ゥ繝シ繧定ソ斐@縺ヲ縺繧九↓繧ゅ°縺九o繧 + 縺壹√懊Μ繝・繝シ繝繝ゥ繝吶Ν縺ョ蜿門セ励r螳溯。後☆繧玖。悟о縺ョ謔ェ縺繧「繝励Μ縺ァ繝帙せ繝亥エ縺ョ + 繝ェ繝繝シ繝舌ヶ繝ォ繝。繝繧」繧「(CD-ROM繝峨Λ繧、繝也ュ)縺檎區蟶ッ繧貞コ縺吶ョ繧帝亟縺舌◆繧√ + 繝懊Μ繝・繝シ繝繝ゥ繝吶Ν縺ョ蜿門セ励ッ繝。繝繧」繧「繝√ぉ繝繧ッ繧偵○縺壹↓陦後↑縺莉墓ァ倥→縺励◆縲 + */ + if ((pFiles->fatr & (Human68k::AT_ARCHIVE | Human68k::AT_DIRECTORY | Human68k::AT_VOLUME)) + == Human68k::AT_VOLUME) { + // 繝代せ繝√ぉ繝繧ッ + CHostFiles f; + f.SetPath(pNamests); + if (f.isRootPath() == FALSE) + return FS_FILENOTFND; + + // 繝舌ャ繝輔ぃ繧堤「コ菫昴○縺壹√>縺阪↑繧顔オ先棡繧定ソ斐☆ + if (FilesVolume(nUnit, pFiles) == FALSE) + return FS_FILENOTFND; + return 0; + } + + // 繝。繝繧」繧「繝√ぉ繝繧ッ + if (m_cEntry.isMediaOffline(nUnit)) + return FS_FATAL_MEDIAOFFLINE; + + // 繝舌ャ繝輔ぃ遒コ菫 + pHostFiles = m_cFiles.Alloc(nKey); + if (pHostFiles == NULL) + return FS_OUTOFMEM; + + // 繝繧」繝ャ繧ッ繝医Μ繝√ぉ繝繧ッ + pHostFiles->SetPath(pNamests); + if (pHostFiles->isRootPath() == FALSE) { + pHostFiles->SetPathOnly(); + if (pHostFiles->Find(nUnit, &m_cEntry) == FALSE) { + m_cFiles.Free(pHostFiles); + return FS_DIRNOTFND; + } + } + + // 繝ッ繧、繝ォ繝峨き繝シ繝我スソ逕ィ蜿ッ閭ス縺ォ險ュ螳 + pHostFiles->SetPathWildcard(); + pHostFiles->SetAttribute(pFiles->fatr); + + // 繝輔ぃ繧、繝ォ讀懃エ「 + if (pHostFiles->Find(nUnit, &m_cEntry) == FALSE) { + m_cFiles.Free(pHostFiles); + return FS_FILENOTFND; + } + + // 讀懃エ「邨先棡繧呈シ邏 + pFiles->attr = (BYTE)pHostFiles->GetAttribute(); + pFiles->date = pHostFiles->GetDate(); + pFiles->time = pHostFiles->GetTime(); + pFiles->size = pHostFiles->GetSize(); + strcpy((char*)pFiles->full, (const char*)pHostFiles->GetHumanResult()); + + // 謫ャ莨シ繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ繧呈欠螳 + pFiles->sector = nKey; + pFiles->offset = 0; + + // 繝輔ぃ繧、繝ォ蜷阪↓繝ッ繧、繝ォ繝峨き繝シ繝峨′縺ェ縺代l縺ー縲√%縺ョ譎らせ縺ァ繝舌ャ繝輔ぃ繧定ァ」謾セ蜿ッ閭ス + if (pNamests->wildcard == 0) { + // 縺励°縺励∽サョ諠ウ繧サ繧ッ繧ソ縺ョ繧ィ繝溘Η繝ャ繝シ繧キ繝ァ繝ウ縺ァ菴ソ縺蜿ッ閭ス諤ァ縺後≠繧九◆繧√√☆縺舌↓縺ッ隗」謾セ縺励↑縺 + // m_cFiles.Free(pHostFiles); + } + + return 0; +} + +//--------------------------------------------------------------------------- +// +/// $48 - 繝輔ぃ繧、繝ォ谺。讀懃エ「 +// +//--------------------------------------------------------------------------- +int CFileSys::NFiles(DWORD nUnit, DWORD nKey, Human68k::files_t* pFiles) +{ + ASSERT(this); + ASSERT(nKey); + ASSERT(pFiles); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + if (nUnit >= m_nUnits) + return FS_FATAL_MEDIAOFFLINE; // 繝ャ繧ク繝・繝シ繝蠕後↓辟。蜉ケ縺ェ繝峨Λ繧、繝紋ク翫〒逋コ逕 + + // 繝。繝繧」繧「繝√ぉ繝繧ッ + if (m_cEntry.isMediaOffline(nUnit)) + return FS_FATAL_MEDIAOFFLINE; + + // 繝舌ャ繝輔ぃ讀懃エ「 + CHostFiles* pHostFiles = m_cFiles.Search(nKey); + if (pHostFiles == NULL) + return FS_INVALIDPTR; + + // 繝輔ぃ繧、繝ォ讀懃エ「 + if (pHostFiles->Find(nUnit, &m_cEntry) == FALSE) { + m_cFiles.Free(pHostFiles); + return FS_FILENOTFND; + } + + ASSERT(pFiles->sector == nKey); + ASSERT(pFiles->offset == 0); + + // 讀懃エ「邨先棡繧呈シ邏 + pFiles->attr = (BYTE)pHostFiles->GetAttribute(); + pFiles->date = pHostFiles->GetDate(); + pFiles->time = pHostFiles->GetTime(); + pFiles->size = pHostFiles->GetSize(); + strcpy((char*)pFiles->full, (const char*)pHostFiles->GetHumanResult()); + + return 0; +} + +//--------------------------------------------------------------------------- +// +/// $49 - 繝輔ぃ繧、繝ォ譁ー隕丈ス懈 +// +//--------------------------------------------------------------------------- +int CFileSys::Create(DWORD nUnit, DWORD nKey, const Human68k::namests_t* pNamests, Human68k::fcb_t* pFcb, DWORD nHumanAttribute, BOOL bForce) +{ + ASSERT(this); + ASSERT(pNamests); + ASSERT(nKey); + ASSERT(pFcb); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + ASSERT(nUnit < m_nUnits); + if (nUnit >= m_nUnits) + return FS_FATAL_MEDIAOFFLINE; // 蠢オ縺ョ縺溘a + + // 繝。繝繧」繧「繝√ぉ繝繧ッ + if (m_cEntry.isMediaOffline(nUnit)) + return FS_FATAL_MEDIAOFFLINE; + + // 譖ク縺崎セシ縺ソ遖∵ュ「繝√ぉ繝繧ッ + if (m_cEntry.isWriteProtect(nUnit)) + return FS_FATAL_WRITEPROTECT; + + // 譌「縺ォ蜷後§繧ュ繝シ繧呈戟縺、鬆伜沺縺後≠繧後ー繧ィ繝ゥ繝シ縺ィ縺吶k + if (m_cFcb.Search(nKey) != NULL) + return FS_INVALIDPTR; + + // 繝代せ蜷咲函謌 + CHostFiles f; + f.SetPath(pNamests); + f.SetPathOnly(); + if (f.Find(nUnit, &m_cEntry) == FALSE) + return FS_INVALIDPATH; + f.AddFilename(); + + // 螻樊ァ繝√ぉ繝繧ッ + if (nHumanAttribute & (Human68k::AT_DIRECTORY | Human68k::AT_VOLUME)) + return FS_CANTACCESS; + + // 繝代せ蜷堺ソ晏ュ + CHostFcb* pHostFcb = m_cFcb.Alloc(nKey); + if (pHostFcb == NULL) + return FS_OUTOFMEM; + pHostFcb->SetFilename(f.GetPath()); + pHostFcb->SetHumanPath(f.GetHumanPath()); + + // 繧ェ繝シ繝励Φ繝「繝シ繝芽ィュ螳 + pFcb->mode = (WORD)((pFcb->mode & ~Human68k::OP_MASK) | Human68k::OP_FULL); + if (pHostFcb->SetMode(pFcb->mode) == FALSE) { + m_cFcb.Free(pHostFcb); + return FS_ILLEGALMOD; + } + + // 繝輔ぃ繧、繝ォ菴懈 + if (pHostFcb->Create(nHumanAttribute, bForce) == FALSE) { + m_cFcb.Free(pHostFcb); + return FS_FILEEXIST; + } + + // 繧ュ繝」繝繧キ繝・譖エ譁ー + m_cEntry.CleanCache(nUnit, f.GetHumanPath()); + + return 0; +} + +//--------------------------------------------------------------------------- +// +/// $4A - 繝輔ぃ繧、繝ォ繧ェ繝シ繝励Φ +// +//--------------------------------------------------------------------------- +int CFileSys::Open(DWORD nUnit, DWORD nKey, const Human68k::namests_t* pNamests, Human68k::fcb_t* pFcb) +{ + ASSERT(this); + ASSERT(pNamests); + ASSERT(nKey); + ASSERT(pFcb); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + if (nUnit >= m_nUnits) + return FS_FATAL_MEDIAOFFLINE; // 繝ャ繧ク繝・繝シ繝蠕後↓辟。蜉ケ縺ェ繝峨Λ繧、繝紋ク翫〒逋コ逕 + + // 繝。繝繧」繧「繝√ぉ繝繧ッ + if (m_cEntry.isMediaOffline(nUnit)) + return FS_FATAL_MEDIAOFFLINE; + + // 譖ク縺崎セシ縺ソ遖∵ュ「繝√ぉ繝繧ッ + switch (pFcb->mode & Human68k::OP_MASK) { + case Human68k::OP_WRITE: + case Human68k::OP_FULL: + if (m_cEntry.isWriteProtect(nUnit)) + return FS_FATAL_WRITEPROTECT; + } + + // 譌「縺ォ蜷後§繧ュ繝シ繧呈戟縺、鬆伜沺縺後≠繧後ー繧ィ繝ゥ繝シ縺ィ縺吶k + if (m_cFcb.Search(nKey) != NULL) + return FS_INVALIDPRM; + + // 繝代せ蜷咲函謌 + CHostFiles f; + f.SetPath(pNamests); + f.SetAttribute(Human68k::AT_ALL); + if (f.Find(nUnit, &m_cEntry) == FALSE) + return FS_FILENOTFND; + + // 繧ソ繧、繝繧ケ繧ソ繝ウ繝 + pFcb->date = f.GetDate(); + pFcb->time = f.GetTime(); + + // 繝輔ぃ繧、繝ォ繧オ繧、繧コ + pFcb->size = f.GetSize(); + + // 繝代せ蜷堺ソ晏ュ + CHostFcb* pHostFcb = m_cFcb.Alloc(nKey); + if (pHostFcb == NULL) + return FS_OUTOFMEM; + pHostFcb->SetFilename(f.GetPath()); + pHostFcb->SetHumanPath(f.GetHumanPath()); + + // 繧ェ繝シ繝励Φ繝「繝シ繝芽ィュ螳 + if (pHostFcb->SetMode(pFcb->mode) == FALSE) { + m_cFcb.Free(pHostFcb); + return FS_ILLEGALMOD; + } + + // 繝輔ぃ繧、繝ォ繧ェ繝シ繝励Φ + if (pHostFcb->Open() == FALSE) { + m_cFcb.Free(pHostFcb); + return FS_INVALIDPATH; + } + + return 0; +} + +//--------------------------------------------------------------------------- +// +/// $4B - 繝輔ぃ繧、繝ォ繧ッ繝ュ繝シ繧コ +// +//--------------------------------------------------------------------------- +int CFileSys::Close(DWORD nUnit, DWORD nKey, Human68k::fcb_t* /* pFcb */) +{ + ASSERT(this); + ASSERT(nKey); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + if (nUnit >= m_nUnits) + return FS_FATAL_MEDIAOFFLINE; // 繝ャ繧ク繝・繝シ繝蠕後↓辟。蜉ケ縺ェ繝峨Λ繧、繝紋ク翫〒逋コ逕 + + // 繝。繝繧」繧「繝√ぉ繝繧ッ + if (m_cEntry.isMediaOffline(nUnit)) + return FS_FATAL_MEDIAOFFLINE; + + // 譌「縺ォ蜷後§繧ュ繝シ繧呈戟縺、鬆伜沺縺後↑縺代l縺ー繧ィ繝ゥ繝シ縺ィ縺吶k + CHostFcb* pHostFcb = m_cFcb.Search(nKey); + if (pHostFcb == NULL) + return FS_INVALIDPRM; + + // 繝輔ぃ繧、繝ォ繧ッ繝ュ繝シ繧コ縺ィ鬆伜沺隗」謾セ + m_cFcb.Free(pHostFcb); + + // 繧ュ繝」繝繧キ繝・譖エ譁ー + if (pHostFcb->isUpdate()) + m_cEntry.CleanCache(nUnit, pHostFcb->GetHumanPath()); + + /// @note 繧ッ繝ュ繝シ繧コ譎ゅョFCB縺ョ迥カ諷九r莉悶ョ繝繝舌う繧ケ縺ィ蜷医o縺帙◆縺 + + return 0; +} + +//--------------------------------------------------------------------------- +// +/// $4C - 繝輔ぃ繧、繝ォ隱ュ縺ソ霎シ縺ソ +/// +/// 0繝舌う繝郁ェュ縺ソ霎シ縺ソ縺ァ繧よュ」蟶ク邨ゆコ縺吶k縲 +// +//--------------------------------------------------------------------------- +int CFileSys::Read(DWORD nKey, Human68k::fcb_t* pFcb, BYTE* pBuffer, DWORD nSize) +{ + ASSERT(this); + ASSERT(nKey); + ASSERT(pFcb); + // ASSERT(pBuffer); // 蠢隕∵凾縺ョ縺ソ蛻、螳 + ASSERT(nSize <= 0xFFFFFF); // 繧ッ繝ェ繝繝玲ク + + // 譌「縺ォ蜷後§繧ュ繝シ繧呈戟縺、鬆伜沺縺後↑縺代l縺ー繧ィ繝ゥ繝シ縺ィ縺吶k + CHostFcb* pHostFcb = m_cFcb.Search(nKey); + if (pHostFcb == NULL) + return FS_NOTOPENED; + + // 繝舌ャ繝輔ぃ蟄伜惠遒コ隱 + if (pBuffer == NULL) { + m_cFcb.Free(pHostFcb); + return FS_INVALIDFUNC; + } + + // 隱ュ縺ソ霎シ縺ソ + DWORD nResult; + nResult = pHostFcb->Read(pBuffer, nSize); + if (nResult == (DWORD)-1) { + m_cFcb.Free(pHostFcb); + return FS_INVALIDFUNC; /// @note 縺薙l縺ォ蜉縺医※繧ィ繝ゥ繝シ繧ウ繝シ繝10(隱ュ縺ソ霎シ縺ソ繧ィ繝ゥ繝シ)繧定ソ斐☆縺ケ縺 + } + ASSERT(nResult <= nSize); + + // 繝輔ぃ繧、繝ォ繝昴う繝ウ繧ソ譖エ譁ー + pFcb->fileptr += nResult; /// @note 繧ェ繝シ繝舌シ繝輔Ο繝シ遒コ隱阪ッ蠢隕√§繧繧阪≧縺具シ + + return nResult; +} + +//--------------------------------------------------------------------------- +// +/// $4D - 繝輔ぃ繧、繝ォ譖ク縺崎セシ縺ソ +/// +/// 0繝舌う繝域嶌縺崎セシ縺ソ縺ョ蝣エ蜷医ッ繝輔ぃ繧、繝ォ繧貞繧願ゥー繧√k縲 +// +//--------------------------------------------------------------------------- +int CFileSys::Write(DWORD nKey, Human68k::fcb_t* pFcb, const BYTE* pBuffer, DWORD nSize) +{ + ASSERT(this); + ASSERT(nKey); + ASSERT(pFcb); + // ASSERT(pBuffer); // 蠢隕∵凾縺ョ縺ソ蛻、螳 + ASSERT(nSize <= 0xFFFFFF); // 繧ッ繝ェ繝繝玲ク + + // 譌「縺ォ蜷後§繧ュ繝シ繧呈戟縺、鬆伜沺縺後↑縺代l縺ー繧ィ繝ゥ繝シ縺ィ縺吶k + CHostFcb* pHostFcb = m_cFcb.Search(nKey); + if (pHostFcb == NULL) + return FS_NOTOPENED; + + DWORD nResult; + if (nSize == 0) { + // 蛻繧願ゥー繧 + if (pHostFcb->Truncate() == FALSE) { + m_cFcb.Free(pHostFcb); + return FS_CANTSEEK; + } + + // 繝輔ぃ繧、繝ォ繧オ繧、繧コ譖エ譁ー + pFcb->size = pFcb->fileptr; + + nResult = 0; + } else { + // 繝舌ャ繝輔ぃ蟄伜惠遒コ隱 + if (pBuffer == NULL) { + m_cFcb.Free(pHostFcb); + return FS_INVALIDFUNC; + } + + // 譖ク縺崎セシ縺ソ + nResult = pHostFcb->Write(pBuffer, nSize); + if (nResult == (DWORD)-1) { + m_cFcb.Free(pHostFcb); + return FS_CANTWRITE; /// @note 縺薙l縺ォ蜉縺医※繧ィ繝ゥ繝シ繧ウ繝シ繝11(譖ク縺崎セシ縺ソ繧ィ繝ゥ繝シ)繧定ソ斐☆縺ケ縺 + } + ASSERT(nResult <= nSize); + + // 繝輔ぃ繧、繝ォ繝昴う繝ウ繧ソ譖エ譁ー + pFcb->fileptr += nResult; /// @note 繧ェ繝シ繝舌シ繝輔Ο繝シ遒コ隱阪ッ蠢隕√§繧繧阪≧縺具シ + + // 繝輔ぃ繧、繝ォ繧オ繧、繧コ譖エ譁ー + if (pFcb->size < pFcb->fileptr) + pFcb->size = pFcb->fileptr; + } + + // 繝輔Λ繧ー譖エ譁ー + pHostFcb->SetUpdate(); + + return nResult; +} + +//--------------------------------------------------------------------------- +// +/// $4E - 繝輔ぃ繧、繝ォ繧キ繝シ繧ッ +// +//--------------------------------------------------------------------------- +int CFileSys::Seek(DWORD nKey, Human68k::fcb_t* pFcb, DWORD nSeek, int nOffset) +{ + ASSERT(this); + ASSERT(pFcb); + + // 譌「縺ォ蜷後§繧ュ繝シ繧呈戟縺、鬆伜沺縺後↑縺代l縺ー繧ィ繝ゥ繝シ縺ィ縺吶k + CHostFcb* pHostFcb = m_cFcb.Search(nKey); + if (pHostFcb == NULL) + return FS_NOTOPENED; + + // 繝代Λ繝。繝シ繧ソ繝√ぉ繝繧ッ + if (nSeek > Human68k::SK_END) { + m_cFcb.Free(pHostFcb); + return FS_INVALIDPRM; + } + + // 繝輔ぃ繧、繝ォ繧キ繝シ繧ッ + DWORD nResult = pHostFcb->Seek(nOffset, nSeek); + if (nResult == (DWORD)-1) { + m_cFcb.Free(pHostFcb); + return FS_CANTSEEK; + } + + // 繝輔ぃ繧、繝ォ繝昴う繝ウ繧ソ譖エ譁ー + pFcb->fileptr = nResult; + + return nResult; +} + +//--------------------------------------------------------------------------- +// +/// $4F - 繝輔ぃ繧、繝ォ譎ょ綾蜿門セ/險ュ螳 +/// +/// 邨先棡縺ョ荳贋ス16Bit縺$FFFF縺縺ィ繧ィ繝ゥ繝シ縲 +// +//--------------------------------------------------------------------------- +DWORD CFileSys::TimeStamp(DWORD nUnit, DWORD nKey, Human68k::fcb_t* pFcb, DWORD nHumanTime) +{ + ASSERT(this); + ASSERT(nKey); + ASSERT(pFcb); + + // 蜿門セ励ョ縺ソ + if (nHumanTime == 0) + return ((DWORD)pFcb->date << 16) | pFcb->time; + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + ASSERT(nUnit < m_nUnits); + if (nUnit >= m_nUnits) + return FS_FATAL_MEDIAOFFLINE; // 蠢オ縺ョ縺溘a + + // 繝。繝繧」繧「繝√ぉ繝繧ッ + if (m_cEntry.isMediaOffline(nUnit)) + return FS_FATAL_MEDIAOFFLINE; + + // 譖ク縺崎セシ縺ソ遖∵ュ「繝√ぉ繝繧ッ + if (m_cEntry.isWriteProtect(nUnit)) + return FS_FATAL_WRITEPROTECT; + + // 譌「縺ォ蜷後§繧ュ繝シ繧呈戟縺、鬆伜沺縺後↑縺代l縺ー繧ィ繝ゥ繝シ縺ィ縺吶k + CHostFcb* pHostFcb = m_cFcb.Search(nKey); + if (pHostFcb == NULL) + return FS_NOTOPENED; + + // 譎ょ綾險ュ螳 + if (pHostFcb->TimeStamp(nHumanTime) == FALSE) { + m_cFcb.Free(pHostFcb); + return FS_INVALIDPRM; + } + pFcb->date = (WORD)(nHumanTime >> 16); + pFcb->time = (WORD)nHumanTime; + + // 繧ュ繝」繝繧キ繝・譖エ譁ー + m_cEntry.CleanCache(nUnit, pHostFcb->GetHumanPath()); + + return 0; +} + +//--------------------------------------------------------------------------- +// +/// $50 - 螳ケ驥丞叙蠕 +// +//--------------------------------------------------------------------------- +int CFileSys::GetCapacity(DWORD nUnit, Human68k::capacity_t* pCapacity) +{ + ASSERT(this); + ASSERT(pCapacity); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + ASSERT(nUnit < m_nUnits); + if (nUnit >= m_nUnits) + return FS_FATAL_MEDIAOFFLINE; // 蠢オ縺ョ縺溘a + + // 繝。繝繧」繧「繝√ぉ繝繧ッ + if (m_cEntry.isMediaOffline(nUnit)) + return FS_FATAL_MEDIAOFFLINE; + + // 螳ケ驥丞叙蠕 + return m_cEntry.GetCapacity(nUnit, pCapacity); +} + +//--------------------------------------------------------------------------- +// +/// $51 - 繝峨Λ繧、繝也憾諷区、懈渊/蛻カ蠕。 +// +//--------------------------------------------------------------------------- +int CFileSys::CtrlDrive(DWORD nUnit, Human68k::ctrldrive_t* pCtrlDrive) +{ + ASSERT(this); + ASSERT(pCtrlDrive); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + if (nUnit >= m_nUnits) + return FS_INVALIDFUNC; // 繝ャ繧ク繝・繝シ繝蠕後↓辟。蜉ケ縺ェ繝峨Λ繧、繝悶〒mint謫堺ス懈凾縺ォ逋ス蟶ッ繧貞コ縺輔↑縺繧医≧謾ケ濶ッ + + switch (pCtrlDrive->status) { + case 0: // 迥カ諷区、懈渊 + case 9: // 迥カ諷区、懈渊2 + pCtrlDrive->status = (BYTE)m_cEntry.GetStatus(nUnit); + return pCtrlDrive->status; + + case 1: // 繧、繧ク繧ァ繧ッ繝 + case 2: // 繧、繧ク繧ァ繧ッ繝育ヲ∵ュ「1 (譛ェ螳溯」) + case 3: // 繧、繧ク繧ァ繧ッ繝郁ィア蜿ッ1 (譛ェ螳溯」) + case 4: // 繝。繝繧」繧「譛ェ謖ソ蜈・譎ゅ↓LED轤ケ貊 (譛ェ螳溯」) + case 5: // 繝。繝繧」繧「譛ェ謖ソ蜈・譎ゅ↓LED豸育ッ (譛ェ螳溯」) + case 6: // 繧、繧ク繧ァ繧ッ繝育ヲ∵ュ「2 (譛ェ螳溯」) + case 7: // 繧、繧ク繧ァ繧ッ繝郁ィア蜿ッ2 (譛ェ螳溯」) + return 0; + + case 8: // 繧、繧ク繧ァ繧ッ繝域、懈渊 + return 1; + } + + return FS_INVALIDFUNC; +} + +//--------------------------------------------------------------------------- +// +/// $52 - DPB蜿門セ +/// +/// 繝ャ繧ク繝・繝シ繝蠕後↓DPB縺悟叙蠕励〒縺阪↑縺縺ィHuman68k蜀驛ィ縺ァ繝峨Λ繧、繝悶′豸域サ縺吶k縺溘a縲 +/// 遽蝗イ螟悶ョ繝ヲ繝九ャ繝医〒繧ゅ→縺ォ縺九¥豁」蟶ク邉サ縺ィ縺励※蜃ヲ逅縺吶k縲 +// +//--------------------------------------------------------------------------- +int CFileSys::GetDPB(DWORD nUnit, Human68k::dpb_t* pDpb) +{ + ASSERT(this); + ASSERT(pDpb); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + + Human68k::capacity_t cap; + BYTE media = Human68k::MEDIA_REMOTE; + if (nUnit < m_nUnits) { + media = m_cEntry.GetMediaByte(nUnit); + + // 繧サ繧ッ繧ソ諠蝣ア迯イ蠕 + if (m_cEntry.GetCapacityCache(nUnit, &cap) == FALSE) { + // 謇句虚繧、繧ク繧ァ繧ッ繝医□縺ィ繝。繝繧」繧「繝√ぉ繝繧ッ繧偵☆繧頑栢縺代k縺溘a縺薙%縺ァ謐墓拷 + if (m_cEntry.isEnable(nUnit) == FALSE) + goto none; + + // 繝。繝繧」繧「繝√ぉ繝繧ッ + if (m_cEntry.isMediaOffline(nUnit)) + goto none; + + // 繝峨Λ繧、繝也憾諷句叙蠕 + m_cEntry.GetCapacity(nUnit, &cap); + } + } else { + none: + cap.clusters = 4; // 縺セ縺」縺」縺溘¥蝠城。後↑縺繝繧ケ繧茨シ + cap.sectors = 64; + cap.bytes = 512; + } + + // 繧キ繝輔ヨ謨ー險育ョ + DWORD nSize = 1; + DWORD nShift = 0; + for (;;) { + if (nSize >= cap.sectors) + break; + nSize <<= 1; + nShift++; + } + + // 繧サ繧ッ繧ソ逡ェ蜿キ險育ョ + // + // 莉・荳九ョ鬆縺ォ荳ヲ縺ケ繧九 + // 繧ッ繝ゥ繧ケ繧ソ0: 譛ェ菴ソ逕ィ + // 繧ッ繝ゥ繧ケ繧ソ1: FAT + // 繧ッ繝ゥ繧ケ繧ソ2: 繝ォ繝シ繝医ョ繧」繝ャ繧ッ繝医Μ + // 繧ッ繝ゥ繧ケ繧ソ3: 繝繝シ繧ソ鬆伜沺(謫ャ莨シ繧サ繧ッ繧ソ) + DWORD nFat = cap.sectors; + DWORD nRoot = cap.sectors * 2; + DWORD nData = cap.sectors * 3; + + // DPB險ュ螳 + pDpb->sector_size = (WORD)cap.bytes; // 1繧サ繧ッ繧ソ蠖薙j縺ョ繝舌う繝域焚 + pDpb->cluster_size = + (BYTE)(cap.sectors - 1); // 1繧ッ繝ゥ繧ケ繧ソ蠖薙j縺ョ繧サ繧ッ繧ソ謨ー - 1 + pDpb->shift = (BYTE)nShift; // 繧ッ繝ゥ繧ケ繧ソ竊偵そ繧ッ繧ソ縺ョ繧キ繝輔ヨ謨ー + pDpb->fat_sector = (WORD)nFat; // FAT 縺ョ蜈磯ュ繧サ繧ッ繧ソ逡ェ蜿キ + pDpb->fat_max = 1; // FAT 鬆伜沺縺ョ蛟区焚 + pDpb->fat_size = (BYTE)cap.sectors; // FAT 縺ョ蜊繧√k繧サ繧ッ繧ソ謨ー(隍蜀吝繧帝勁縺) + pDpb->file_max = + (WORD)(cap.sectors * cap.bytes / 0x20); // 繝ォ繝シ繝医ョ繧」繝ャ繧ッ繝医Μ縺ォ蜈・繧九ヵ繧。繧、繝ォ縺ョ蛟区焚 + pDpb->data_sector = (WORD)nData; // 繝繝シ繧ソ鬆伜沺縺ョ蜈磯ュ繧サ繧ッ繧ソ逡ェ蜿キ + pDpb->cluster_max = (WORD)cap.clusters; // 邱上け繝ゥ繧ケ繧ソ謨ー + 1 + pDpb->root_sector = (WORD)nRoot; // 繝ォ繝シ繝医ョ繧」繝ャ繧ッ繝医Μ縺ョ蜈磯ュ繧サ繧ッ繧ソ逡ェ蜿キ + pDpb->media = media; // 繝。繝繧」繧「繝舌う繝 + + return 0; +} + +//--------------------------------------------------------------------------- +// +/// $53 - 繧サ繧ッ繧ソ隱ュ縺ソ霎シ縺ソ +/// +/// 繧サ繧ッ繧ソ縺ッ逍台シシ逧縺ォ讒狗ッ峨@縺溘b縺ョ繧剃スソ逕ィ縺吶k縲 +/// 繝舌ャ繝輔ぃ繧オ繧、繧コ縺ッ$200繝舌う繝亥崋螳壹 +// +//--------------------------------------------------------------------------- +int CFileSys::DiskRead(DWORD nUnit, BYTE* pBuffer, DWORD nSector, DWORD nSize) +{ + ASSERT(this); + ASSERT(pBuffer); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + if (nUnit >= m_nUnits) + return FS_FATAL_MEDIAOFFLINE; // 繝ャ繧ク繝・繝シ繝蠕後↓辟。蜉ケ縺ェ繝峨Λ繧、繝紋ク翫〒逋コ逕 + + // 繝。繝繧」繧「繝√ぉ繝繧ッ + if (m_cEntry.isMediaOffline(nUnit)) + return FS_FATAL_MEDIAOFFLINE; + + // 繧サ繧ッ繧ソ謨ー1莉・螟悶ョ蝣エ蜷医ッ繧ィ繝ゥ繝シ + if (nSize != 1) + return FS_INVALIDPRM; + + // 繧サ繧ッ繧ソ諠蝣ア迯イ蠕 + Human68k::capacity_t cap; + if (m_cEntry.GetCapacityCache(nUnit, &cap) == FALSE) { + // 繝峨Λ繧、繝也憾諷句叙蠕 + m_cEntry.GetCapacity(nUnit, &cap); + } + + // 謫ャ莨シ繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ縺ク縺ョ繧「繧ッ繧サ繧ケ + CHostFiles* pHostFiles = m_cFiles.Search(nSector); + if (pHostFiles) { + // 謫ャ莨シ繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ繧堤函謌 + Human68k::dirent_t* dir = (Human68k::dirent_t*)pBuffer; + memcpy(pBuffer, pHostFiles->GetEntry(), sizeof(*dir)); + memset(pBuffer + sizeof(*dir), 0xE5, 0x200 - sizeof(*dir)); + + // 謫ャ莨シ繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ蜀縺ォ繝輔ぃ繧、繝ォ螳滉ス薙r謖縺呎闘莨シ繧サ繧ッ繧ソ逡ェ蜿キ繧定ィ倬鹸 + // 縺ェ縺翫〕zdsys縺ァ縺ッ莉・荳九ョ蠑上〒隱ュ縺ソ霎シ縺ソ繧サ繧ッ繧ソ逡ェ蜿キ繧堤ョ怜コ縺励※縺繧九 + // (dirent.cluster - 2) * (dpb.cluster_size + 1) + dpb.data_sector + /// @warning 繝ェ繝医Ν繧ィ繝ウ繝繧」繧「繝ウ蟆ら畑 + dir->cluster = (WORD)(m_nHostSectorCount + 2); // 謫ャ莨シ繧サ繧ッ繧ソ逡ェ蜿キ + m_nHostSectorBuffer[m_nHostSectorCount] = nSector; // 謫ャ莨シ繧サ繧ッ繧ソ縺ョ謖縺吝ョ滉ス + m_nHostSectorCount++; + m_nHostSectorCount %= XM6_HOST_PSEUDO_CLUSTER_MAX; + + return 0; + } + + // 繧ッ繝ゥ繧ケ繧ソ逡ェ蜿キ縺九i繧サ繧ッ繧ソ逡ェ蜿キ繧堤ョ怜コ + DWORD n = nSector - (3 * cap.sectors); + DWORD nMod = 1; + if (cap.sectors) { + // 繝。繝繧」繧「縺悟ュ伜惠縺励↑縺蝣エ蜷医ッcap.sectors縺0縺ォ縺ェ繧九ョ縺ァ豕ィ諢 + nMod = n % cap.sectors; + n /= cap.sectors; + } + + // 繝輔ぃ繧、繝ォ螳滉ス薙∈縺ョ繧「繧ッ繧サ繧ケ + if (nMod == 0 && n < XM6_HOST_PSEUDO_CLUSTER_MAX) { + pHostFiles = m_cFiles.Search(m_nHostSectorBuffer[n]); // 螳滉ス薙r讀懃エ「 + if (pHostFiles) { + // 謫ャ莨シ繧サ繧ッ繧ソ繧堤函謌 + CHostFcb f; + f.SetFilename(pHostFiles->GetPath()); + f.SetMode(Human68k::OP_READ); + if (f.Open() == FALSE) + return FS_INVALIDPRM; + memset(pBuffer, 0, 0x200); + DWORD nResult = f.Read(pBuffer, 0x200); + f.Close(); + if (nResult == (DWORD)-1) + return FS_INVALIDPRM; + + return 0; + } + } + + return FS_INVALIDPRM; +} + +//--------------------------------------------------------------------------- +// +/// $54 - 繧サ繧ッ繧ソ譖ク縺崎セシ縺ソ +// +//--------------------------------------------------------------------------- +int CFileSys::DiskWrite(DWORD nUnit) +{ + ASSERT(this); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + ASSERT(nUnit < m_nUnits); + if (nUnit >= m_nUnits) + return FS_FATAL_MEDIAOFFLINE; // 蠢オ縺ョ縺溘a + + // 繝。繝繧」繧「繝√ぉ繝繧ッ + if (m_cEntry.isMediaOffline(nUnit)) + return FS_FATAL_MEDIAOFFLINE; + + // 譖ク縺崎セシ縺ソ遖∵ュ「繝√ぉ繝繧ッ + if (m_cEntry.isWriteProtect(nUnit)) + return FS_FATAL_WRITEPROTECT; + + // 迴セ螳溘r遯√″縺、縺代k + return FS_INVALIDPRM; +} + +//--------------------------------------------------------------------------- +// +/// $55 - IOCTRL +// +//--------------------------------------------------------------------------- +int CFileSys::Ioctrl(DWORD nUnit, DWORD nFunction, Human68k::ioctrl_t* pIoctrl) +{ + ASSERT(this); + ASSERT(pIoctrl); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + if (nUnit >= m_nUnits) + return FS_INVALIDFUNC; // 繝ャ繧ク繝・繝シ繝蠕後↓辟。蜉ケ縺ェ繝峨Λ繧、繝悶〒mint謫堺ス懈凾縺ォ逋ス蟶ッ繧貞コ縺輔↑縺繧医≧謾ケ濶ッ + + switch (nFunction) { + case 0: + // 繝。繝繧」繧「繝舌う繝医ョ迯イ蠕 + pIoctrl->media = m_cEntry.GetMediaByte(nUnit); + return 0; + + case 1: + // Human68k莠呈鋤縺ョ縺溘a縺ョ繝繝溘シ + pIoctrl->param = (unsigned long)-1; + return 0; + + case 2: + switch (pIoctrl->param) { + case -1: + // 繝。繝繧」繧「蜀崎ェ崎ュ + m_cEntry.isMediaOffline(nUnit); + return 0; + + case 0: + case 1: + // Human68k莠呈鋤縺ョ縺溘a縺ョ繝繝溘シ + return 0; + } + break; + + case -1: + // 蟶ク鬧仙愛螳 + memcpy(pIoctrl->buffer, "WindrvXM", 8); + return 0; + + case -2: + // 繧ェ繝励す繝ァ繝ウ險ュ螳 + SetOption(pIoctrl->param); + return 0; + + case -3: + // 繧ェ繝励す繝ァ繝ウ迯イ蠕 + pIoctrl->param = GetOption(); + return 0; + } + + return FS_NOTIOCTRL; +} + +//--------------------------------------------------------------------------- +// +/// $56 - 繝輔Λ繝繧キ繝・ +// +//--------------------------------------------------------------------------- +int CFileSys::Flush(DWORD nUnit) +{ + ASSERT(this); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + if (nUnit >= m_nUnits) + return FS_INVALIDFUNC; // 繝ャ繧ク繝・繝シ繝蠕後↓辟。蜉ケ縺ェ繝峨Λ繧、繝悶〒mint縺九i繧ウ繝槭Φ繝峨r螳溯。後@謌サ繧区凾縺ォ逋ス蟶ッ繧貞コ縺輔↑縺繧医≧謾ケ濶ッ + + // 蟶ク縺ォ謌仙粥 + return 0; +} + +//--------------------------------------------------------------------------- +// +/// $57 - 繝。繝繧」繧「莠、謠帙メ繧ァ繝繧ッ +// +//--------------------------------------------------------------------------- +int CFileSys::CheckMedia(DWORD nUnit) +{ + ASSERT(this); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + if (nUnit >= m_nUnits) + return FS_INVALIDFUNC; // 繝ャ繧ク繝・繝シ繝蠕後↓辟。蜉ケ縺ェ繝峨Λ繧、繝悶〒mint謫堺ス懈凾縺ォ逋ス蟶ッ繧貞コ縺輔↑縺繧医≧謾ケ濶ッ + + // 繝。繝繧」繧「莠、謠帙メ繧ァ繝繧ッ + m_cEntry.CleanCache(nUnit); + return 0; +} + +//--------------------------------------------------------------------------- +// +/// $58 - 謗剃サ門宛蠕。 +// +//--------------------------------------------------------------------------- +int CFileSys::Lock(DWORD nUnit) +{ + ASSERT(this); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + ASSERT(nUnit < m_nUnits); + if (nUnit >= m_nUnits) + return FS_FATAL_MEDIAOFFLINE; // 蠢オ縺ョ縺溘a + + // 繝。繝繧」繧「繝√ぉ繝繧ッ + if (m_cEntry.isMediaOffline(nUnit)) + return FS_FATAL_MEDIAOFFLINE; + + // 蟶ク縺ォ謌仙粥 + return 0; +} + +//--------------------------------------------------------------------------- +// +/// 繧ェ繝励す繝ァ繝ウ險ュ螳 +// +//--------------------------------------------------------------------------- +void CFileSys::SetOption(DWORD nOption) +{ + ASSERT(this); + + // 繧ェ繝励す繝ァ繝ウ險ュ螳壼、画峩縺ァ繧ュ繝」繝繧キ繝・繧ッ繝ェ繧「 + if (m_nOption ^ nOption) + m_cEntry.CleanCache(); + + m_nOption = nOption; + g_nOption = nOption; +} + +//--------------------------------------------------------------------------- +// +/// 繧ェ繝励す繝ァ繝ウ蛻晄悄蛹 +// +//--------------------------------------------------------------------------- +void CFileSys::InitOption(const Human68k::argument_t* pArgument) +{ + ASSERT(this); + ASSERT(pArgument); + + // 繝峨Λ繧、繝匁焚繧貞晄悄蛹 + m_nDrives = 0; + + const BYTE* pp = pArgument->buf; + pp += strlen((const char*)pp) + 1; + + DWORD nOption = m_nOptionDefault; + for (;;) { + ASSERT(pp < pArgument->buf + sizeof(*pArgument)); + const BYTE* p = pp; + BYTE c = *p++; + if (c == '\0') + break; + + DWORD nMode; + if (c == '+') { + nMode = 1; + } else if (c == '-') { + nMode = 0; + } else if (c == '/') { + // 繝繝輔か繝ォ繝医吶シ繧ケ繝代せ縺ョ謖螳 + if (m_nDrives < DriveMax) { + p--; + strcpy(m_szBase[m_nDrives], (const char *)p); + m_nDrives++; + } + pp += strlen((const char*)pp) + 1; + continue; + } else { + // 繧ェ繝励す繝ァ繝ウ謖螳壹〒縺ッ縺ェ縺縺ョ縺ァ谺。縺ク + pp += strlen((const char*)pp) + 1; + continue; + } + + for (;;) { + c = *p++; + if (c == '\0') + break; + + DWORD nBit = 0; + switch (c) { + case 'A': case 'a': nBit = WINDRV_OPT_CONVERT_LENGTH; break; + case 'T': case 't': nBit = WINDRV_OPT_COMPARE_LENGTH; nMode ^= 1; break; + case 'C': case 'c': nBit = WINDRV_OPT_ALPHABET; break; + + case 'E': nBit = WINDRV_OPT_CONVERT_PERIOD; break; + case 'P': nBit = WINDRV_OPT_CONVERT_PERIODS; break; + case 'N': nBit = WINDRV_OPT_CONVERT_HYPHEN; break; + case 'H': nBit = WINDRV_OPT_CONVERT_HYPHENS; break; + case 'X': nBit = WINDRV_OPT_CONVERT_BADCHAR; break; + case 'S': nBit = WINDRV_OPT_CONVERT_SPACE; break; + + case 'e': nBit = WINDRV_OPT_REDUCED_PERIOD; break; + case 'p': nBit = WINDRV_OPT_REDUCED_PERIODS; break; + case 'n': nBit = WINDRV_OPT_REDUCED_HYPHEN; break; + case 'h': nBit = WINDRV_OPT_REDUCED_HYPHENS; break; + case 'x': nBit = WINDRV_OPT_REDUCED_BADCHAR; break; + case 's': nBit = WINDRV_OPT_REDUCED_SPACE; break; + } + + if (nMode) + nOption |= nBit; + else + nOption &= ~nBit; + } + + pp = p; + } + + // 繧ェ繝励す繝ァ繝ウ險ュ螳 + if (nOption != m_nOption) { + SetOption(nOption); + } +} + +//--------------------------------------------------------------------------- +// +/// 繝懊Μ繝・繝シ繝繝ゥ繝吶Ν蜿門セ +// +//--------------------------------------------------------------------------- +BOOL CFileSys::FilesVolume(DWORD nUnit, Human68k::files_t* pFiles) +{ + ASSERT(this); + ASSERT(pFiles); + + // 繝懊Μ繝・繝シ繝繝ゥ繝吶Ν蜿門セ + TCHAR szVolume[32]; + BOOL bResult = m_cEntry.GetVolumeCache(nUnit, szVolume); + if (bResult == FALSE) { + // 謇句虚繧、繧ク繧ァ繧ッ繝医□縺ィ繝。繝繧」繧「繝√ぉ繝繧ッ繧偵☆繧頑栢縺代k縺溘a縺薙%縺ァ謐墓拷 + if (m_cEntry.isEnable(nUnit) == FALSE) + return FALSE; + + // 繝。繝繧」繧「繝√ぉ繝繧ッ + if (m_cEntry.isMediaOffline(nUnit)) + return FALSE; + + // 繝懊Μ繝・繝シ繝繝ゥ繝吶Ν蜿門セ + m_cEntry.GetVolume(nUnit, szVolume); + } + if (szVolume[0] == _T('\0')) + return FALSE; + + pFiles->attr = Human68k::AT_VOLUME; + pFiles->time = 0; + pFiles->date = 0; + pFiles->size = 0; + + CHostFilename fname; + fname.SetHost(szVolume); + fname.ConvertHuman(); + strcpy((char*)pFiles->full, (const char*)fname.GetHuman()); + + return TRUE; +} diff --git a/src/raspberrypi/cfilesystem.h b/src/raspberrypi/cfilesystem.h new file mode 100644 index 00000000..58dabe8e --- /dev/null +++ b/src/raspberrypi/cfilesystem.h @@ -0,0 +1,1157 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technology. +// Copyright (C) 2016-2018 GIMONS +// [ 繝帙せ繝医ヵ繧。繧、繝ォ繧キ繧ケ繝繝 ] +// +//--------------------------------------------------------------------------- + +#ifndef cfilesystem_h +#define cfilesystem_h + +//--------------------------------------------------------------------------- +// +// 繧ケ繝繝シ繧ソ繧ケ繧ウ繝シ繝牙ョ夂セゥ +// +//--------------------------------------------------------------------------- +#define FS_INVALIDFUNC 0xFFFFFFFF ///< 辟。蜉ケ縺ェ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ繧ウ繝シ繝峨r螳溯。後@縺 +#define FS_FILENOTFND 0xFFFFFFFE ///< 謖螳壹@縺溘ヵ繧。繧、繝ォ縺瑚ヲ九▽縺九i縺ェ縺 +#define FS_DIRNOTFND 0xFFFFFFFD ///< 謖螳壹@縺溘ョ繧」繝ャ繧ッ繝医Μ縺瑚ヲ九▽縺九i縺ェ縺 +#define FS_OVEROPENED 0xFFFFFFFC ///< 繧ェ繝シ繝励Φ縺励※縺繧九ヵ繧。繧、繝ォ縺悟、壹☆縺弱k +#define FS_CANTACCESS 0xFFFFFFFB ///< 繝繧」繝ャ繧ッ繝医Μ繧繝懊Μ繝・繝シ繝繝ゥ繝吶Ν縺ッ繧「繧ッ繧サ繧ケ荳榊庄 +#define FS_NOTOPENED 0xFFFFFFFA ///< 謖螳壹@縺溘ワ繝ウ繝峨Ν縺ッ繧ェ繝シ繝励Φ縺輔l縺ヲ縺縺ェ縺 +#define FS_INVALIDMEM 0xFFFFFFF9 ///< 繝。繝「繝ェ邂。逅鬆伜沺縺檎エ螢翫&繧後◆ +#define FS_OUTOFMEM 0xFFFFFFF8 ///< 螳溯。後↓蠢隕√↑繝。繝「繝ェ縺後↑縺 +#define FS_INVALIDPTR 0xFFFFFFF7 ///< 辟。蜉ケ縺ェ繝。繝「繝ェ邂。逅繝昴う繝ウ繧ソ繧呈欠螳壹@縺 +#define FS_INVALIDENV 0xFFFFFFF6 ///< 荳肴ュ」縺ェ迺ー蠅繧呈欠螳壹@縺 +#define FS_ILLEGALFMT 0xFFFFFFF5 ///< 螳溯。後ヵ繧。繧、繝ォ縺ョ繝輔か繝シ繝槭ャ繝医′逡ー蟶ク +#define FS_ILLEGALMOD 0xFFFFFFF4 ///< 繧ェ繝シ繝励Φ縺ョ繧「繧ッ繧サ繧ケ繝「繝シ繝峨′逡ー蟶ク +#define FS_INVALIDPATH 0xFFFFFFF3 ///< 繝輔ぃ繧、繝ォ蜷阪ョ謖螳壹↓隱、繧翫′縺ゅk +#define FS_INVALIDPRM 0xFFFFFFF2 ///< 辟。蜉ケ縺ェ繝代Λ繝。繝シ繧ソ縺ァ繧ウ繝シ繝ォ縺励◆ +#define FS_INVALIDDRV 0xFFFFFFF1 ///< 繝峨Λ繧、繝匁欠螳壹↓隱、繧翫′縺ゅk +#define FS_DELCURDIR 0xFFFFFFF0 ///< 繧ォ繝ャ繝ウ繝医ョ繧」繝ャ繧ッ繝医Μ縺ッ蜑企勁縺ァ縺阪↑縺 +#define FS_NOTIOCTRL 0xFFFFFFEF ///< IOCTRL縺ァ縺阪↑縺繝繝舌う繧ケ +#define FS_LASTFILE 0xFFFFFFEE ///< 縺薙l莉・荳翫ヵ繧。繧、繝ォ縺瑚ヲ九▽縺九i縺ェ縺 +#define FS_CANTWRITE 0xFFFFFFED ///< 謖螳壹ョ繝輔ぃ繧、繝ォ縺ッ譖ク縺崎セシ縺ソ縺ァ縺阪↑縺 +#define FS_DIRALREADY 0xFFFFFFEC ///< 謖螳壹ョ繝繧」繝ャ繧ッ繝医Μ縺ッ譌「縺ォ逋サ骭イ縺輔l縺ヲ縺繧 +#define FS_CANTDELETE 0xFFFFFFEB ///< 繝輔ぃ繧、繝ォ縺後≠繧九ョ縺ァ蜑企勁縺ァ縺阪↑縺 +#define FS_CANTRENAME 0xFFFFFFEA ///< 繝輔ぃ繧、繝ォ縺後≠繧九ョ縺ァ繝ェ繝阪シ繝縺ァ縺阪↑縺 +#define FS_DISKFULL 0xFFFFFFE9 ///< 繝繧」繧ケ繧ッ縺御ク譚ッ縺ァ繝輔ぃ繧、繝ォ縺御ス懊l縺ェ縺 +#define FS_DIRFULL 0xFFFFFFE8 ///< 繝繧」繝ャ繧ッ繝医Μ縺御ク譚ッ縺ァ繝輔ぃ繧、繝ォ縺御ス懊l縺ェ縺 +#define FS_CANTSEEK 0xFFFFFFE7 ///< 謖螳壹ョ菴咲スョ縺ォ縺ッ繧キ繝シ繧ッ縺ァ縺阪↑縺 +#define FS_SUPERVISOR 0xFFFFFFE6 ///< 繧ケ繝シ繝代シ繝舌う繧カ迥カ諷九〒繧ケ繝シ繝代ヰ繧、繧カ謖螳壹@縺 +#define FS_THREADNAME 0xFFFFFFE5 ///< 蜷後§繧ケ繝ャ繝繝牙錐縺悟ュ伜惠縺吶k +#define FS_BUFWRITE 0xFFFFFFE4 ///< 繝励Ο繧サ繧ケ髢馴壻ソ。縺ョ繝舌ャ繝輔ぃ縺梧嶌霎シ縺ソ遖∵ュ「 +#define FS_BACKGROUND 0xFFFFFFE3 ///< 繝舌ャ繧ッ繧ー繝ゥ繧ヲ繝ウ繝峨励Ο繧サ繧ケ繧定オキ蜍輔〒縺阪↑縺 +#define FS_OUTOFLOCK 0xFFFFFFE0 ///< 繝ュ繝繧ッ鬆伜沺縺瑚カウ繧翫↑縺 +#define FS_LOCKED 0xFFFFFFDF ///< 繝ュ繝繧ッ縺輔l縺ヲ縺縺ヲ繧「繧ッ繧サ繧ケ縺ァ縺阪↑縺 +#define FS_DRIVEOPENED 0xFFFFFFDE ///< 謖螳壹ョ繝峨Λ繧、繝悶ッ繝上Φ繝峨Λ縺後が繝シ繝励Φ縺輔l縺ヲ縺繧 +#define FS_LINKOVER 0xFFFFFFDD ///< 繧キ繝ウ繝懊Μ繝繧ッ繝ェ繝ウ繧ッ繝阪せ繝医′16蝗槭r雜縺医◆ +#define FS_FILEEXIST 0xFFFFFFB0 ///< 繝輔ぃ繧、繝ォ縺悟ュ伜惠縺吶k + +#define FS_FATAL_MEDIAOFFLINE 0xFFFFFFA3 ///< 繝。繝繧」繧「縺悟・縺」縺ヲ縺縺ェ縺 +#define FS_FATAL_WRITEPROTECT 0xFFFFFFA2 ///< 譖ク縺崎セシ縺ソ遖∵ュ「驕募渚 +#define FS_FATAL_INVALIDCOMMAND 0xFFFFFFA1 ///< 荳肴ュ」縺ェ繧ウ繝槭Φ繝臥分蜿キ +#define FS_FATAL_INVALIDUNIT 0xFFFFFFA0 ///< 荳肴ュ」縺ェ繝ヲ繝九ャ繝育分蜿キ + +#define HUMAN68K_PATH_MAX 96 ///< Human68k縺ョ繝代せ譛螟ァ髟キ + +//=========================================================================== +// +/// Human68k 蜷榊燕遨コ髢 +// +//=========================================================================== +namespace Human68k { + /// 繝輔ぃ繧、繝ォ螻樊ァ繝薙ャ繝 + enum attribute_t { + AT_READONLY = 0x01, ///< 隱ュ縺ソ霎シ縺ソ蟆ら畑螻樊ァ + AT_HIDDEN = 0x02, ///< 髫縺怜ア樊ァ + AT_SYSTEM = 0x04, ///< 繧キ繧ケ繝繝螻樊ァ + AT_VOLUME = 0x08, ///< 繝懊Μ繝・繝シ繝繝ゥ繝吶Ν螻樊ァ + AT_DIRECTORY = 0x10, ///< 繝繧」繝ャ繧ッ繝医Μ螻樊ァ + AT_ARCHIVE = 0x20, ///< 繧「繝シ繧ォ繧、繝門ア樊ァ + AT_ALL = 0xFF, ///< 蜈ィ縺ヲ縺ョ螻樊ァ繝薙ャ繝医′1 + }; + + /// 繝輔ぃ繧、繝ォ繧ェ繝シ繝励Φ繝「繝シ繝 + enum open_t { + OP_READ = 0, ///< 隱ュ縺ソ霎シ縺ソ + OP_WRITE = 1, ///< 譖ク縺崎セシ縺ソ + OP_FULL = 2, ///< 隱ュ縺ソ譖ク縺 + OP_MASK = 0x0F, ///< 蛻、螳夂畑繝槭せ繧ッ + OP_SHARE_NONE = 0x10, ///< 蜈ア譛臥ヲ∵ュ「 + OP_SHARE_READ = 0x20, ///< 隱ュ縺ソ霎シ縺ソ蜈ア譛 + OP_SHARE_WRITE = 0x30, ///< 譖ク縺崎セシ縺ソ蜈ア譛 + OP_SHARE_FULL = 0x40, ///< 隱ュ縺ソ譖ク縺榊ア譛 + OP_SHARE_MASK = 0x70, ///< 蜈ア譛牙愛螳夂畑繝槭せ繧ッ + OP_SPECIAL = 0x100, ///< 霎樊嶌繧「繧ッ繧サ繧ケ + }; + + /// 繧キ繝シ繧ッ遞ョ鬘 + enum seek_t { + SK_BEGIN = 0, ///< 繝輔ぃ繧、繝ォ蜈磯ュ縺九i + SK_CURRENT = 1, ///< 迴セ蝨ィ菴咲スョ縺九i + SK_END = 2, ///< 繝輔ぃ繧、繝ォ譛ォ蟆セ縺九i + }; + + /// 繝。繝繧」繧「繝舌う繝 + enum media_t { + MEDIA_2DD_10 = 0xE0, ///< 2DD/10繧サ繧ッ繧ソ + MEDIA_1D_9 = 0xE5, ///< 1D/9繧サ繧ッ繧ソ + MEDIA_2D_9 = 0xE6, ///< 2D/9繧サ繧ッ繧ソ + MEDIA_1D_8 = 0xE7, ///< 1D/8繧サ繧ッ繧ソ + MEDIA_2D_8 = 0xE8, ///< 2D/8繧サ繧ッ繧ソ + MEDIA_2HT = 0xEA, ///< 2HT + MEDIA_2HS = 0xEB, ///< 2HS + MEDIA_2HDE = 0xEC, ///< 2DDE + MEDIA_1DD_9 = 0xEE, ///< 1DD/9繧サ繧ッ繧ソ + MEDIA_1DD_8 = 0xEF, ///< 1DD/8繧サ繧ッ繧ソ + MEDIA_MANUAL = 0xF1, ///< 繝ェ繝「繝シ繝医ラ繝ゥ繧、繝 (謇句虚繧、繧ク繧ァ繧ッ繝) + MEDIA_REMOVABLE = 0xF2, ///< 繝ェ繝「繝シ繝医ラ繝ゥ繧、繝 (繝ェ繝繝シ繝舌ヶ繝ォ) + MEDIA_REMOTE = 0xF3, ///< 繝ェ繝「繝シ繝医ラ繝ゥ繧、繝 + MEDIA_DAT = 0xF4, ///< SCSI-DAT + MEDIA_CDROM = 0xF5, ///< SCSI-CDROM + MEDIA_MO = 0xF6, ///< SCSI-MO + MEDIA_SCSI_HD = 0xF7, ///< SCSI-HD + MEDIA_SASI_HD = 0xF8, ///< SASI-HD + MEDIA_RAMDISK = 0xF9, ///< RAM繝繧」繧ケ繧ッ + MEDIA_2HQ = 0xFA, ///< 2HQ + MEDIA_2DD_8 = 0xFB, ///< 2DD/8繧サ繧ッ繧ソ + MEDIA_2DD_9 = 0xFC, ///< 2DD/9繧サ繧ッ繧ソ + MEDIA_2HC = 0xFD, ///< 2HC + MEDIA_2HD = 0xFE, ///< 2HD + }; + + /// namests讒矩菴 + struct namests_t { + BYTE wildcard; ///< 繝ッ繧、繝ォ繝峨き繝シ繝画枚蟄玲焚 + BYTE drive; ///< 繝峨Λ繧、繝也分蜿キ + BYTE path[65]; ///< 繝代せ(繧オ繝悶ョ繧」繝ャ繧ッ繝医Μ+/) + BYTE name[8]; ///< 繝輔ぃ繧、繝ォ蜷 (PADDING 0x20) + BYTE ext[3]; ///< 諡。蠑オ蟄 (PADDING 0x20) + BYTE add[10]; ///< 繝輔ぃ繧、繝ォ蜷崎ソス蜉 (PADDING 0x00) + + // 譁蟄怜怜叙蠕 + void FASTCALL GetCopyPath(BYTE* szPath) const; + ///< 繝代せ蜷榊叙蠕 + void FASTCALL GetCopyFilename(BYTE* szFilename) const; + ///< 繝輔ぃ繧、繝ォ蜷榊叙蠕 + }; + + /// files讒矩菴 + struct files_t { + BYTE fatr; ///< + 0 讀懃エ「縺吶k螻樊ァ 隱ュ霎シ蟆ら畑 + // BYTE drive; ///< + 1 繝峨Λ繧、繝也分蜿キ 隱ュ霎シ蟆ら畑 + DWORD sector; ///< + 2 繝繧」繝ャ繧ッ繝医Μ縺ョ繧サ繧ッ繧ソ DOS _FILES蜈磯ュ繧「繝峨Ξ繧ケ縺ァ莉」逕ィ + // WORD cluster; ///< + 6 繝繧」繝ャ繧ッ繝医Μ縺ョ繧ッ繝ゥ繧ケ繧ソ 隧ウ邏ー荳肴 (譛ェ菴ソ逕ィ) + WORD offset; ///< + 8 繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ 譖ク霎シ蟆ら畑 + // BYTE name[8]; ///< +10 菴懈・ュ逕ィ繝輔ぃ繧、繝ォ蜷 隱ュ霎シ蟆ら畑 (譛ェ菴ソ逕ィ) + // BYTE ext[3]; ///< +18 菴懈・ュ逕ィ諡。蠑オ蟄 隱ュ霎シ蟆ら畑 (譛ェ菴ソ逕ィ) + BYTE attr; ///< +21 繝輔ぃ繧、繝ォ螻樊ァ 譖ク霎シ蟆ら畑 + WORD time; ///< +22 譛邨ょ、画峩譎ょ綾 譖ク霎シ蟆ら畑 + WORD date; ///< +24 譛邨ょ、画峩譛域律 譖ク霎シ蟆ら畑 + DWORD size; ///< +26 繝輔ぃ繧、繝ォ繧オ繧、繧コ 譖ク霎シ蟆ら畑 + BYTE full[23]; ///< +30 繝輔Ν繝輔ぃ繧、繝ォ蜷 譖ク霎シ蟆ら畑 + }; + + /// FCB讒矩菴 + struct fcb_t { + // BYTE pad00[6]; ///< + 0ス+ 5 (譛ェ菴ソ逕ィ) + DWORD fileptr; ///< + 6ス+ 9 繝輔ぃ繧、繝ォ繝昴う繝ウ繧ソ + // BYTE pad01[4]; ///< +10ス+13 (譛ェ菴ソ逕ィ) + WORD mode; ///< +14ス+15 繧ェ繝シ繝励Φ繝「繝シ繝 + // BYTE pad02[16]; ///< +16ス+31 (譛ェ菴ソ逕ィ) + // DWORD zero; ///< +32ス+35 繧ェ繝シ繝励Φ縺ョ縺ィ縺0縺梧嶌縺崎セシ縺セ繧後※縺繧 (譛ェ菴ソ逕ィ) + // BYTE name[8]; ///< +36ス+43 繝輔ぃ繧、繝ォ蜷 (PADDING 0x20) (譛ェ菴ソ逕ィ) + // BYTE ext[3]; ///< +44ス+46 諡。蠑オ蟄 (PADDING 0x20) (譛ェ菴ソ逕ィ) + BYTE attr; ///< +47 繝輔ぃ繧、繝ォ螻樊ァ + // BYTE add[10]; ///< +48ス+57 繝輔ぃ繧、繝ォ蜷崎ソス蜉 (PADDING 0x00) (譛ェ菴ソ逕ィ) + WORD time; ///< +58ス+59 譛邨ょ、画峩譎ょ綾 + WORD date; ///< +60ス+61 譛邨ょ、画峩譛域律 + // WORD cluster; ///< +62ス+63 繧ッ繝ゥ繧ケ繧ソ逡ェ蜿キ (譛ェ菴ソ逕ィ) + DWORD size; ///< +64ス+67 繝輔ぃ繧、繝ォ繧オ繧、繧コ + // BYTE pad03[28]; ///< +68ス+95 FAT繧ュ繝」繝繧キ繝・ (譛ェ菴ソ逕ィ) + }; + + /// capacity讒矩菴 + struct capacity_t { + WORD freearea; ///< + 0 菴ソ逕ィ蜿ッ閭ス縺ェ繧ッ繝ゥ繧ケ繧ソ謨ー + WORD clusters; ///< + 2 邱上け繝ゥ繧ケ繧ソ謨ー + WORD sectors; ///< + 4 繧ッ繝ゥ繧ケ繧ソ縺ゅ◆繧翫ョ繧サ繧ッ繧ソ謨ー + WORD bytes; ///< + 6 繧サ繧ッ繧ソ蠖薙◆繧翫ョ繝舌う繝域焚 + }; + + /// ctrldrive讒矩菴 + struct ctrldrive_t { + BYTE status; ///< +13 迥カ諷 + BYTE pad[3]; ///< Padding + }; + + /// DPB讒矩菴 + struct dpb_t { + WORD sector_size; ///< + 0 1繧サ繧ッ繧ソ蠖薙j縺ョ繝舌う繝域焚 + BYTE cluster_size; ///< + 2 1繧ッ繝ゥ繧ケ繧ソ蠖薙j縺ョ繧サ繧ッ繧ソ謨ー-1 + BYTE shift; ///< + 3 繧ッ繝ゥ繧ケ繧ソ竊偵そ繧ッ繧ソ縺ョ繧キ繝輔ヨ謨ー + WORD fat_sector; ///< + 4 FAT縺ョ蜈磯ュ繧サ繧ッ繧ソ逡ェ蜿キ + BYTE fat_max; ///< + 6 FAT鬆伜沺縺ョ蛟区焚 + BYTE fat_size; ///< + 7 FAT縺ョ蜊繧√k繧サ繧ッ繧ソ謨ー(隍蜀吝繧帝勁縺) + WORD file_max; ///< + 8 繝ォ繝シ繝医ョ繧」繝ャ繧ッ繝医Μ縺ォ蜈・繧九ヵ繧。繧、繝ォ縺ョ蛟区焚 + WORD data_sector; ///< +10 繝繝シ繧ソ鬆伜沺縺ョ蜈磯ュ繧サ繧ッ繧ソ逡ェ蜿キ + WORD cluster_max; ///< +12 邱上け繝ゥ繧ケ繧ソ謨ー+1 + WORD root_sector; ///< +14 繝ォ繝シ繝医ョ繧」繝ャ繧ッ繝医Μ縺ョ蜈磯ュ繧サ繧ッ繧ソ逡ェ蜿キ + // DWORD driverentry; ///< +16 繝繝舌う繧ケ繝峨Λ繧、繝舌∈縺ョ繝昴う繝ウ繧ソ (譛ェ菴ソ逕ィ) + BYTE media; ///< +20 繝。繝繧」繧「隴伜挨蟄 + // BYTE flag; ///< +21 DPB菴ソ逕ィ繝輔Λ繧ー (譛ェ菴ソ逕ィ) + }; + + /// 繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ讒矩菴 + struct dirent_t { + BYTE name[8]; ///< + 0 繝輔ぃ繧、繝ォ蜷 (PADDING 0x20) + BYTE ext[3]; ///< + 8 諡。蠑オ蟄 (PADDING 0x20) + BYTE attr; ///< +11 繝輔ぃ繧、繝ォ螻樊ァ + BYTE add[10]; ///< +12 繝輔ぃ繧、繝ォ蜷崎ソス蜉 (PADDING 0x00) + WORD time; ///< +22 譛邨ょ、画峩譎ょ綾 + WORD date; ///< +24 譛邨ょ、画峩譛域律 + WORD cluster; ///< +26 繧ッ繝ゥ繧ケ繧ソ逡ェ蜿キ + DWORD size; ///< +28 繝輔ぃ繧、繝ォ繧オ繧、繧コ + }; + + /// IOCTRL繝代Λ繝。繝シ繧ソ蜈ア逕ィ菴 + union ioctrl_t { + BYTE buffer[8]; ///< 繝舌う繝亥腰菴阪〒縺ョ繧「繧ッ繧サ繧ケ + DWORD param; ///< 繝代Λ繝。繝シ繧ソ(蜈磯ュ4繝舌う繝) + WORD media; ///< 繝。繝繧」繧「繝舌う繝(蜈磯ュ2繝舌う繝) + }; + + /// 繧ウ繝槭Φ繝峨Λ繧、繝ウ蠑墓焚讒矩菴 + /** + 蜈磯ュ縺ォ繝峨Λ繧、繝占ェ霄ォ縺ョ繝代せ縺悟性縺セ繧後k縺溘aHUMAN68K_PATH_MAX莉・荳翫ョ繧オ繧、繧コ縺ォ縺吶k縲 + */ + struct argument_t { + BYTE buf[256]; ///< 繧ウ繝槭Φ繝峨Λ繧、繝ウ蠑墓焚 + }; +} + +/// FILES逕ィ繝舌ャ繝輔ぃ蛟区焚 +/** +騾壼クク縺ッ謨ー蛟九〒蜊∝縺縺後?uman68k縺ョ隍謨ー縺ョ繝励Ο繧サ繧ケ縺後槭Ν繝√ち繧ケ繧ッ縺ァ蜷梧凾縺ォ +豺ア縺髫主ア、縺ォ貂。縺」縺ヲ菴懈・ュ縺吶k譎ゅ↑縺ゥ縺ッ縺薙ョ蛟、繧貞「励d縺吝ソ隕√′縺ゅk縲 + +繝繝輔か繝ォ繝医ッ20蛟九 +*/ +#define XM6_HOST_FILES_MAX 20 + +/// FCB逕ィ繝舌ャ繝輔ぃ蛟区焚 +/** +蜷梧凾縺ォ繧ェ繝シ繝励Φ縺ァ縺阪k繝輔ぃ繧、繝ォ謨ー縺ッ縺薙l縺ァ豎コ縺セ繧九 + +繝繝輔か繝ォ繝医ッ100繝輔ぃ繧、繝ォ縲 +*/ +#define XM6_HOST_FCB_MAX 100 + +/// 莉ョ諠ウ繧サ繧ッ繧ソ/繧ッ繝ゥ繧ケ繧ソ 譛螟ァ蛟区焚 +/** +繝輔ぃ繧、繝ォ螳滉ス薙ョ蜈磯ュ繧サ繧ッ繧ソ縺ク縺ョ繧「繧ッ繧サ繧ケ縺ォ蟇セ蠢懊☆繧九◆繧√ョ莉ョ諠ウ繧サ繧ッ繧ソ縺ョ蛟区焚縲 +lzdsys縺ォ繧医k繧「繧ッ繧サ繧ケ繧定。後↑縺繧ケ繝ャ繝繝峨ョ謨ー繧医j螟壹a縺ォ遒コ菫昴☆繧九 + +繝繝輔か繝ォ繝医ッ10繧サ繧ッ繧ソ縲 +*/ +#define XM6_HOST_PSEUDO_CLUSTER_MAX 10 + +/// 繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ 繧ュ繝」繝繧キ繝・蛟区焚 +/** +Human68k縺ッ縲√し繝悶ョ繧」繝ャ繧ッ繝医Μ蜀縺ァ蜃ヲ逅繧定。後↑縺髫帙↓繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ +縺ョ繝√ぉ繝繧ッ繧貞、ァ驥上↓逋コ陦後☆繧九ゅ%縺ョ蠢懃ュ斐r鬮倬溷喧縺吶k縺溘a縺ョ邁。譏薙く繝」繝繧キ繝・ +縺ョ蛟区焚繧呈欠螳壹☆繧九ゅく繝」繝繧キ繝・縺ッ蜷繝峨Λ繧、繝匁ッ弱↓遒コ菫昴&繧後k縲 +螟壹>縺サ縺ゥ鬮倬溘↓縺ェ繧九′縲∝「励d縺励☆縺弱k縺ィ繝帙せ繝OS蛛エ縺ォ雋諡縺後°縺九k縺ョ縺ァ豕ィ諢上 + +繝繝輔か繝ォ繝医ッ16蛟九 +*/ +#define XM6_HOST_DIRENTRY_CACHE_MAX 16 + +/// 1繝繧」繝ャ繧ッ繝医Μ縺ォ蜿守エ阪〒縺阪k繧ィ繝ウ繝医Μ縺ョ譛螟ァ謨ー +/** +繝繧」繝ャ繧ッ繝医Μ蜀縺ォ繝輔ぃ繧、繝ォ縺悟、ァ驥上↓蟄伜惠縺吶k縺ィ縲∝ス捺凾縺ョ繧「繝励Μ繧ア繝シ繧キ繝ァ繝ウ縺 +諠ウ螳壹@縺ヲ縺縺ェ縺螟ァ驥上ョ繝繝シ繧ソ繧定ソ斐@縺ヲ縺励∪縺縺薙→縺ォ縺ェ繧九ゅい繝励Μ縺ォ繧医▲縺ヲ縺ッ +荳驛ィ縺励°隱崎ュ倥&繧後↑縺九▲縺溘j縲騾溷コヲ縺悟、ァ蟷縺ォ菴惹ク九@縺溘j縲√Γ繝「繝ェ荳崎カウ縺ァ蛛懈ュ「 +縺吶k縺ェ縺ゥ縺ョ蜊ア髯コ諤ァ縺悟ュ伜惠縺吶k縲ゅ%縺ョ縺溘a荳企剞繧定ィュ螳壹☆繧九%縺ィ縺ァ蟇セ蜃ヲ縺吶k縲 +萓九∴縺ー縺ィ縺ゅk繝輔ぃ繧、繝ゥ縺ョ蝣エ蜷医2560繝輔ぃ繧、繝ォ縺御ク企剞縺ィ縺ェ縺」縺ヲ縺繧九ゅ%縺ョ謨ー繧 +荳縺、縺ョ逶ョ螳峨→縺吶k縺ョ縺瑚憶縺縲 + +繝繝輔か繝ォ繝医ッ邏6荳繧ィ繝ウ繝医Μ縲(FAT縺ョ繝ォ繝シ繝医ョ繧」繝ャ繧ッ繝医Μ縺ァ縺ョ荳企剞蛟、) +*/ +#define XM6_HOST_DIRENTRY_FILE_MAX 65535 + +/// 繝輔ぃ繧、繝ォ蜷阪ョ驥崎、髯、螟悶ヱ繧ソ繝シ繝ウ縺ョ譛螟ァ謨ー +/** +Human68k蛛エ縺ョ繝輔ぃ繧、繝ォ蜷阪ッ縲√帙せ繝亥エ縺ョ繝輔ぃ繧、繝ォ繧キ繧ケ繝繝縺ョ蜷咲ァー繧偵b縺ィ縺ォ閾ェ +蜍慕函謌舌&繧後k縺後?uman68k蛛エ縺ョ繝輔ぃ繧、繝ォ蜷阪h繧翫b繝帙せ繝亥エ縺ョ繝輔ぃ繧、繝ォ蜷阪ョ蜷 +遘ー縺ョ縺サ縺縺碁聞縺縺溘a縲∝酔蜷阪ョ繝輔ぃ繧、繝ォ蜷阪′逕滓舌&繧後※縺励∪縺蜿ッ閭ス諤ァ縺後≠繧九 +縺昴ョ譎ゅ?uman68k蛛エ縺九i繝輔ぃ繧、繝ォ蜷阪r蛹コ蛻・縺ァ縺阪k繧医≧縺ォ縺吶k縺溘a縲仝indrvXM +迢ャ閾ェ縺ョ蜻ス蜷崎ヲ丞援縺ォ蠕薙▲縺ヲ蛻・蜷阪r逕滓舌@縺ヲ隗」豎コ縺励※縺繧九 +逅隲紋ク翫ッ邏6蜊荳(36縺ョ5荵)騾壹j縺ョ蛻・蜷阪r逕滓舌〒縺阪k譁ケ蠑上r蜿悶▲縺ヲ縺繧九′縲∝ョ +髫帙↓縺ッ謨ー逋セ繝代ち繝シ繝ウ莉・荳翫ョ驥崎、蛻、螳壹′逋コ逕溘☆繧九→蜃ヲ逅縺ォ譎る俣縺後°縺九▲縺ヲ縺励∪ +縺縺溘a縲驥崎、縺ョ荳企剞繧定ィュ螳壹☆繧九%縺ィ縺ァ騾溷コヲ繧堤カュ謖√☆繧九ょクク隴倡噪縺ェ驕狗畑縺ァ縺ゅl +縺ー縲∽サ」譖ソ蜷阪ッ謨ー繝代ち繝シ繝ウ繧ゅ≠繧後ー蜊∝驕狗畑縺ァ縺阪k縺ッ縺壹〒縺ゅj縲√%縺ョ蛟、繧貞庄閭ス +縺ェ髯舌j蟆上&縺蛟、縺ォ縺吶k縺薙→縺ァ繝代ヵ繧ゥ繝シ繝槭Φ繧ケ縺ョ謾ケ蝟縺梧悄蠕縺ァ縺阪k縲 +縺薙ョ蛟区焚繧定カ縺医k繝輔ぃ繧、繝ォ蜷阪′驥崎、縺励※縺励∪縺」縺溷エ蜷医ッ縲∝酔蜷阪ョ繧ィ繝ウ繝医Μ縺 +隍謨ー逕滓舌&繧後k縲ゅ%縺ョ蝣エ蜷医√ヵ繧。繧、繝ォ荳隕ァ縺ァ縺ッ隕九∴繧九′繝輔ぃ繧、繝ォ蜷阪〒謖螳壹☆ +繧九→譛蛻昴ョ繧ィ繝ウ繝医Μ縺ョ縺ソ謇ア縺医k迥カ諷九→縺ェ繧九 + +繝繝輔か繝ォ繝医ッ36繝代ち繝シ繝ウ縲 +*/ +#define XM6_HOST_FILENAME_PATTERN_MAX 36 + +/// 繝輔ぃ繧、繝ォ蜷埼崎、髦イ豁「繝槭シ繧ッ +/** +繝帙せ繝亥エ縺ョ繝輔ぃ繧、繝ォ蜷阪→Human68k蛛エ繝輔ぃ繧、繝ォ蜷阪ョ蜷咲ァー縺ョ蛹コ蛻・繧偵▽縺代k縺ィ縺阪↓ +菴ソ縺譁蟄励ゅさ繝槭Φ繝峨す繧ァ繝ォ遲峨ョ繧ィ繧ケ繧ア繝シ繝玲枚蟄励→驥阪↑繧峨↑縺繧ゅョ繧帝∈縺カ縺ィ蜷峨 + +繝繝輔か繝ォ繝医ッ縲掘縲阪 +*/ +#define XM6_HOST_FILENAME_MARK '@' + +/// WINDRV蜍穂ス懊ヵ繝ゥ繧ー +/** +騾壼クク縺ッ0縺ォ縺吶k縲ゅヵ繧。繧、繝ォ蜑企勁縺ォOS縺ョ縺斐∩邂ア讖溯ス繧貞茜逕ィ縺吶k蝣エ蜷医ッ1縺ォ縺吶k縲 +縺昴l莉・螟悶ョ蛟、縺ッ蟆譚・縺ョ縺溘a縺ョ莠育エ縺ィ縺吶k縲 +蜀驛ィ蜍穂ス懊ヵ繝ゥ繧ー縺ィ繝。繝繧」繧「繝舌う繝亥⊃陬縺ェ縺ゥ繧定ヲ玖カ翫@縺溷ー譚・縺ョ諡。蠑オ逕ィ縲 +*/ +enum { + WINDRV_OPT_REMOVE = 0x00000001, + ///< Bit 0: 繝輔ぃ繧、繝ォ蜑企勁蜃ヲ逅 0:逶エ謗・ 1:縺斐∩邂ア + WINDRV_OPT_ALPHABET = 0x00000020, + ///< Bit 5: 繝輔ぃ繧、繝ォ蜷肴ッ碑シ Alphabet蛹コ蛻・ 0:縺ェ縺 1:縺ゅj 0:-C 1:+C + WINDRV_OPT_COMPARE_LENGTH = 0x00000040, + ///< Bit 6: 繝輔ぃ繧、繝ォ蜷肴ッ碑シ 譁蟄玲焚(譛ェ螳溯」) 0:18+3 1:8+3 0:+T 1:-T + WINDRV_OPT_CONVERT_LENGTH = 0x00000080, + ///< Bit 7: 繝輔ぃ繧、繝ォ蜷榊、画鋤 譁蟄玲焚 0:18+3 1:8+3 0:-A 1:+A + + WINDRV_OPT_CONVERT_SPACE = 0x00000100, + ///< Bit 8: 繝輔ぃ繧、繝ォ蜷榊、画鋤 繧ケ繝壹シ繧ケ 0:縺ェ縺 1:'_' + WINDRV_OPT_CONVERT_BADCHAR = 0x00000200, + ///< Bit 9: 繝輔ぃ繧、繝ォ蜷榊、画鋤 辟。蜉ケ縺ェ譁蟄 0:縺ェ縺 1:'_' + WINDRV_OPT_CONVERT_HYPHENS = 0x00000400, + ///< Bit10: 繝輔ぃ繧、繝ォ蜷榊、画鋤 荳ュ髢薙ョ繝上う繝輔Φ 0:縺ェ縺 1:'_' + WINDRV_OPT_CONVERT_HYPHEN = 0x00000800, + ///< Bit11: 繝輔ぃ繧、繝ォ蜷榊、画鋤 蜈磯ュ縺ョ繝上う繝輔Φ 0:縺ェ縺 1:'_' + WINDRV_OPT_CONVERT_PERIODS = 0x00001000, + ///< Bit12: 繝輔ぃ繧、繝ォ蜷榊、画鋤 荳ュ髢薙ョ繝斐Μ繧ェ繝 0:縺ェ縺 1:'_' + WINDRV_OPT_CONVERT_PERIOD = 0x00002000, + ///< Bit13: 繝輔ぃ繧、繝ォ蜷榊、画鋤 蜈磯ュ縺ョ繝斐Μ繧ェ繝 0:縺ェ縺 1:'_' + + WINDRV_OPT_REDUCED_SPACE = 0x00010000, + ///< Bit16: 繝輔ぃ繧、繝ォ蜷咲洒邵ョ 繧ケ繝壹シ繧ケ 0:縺ェ縺 1:遏ュ邵ョ + WINDRV_OPT_REDUCED_BADCHAR = 0x00020000, + ///< Bit17: 繝輔ぃ繧、繝ォ蜷咲洒邵ョ 辟。蜉ケ縺ェ譁蟄 0:縺ェ縺 1:遏ュ邵ョ + WINDRV_OPT_REDUCED_HYPHENS = 0x00040000, + ///< Bit18: 繝輔ぃ繧、繝ォ蜷咲洒邵ョ 荳ュ髢薙ョ繝上う繝輔Φ 0:縺ェ縺 1:遏ュ邵ョ + WINDRV_OPT_REDUCED_HYPHEN = 0x00080000, + ///< Bit19: 繝輔ぃ繧、繝ォ蜷咲洒邵ョ 蜈磯ュ縺ョ繝上う繝輔Φ 0:縺ェ縺 1:遏ュ邵ョ + WINDRV_OPT_REDUCED_PERIODS = 0x00100000, + ///< Bit20: 繝輔ぃ繧、繝ォ蜷咲洒邵ョ 荳ュ髢薙ョ繝斐Μ繧ェ繝 0:縺ェ縺 1:遏ュ邵ョ + WINDRV_OPT_REDUCED_PERIOD = 0x00200000, + ///< Bit21: 繝輔ぃ繧、繝ォ蜷咲洒邵ョ 蜈磯ュ縺ョ繝斐Μ繧ェ繝 0:縺ェ縺 1:遏ュ邵ョ + + // Bit24ス30 繝輔ぃ繧、繝ォ驥崎、髦イ豁「繝槭シ繧ッ 0:閾ェ蜍 1ス127:譁蟄 +}; + +/// 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝蜍穂ス懊ヵ繝ゥ繧ー +/** +騾壼クク縺ッ0縺ォ縺吶k縲ゅΜ繝シ繝峨が繝ウ繝ェ繝シ縺ァ繝槭え繝ウ繝医@縺溘>繝峨Λ繧、繝悶ョ蝣エ蜷医ッ1縺ォ縺吶k縲 +縺昴l莉・螟悶ョ蛟、縺ッ蟆譚・縺ョ縺溘a縺ョ莠育エ縺ィ縺吶k縲 +蛻、螳壹′蝗ー髮」縺ェ繝繝舌う繧ケ(閾ェ菴弑SB繧ケ繝医Ξ繝シ繧ク縺ィ縺)縺ョ縺溘a縺ョ菫晞匱逕ィ縲 +*/ +enum { + FSFLAG_WRITE_PROTECT = 0x00000001, + ///< Bit0: 蠑キ蛻カ譖ク縺崎セシ縺ソ遖∵ュ「 + FSFLAG_REMOVABLE = 0x00000002, + ///< Bit1: 蠑キ蛻カ繝ェ繝繝シ繝舌ヶ繝ォ繝。繝繧」繧「 + FSFLAG_MANUAL = 0x00000004, + ///< Bit2: 蠑キ蛻カ謇句虚繧、繧ク繧ァ繧ッ繝 +}; + +//=========================================================================== +// +/// 縺セ繧九▲縺ィ繝ェ繝ウ繧ー繝ェ繧ケ繝 +/// +/// 蜈磯ュ(root.next)縺梧怙繧よ眠縺励>繧ェ繝悶ず繧ァ繧ッ繝医 +/// 譛ォ蟆セ(root.prev)縺梧怙繧ょ商縺/譛ェ菴ソ逕ィ繧ェ繝悶ず繧ァ繧ッ繝医 +/// 繧ウ繝シ繝牙柑邇霑ス豎ゅョ縺溘a縲‥elete譎ゅッ蠢縺壹昴う繝ウ繧ソ繧偵い繝繝励く繝」繧ケ繝医☆繧九%縺ィ縲 +// +//=========================================================================== +class CRing { +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + CRing() { Init(); } + ///< 繝繝輔か繝ォ繝医さ繝ウ繧ケ繝医Λ繧ッ繧ソ + ~CRing() { Remove(); } + ///< 繝繧ケ繝医Λ繧ッ繧ソ final + void Init() { ASSERT(this); next = prev = this; } + ///< 蛻晄悄蛹 + + CRing* Next() const { ASSERT(this); return next; } + ///< 谺。縺ョ隕∫エ繧貞叙蠕 + CRing* Prev() const { ASSERT(this); return prev; } + ///< 蜑阪ョ隕∫エ繧貞叙蠕 + + void Insert(CRing* pRoot) + { + ASSERT(this); + // 隧イ蠖薙が繝悶ず繧ァ繧ッ繝医r蛻繧企屬縺 + ASSERT(next); + ASSERT(prev); + next->prev = prev; + prev->next = next; + // 繝ェ繝ウ繧ー蜈磯ュ縺ク謖ソ蜈・ + ASSERT(pRoot); + ASSERT(pRoot->next); + next = pRoot->next; + prev = pRoot; + pRoot->next->prev = this; + pRoot->next = this; + } + ///< 繧ェ繝悶ず繧ァ繧ッ繝亥繧企屬縺 & 繝ェ繝ウ繧ー蜈磯ュ縺ク謖ソ蜈・ + + void InsertTail(CRing* pRoot) + { + ASSERT(this); + // 隧イ蠖薙が繝悶ず繧ァ繧ッ繝医r蛻繧企屬縺 + ASSERT(next); + ASSERT(prev); + next->prev = prev; + prev->next = next; + // 繝ェ繝ウ繧ー譛ォ蟆セ縺ク謖ソ蜈・ + ASSERT(pRoot); + ASSERT(pRoot->prev); + next = pRoot; + prev = pRoot->prev; + pRoot->prev->next = this; + pRoot->prev = this; + } + ///< 繧ェ繝悶ず繧ァ繧ッ繝亥繧企屬縺 & 繝ェ繝ウ繧ー譛ォ蟆セ縺ク謖ソ蜈・ + + void InsertRing(CRing* pRoot) + { + ASSERT(this); + if (next == prev) return; + + // 繝ェ繝ウ繧ー蜈磯ュ縺ク謖ソ蜈・ + ASSERT(pRoot); + ASSERT(pRoot->next); + pRoot->next->prev = prev; + prev->next = pRoot->next; + pRoot->next = next; + next->prev = pRoot; + + // 閾ェ蛻閾ェ霄ォ繧堤ゥコ縺ォ縺吶k + next = prev = this; + } + ///< 閾ェ蛻莉・螟悶ョ繧ェ繝悶ず繧ァ繧ッ繝亥繧企屬縺 & 繝ェ繝ウ繧ー蜈磯ュ縺ク謖ソ蜈・ + + void Remove() + { + ASSERT(this); + // 隧イ蠖薙が繝悶ず繧ァ繧ッ繝医r蛻繧企屬縺 + ASSERT(next); + ASSERT(prev); + next->prev = prev; + prev->next = next; + // 螳牙ィ縺ョ縺溘a閾ェ蛻閾ェ霄ォ繧呈欠縺励※縺翫¥ (菴募コヲ蛻繧企屬縺励※繧ょ撫鬘後↑縺) + next = prev = this; + } + ///< 繧ェ繝悶ず繧ァ繧ッ繝亥繧企屬縺 + +private: + CRing* next; ///< 谺。縺ョ隕∫エ + CRing* prev; ///< 蜑阪ョ隕∫エ +}; + +//=========================================================================== +// +/// 繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ 繝輔ぃ繧、繝ォ蜷 +// +//=========================================================================== +class CHostFilename { +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + CHostFilename(); + ///< 繝繝輔か繝ォ繝医さ繝ウ繧ケ繝医Λ繧ッ繧ソ + static size_t Offset() { return offsetof(CHostFilename, m_szHost); } + ///< 繧ェ繝輔そ繝繝井ス咲スョ蜿門セ + + void SetHost(const TCHAR* szHost); + ///< 繝帙せ繝亥エ縺ョ蜷咲ァー繧定ィュ螳 + const TCHAR* GetHost() const { ASSERT(this); return m_szHost; } + ///< 繝帙せ繝亥エ縺ョ蜷咲ァー繧貞叙蠕 + void ConvertHuman(int nCount = -1); + ///< Human68k蛛エ縺ョ蜷咲ァー繧貞、画鋤 + void CopyHuman(const BYTE* szHuman); + ///< Human68k蛛エ縺ョ蜷咲ァー繧定、陬ス + BOOL isReduce() const; + ///< Human68k蛛エ縺ョ蜷咲ァー縺悟刈蟾・縺輔l縺溘°隱ソ譟サ + BOOL isCorrect() const { ASSERT(this); return m_bCorrect; } + ///< Human68k蛛エ縺ョ繝輔ぃ繧、繝ォ蜷崎ヲ丞援縺ォ蜷郁エ縺励※縺繧九°隱ソ譟サ + const BYTE* GetHuman() const { ASSERT(this); return m_szHuman; } + ///< Human68k繝輔ぃ繧、繝ォ蜷阪r蜿門セ + const BYTE* GetHumanLast() const { ASSERT(this); return m_pszHumanLast; } + ///< Human68k繝輔ぃ繧、繝ォ蜷阪r蜿門セ + const BYTE* GetHumanExt() const { ASSERT(this); return m_pszHumanExt; } + ///< Human68k繝輔ぃ繧、繝ォ蜷阪r蜿門セ + void SetEntryName(); + ///< Human68k繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ繧定ィュ螳 + void SetEntryAttribute(BYTE nHumanAttribute) + { ASSERT(this); m_dirHuman.attr = nHumanAttribute; } + ///< Human68k繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ繧定ィュ螳 + void SetEntrySize(DWORD nHumanSize) + { ASSERT(this); m_dirHuman.size = nHumanSize; } + ///< Human68k繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ繧定ィュ螳 + void SetEntryDate(WORD nHumanDate) + { ASSERT(this); m_dirHuman.date = nHumanDate; } + ///< Human68k繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ繧定ィュ螳 + void SetEntryTime(WORD nHumanTime) + { ASSERT(this); m_dirHuman.time = nHumanTime; } + ///< Human68k繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ繧定ィュ螳 + void SetEntryCluster(WORD nHumanCluster) + { ASSERT(this); m_dirHuman.cluster = nHumanCluster; } + ///< Human68k繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ繧定ィュ螳 + const Human68k::dirent_t* GetEntry() const { ASSERT(this); return &m_dirHuman; } + ///< Human68k繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ繧貞叙蠕 + BOOL CheckAttribute(DWORD nHumanAttribute) const; + ///< Human68k繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ縺ョ螻樊ァ蛻、螳 + BOOL isSameEntry(const Human68k::dirent_t* pdirHuman) const + { ASSERT(this); ASSERT(pdirHuman); return memcmp(&m_dirHuman, pdirHuman, sizeof(m_dirHuman)) == 0; } + ///< Human68k繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ縺ョ荳閾エ蛻、螳 + + // 繝代せ蜷肴桃菴 + static const BYTE* SeparateExt(const BYTE* szHuman); + ///< Human68k繝輔ぃ繧、繝ォ蜷阪°繧画僑蠑オ蟄舌r蛻髮「 + +private: + static BYTE* CopyName(BYTE* pWrite, const BYTE* pFirst, const BYTE* pLast); + ///< Human68k蛛エ縺ョ繝輔ぃ繧、繝ォ蜷崎ヲ∫エ繧偵さ繝斐シ + + const BYTE* m_pszHumanLast; ///< 隧イ蠖薙お繝ウ繝医Μ縺ョHuman68k蜀驛ィ蜷阪ョ邨らォッ菴咲スョ + const BYTE* m_pszHumanExt; ///< 隧イ蠖薙お繝ウ繝医Μ縺ョHuman68k蜀驛ィ蜷阪ョ諡。蠑オ蟄蝉ス咲スョ + BOOL m_bCorrect; ///< 隧イ蠖薙お繝ウ繝医Μ縺ョHuman68k蜀驛ィ蜷阪′豁」縺励¢繧後ー逵 + BYTE m_szHuman[24]; ///< 隧イ蠖薙お繝ウ繝医Μ縺ョHuman68k蜀驛ィ蜷 + Human68k::dirent_t m_dirHuman; ///< 隧イ蠖薙お繝ウ繝医Μ縺ョHuman68k蜈ィ諠蝣ア + TCHAR m_szHost[FILEPATH_MAX]; ///< 隧イ蠖薙お繝ウ繝医Μ縺ョ繝帙せ繝亥エ縺ョ蜷咲ァー (蜿ッ螟蛾聞) +}; + +//=========================================================================== +// +/// 繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ 繝代せ蜷 +/// +/// Human68k蛛エ縺ョ繝代せ蜷阪ッ縲∝ソ縺壼磯ュ縺/縺ァ蟋九∪繧翫∵忰蟆セ縺/縺ァ邨ゅo繧九 +/// 繝ヲ繝九ャ繝育分蜿キ縺ッ謖√◆縺ェ縺縲 +/// 鬮倬溷喧縺ョ縺溘a縲√帙せ繝亥エ縺ョ蜷咲ァー縺ォ縺ッ繝吶シ繧ケ繝代せ驛ィ蛻繧ょ性繧縲 +// +//=========================================================================== +/** @note +縺サ縺ィ繧薙←縺ョHuman68k縺ョ繧「繝励Μ縺ッ縲√ヵ繧。繧、繝ォ縺ョ譖エ譁ー遲峨↓繧医▲縺ヲ繝繧」繝ャ繧ッ繝医Μ繧ィ +繝ウ繝医Μ縺ォ螟画峩縺檎函縺倥◆髫帙∬ヲェ繝繧」繝ャ繧ッ繝医Μ縺ョ繧ソ繧、繝繧ケ繧ソ繝ウ繝励ッ螟牙喧縺励↑縺繧 +縺ョ縺ィ諠ウ螳壹@縺ヲ菴懊i繧後※縺繧九 +縺ィ縺薙m縺後帙せ繝亥エ縺ョ繝輔ぃ繧、繝ォ繧キ繧ケ繝繝縺ァ縺ッ隕ェ繝繧」繝ャ繧ッ繝医Μ縺ョ繧ソ繧、繝繧ケ繧ソ繝ウ繝 +繧ょ、牙喧縺励※縺励∪縺繧ゅョ縺御クサ豬√→縺ェ縺」縺ヲ縺励∪縺」縺ヲ縺繧九 + +縺薙ョ縺溘a縲√ョ繧」繝ャ繧ッ繝医Μ縺ョ繧ウ繝斐シ遲峨↓縺翫>縺ヲ縲√い繝励Μ蛛エ縺ッ豁」遒コ縺ォ繧ソ繧、繝繧ケ繧ソ +繝ウ繝玲ュ蝣ア縺ェ縺ゥ繧定ィュ螳壹@縺ヲ縺繧九↓繧ゅ°縺九o繧峨★縲∝ョ溯。檎オ先棡縺ァ縺ッ譎ょ綾諠蝣ア縺御ク頑嶌 +縺阪&繧後※縺励∪縺縺ィ縺縺諠ィ蜉縺瑚オキ縺阪※縺励∪縺縲 + +縺昴%縺ァ繝繧」繝ャ繧ッ繝医Μ繧ュ繝」繝繧キ繝・蜀縺ォFAT繧ソ繧、繝繧ケ繧ソ繝ウ繝励ョ繧ィ繝溘Η繝ャ繝シ繧キ繝ァ繝ウ +讖溯ス繧貞ョ溯」縺励◆縲ゅ帙せ繝亥エ縺ョ繝輔ぃ繧、繝ォ繧キ繧ケ繝繝縺ョ譖エ譁ー譎ゅ↓繧ソ繧、繝繧ケ繧ソ繝ウ繝玲ュ +蝣ア繧貞セゥ蜈縺吶k縺薙→縺ァHuman68k蛛エ縺ョ譛溷セ縺吶k邨先棡縺ィ荳閾エ縺輔○繧九 +*/ +class CHostPath: public CRing { + /// 繝。繝「繝ェ邂。逅逕ィ + struct ring_t { + CRing r; ///< 蜀迺ー + CHostFilename f; ///< 螳滉ス + }; + +public: + /// 讀懃エ「逕ィ繝舌ャ繝輔ぃ + struct find_t { + DWORD count; ///< 讀懃エ「螳溯。悟屓謨ー + 1 (0縺ョ縺ィ縺阪ッ莉・荳九ョ蛟、縺ッ辟。蜉ケ) + DWORD id; ///< 谺。蝗樊、懃エ「繧堤カ夊。後☆繧九ヱ繧ケ縺ョ繧ィ繝ウ繝医Μ隴伜挨ID + const ring_t* pos; ///< 谺。蝗樊、懃エ「繧堤カ夊。後☆繧倶ス咲スョ (隴伜挨ID荳閾エ譎) + Human68k::dirent_t entry; ///< 谺。蝗樊、懃エ「繧堤カ夊。後☆繧九お繝ウ繝医Μ蜀螳ケ + + void Clear() { count = 0; } + ///< 蛻晄悄蛹 + }; + + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + CHostPath(); + ///< 繝繝輔か繝ォ繝医さ繝ウ繧ケ繝医Λ繧ッ繧ソ + ~CHostPath(); + ///< 繝繧ケ繝医Λ繧ッ繧ソ final + void Clean(); + ///< 蜀榊茜逕ィ縺ョ縺溘a縺ョ蛻晄悄蛹 + + void SetHuman(const BYTE* szHuman); + ///< Human68k蛛エ縺ョ蜷咲ァー繧堤峩謗・謖螳壹☆繧 + void SetHost(const TCHAR* szHost); + ///< 繝帙せ繝亥エ縺ョ蜷咲ァー繧堤峩謗・謖螳壹☆繧 + BOOL isSameHuman(const BYTE* szHuman) const; + ///< Human68k蛛エ縺ョ蜷咲ァー繧呈ッ碑シ縺吶k + BOOL isSameChild(const BYTE* szHuman) const; + ///< Human68k蛛エ縺ョ蜷咲ァー繧呈ッ碑シ縺吶k + const TCHAR* GetHost() const { ASSERT(this); return m_szHost; } + ///< 繝帙せ繝亥エ縺ョ蜷咲ァー縺ョ迯イ蠕 + const CHostFilename* FindFilename(const BYTE* szHuman, DWORD nHumanAttribute = Human68k::AT_ALL) const; + ///< 繝輔ぃ繧、繝ォ蜷阪r讀懃エ「 + const CHostFilename* FindFilenameWildcard(const BYTE* szHuman, DWORD nHumanAttribute, find_t* pFind) const; + ///< 繝輔ぃ繧、繝ォ蜷阪r讀懃エ「 (繝ッ繧、繝ォ繝峨き繝シ繝牙ッセ蠢) + BOOL isRefresh(); + ///< 繝輔ぃ繧、繝ォ螟画峩縺瑚。後↑繧上l縺溘°遒コ隱 + void Refresh(); + ///< 繝輔ぃ繧、繝ォ蜀肴ァ区 + void Backup(); + /// 繝帙せ繝亥エ縺ョ繧ソ繧、繝繧ケ繧ソ繝ウ繝励r菫晏ュ + void Restore() const; + /// 繝帙せ繝亥エ縺ョ繧ソ繧、繝繧ケ繧ソ繝ウ繝励r蠕ゥ蜈 + void Release(); + ///< 譖エ譁ー + + // CHostEntry縺悟茜逕ィ縺吶k螟夜ΚAPI + static void InitId() { g_nId = 0; } + ///< 隴伜挨ID逕滓千畑繧ォ繧ヲ繝ウ繧ソ蛻晄悄蛹 + +private: + static ring_t* Alloc(size_t nLength); + ///< 繝輔ぃ繧、繝ォ蜷埼伜沺遒コ菫 + static void Free(ring_t* pRing); + ///< 繝輔ぃ繧、繝ォ蜷埼伜沺隗」謾セ + static int Compare(const BYTE* pFirst, const BYTE* pLast, const BYTE* pBufFirst, const BYTE* pBufLast); + ///< 譁蟄怜玲ッ碑シ (繝ッ繧、繝ォ繝峨き繝シ繝牙ッセ蠢) + + CRing m_cRing; ///< CHostFilename騾」邨千畑 + time_t m_tBackup; ///< 譎ょ綾蠕ゥ蜈逕ィ + BOOL m_bRefresh; ///< 譖エ譁ー繝輔Λ繧ー + DWORD m_nId; ///< 隴伜挨ID (蛟、縺悟、牙喧縺励◆蝣エ蜷医ッ譖エ譁ー繧呈э蜻ウ縺吶k) + BYTE m_szHuman[HUMAN68K_PATH_MAX]; ///< 隧イ蠖薙お繝ウ繝医Μ縺ョHuman68k蜀驛ィ蜷 + TCHAR m_szHost[FILEPATH_MAX]; ///< 隧イ蠖薙お繝ウ繝医Μ縺ョ繝帙せ繝亥エ縺ョ蜷咲ァー + + static DWORD g_nId; ///< 隴伜挨ID逕滓千畑繧ォ繧ヲ繝ウ繧ソ +}; + +//=========================================================================== +// +/// 繝輔ぃ繧、繝ォ讀懃エ「蜃ヲ逅 +/// +/// Human68k蛛エ縺ョ繝輔ぃ繧、繝ォ蜷阪r蜀驛ィUnicode縺ァ蜃ヲ逅縺吶k縺ョ縺ッ豁」逶エ繧ュ繝縺縲ゅ→ +/// 縺縺繧上¢縺ァ縲∝ィ縺ヲBYTE縺ォ螟画鋤縺励※蜃ヲ逅縺吶k縲ょ、画鋤蜃ヲ逅縺ッ繝繧」繝ャ繧ッ繝医Μ繧ィ +/// 繝ウ繝医Μ繧ュ繝」繝繧キ繝・縺御ク謇九↓諡縺縲仝INDRV蛛エ縺ッ縺吶∋縺ヲ繧キ繝輔ヨJIS縺ョ縺ソ縺ァ謇ア +/// 縺医k繧医≧縺ォ縺吶k縲 +/// 縺セ縺溘?uman68k蛛エ蜷咲ァー縺ッ縲∝ョ悟ィ縺ォ繝吶シ繧ケ繝代せ謖螳壹°繧臥峡遶九&縺帙k縲 +/// +/// 繝輔ぃ繧、繝ォ繧呈桶縺逶エ蜑阪↓縲√ョ繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ縺ョ繧ュ繝」繝繧キ繝・繧堤函謌舌☆繧九 +/// 繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ縺ョ逕滓仙ヲ逅縺ッ鬮倥さ繧ケ繝医ョ縺溘a縲∽ク蠎ヲ逕滓舌@縺溘お繝ウ繝医Μ縺ッ +/// 蜿ッ閭ス縺ェ髯舌j邯ュ謖√@縺ヲ菴ソ縺蝗槭☆縲 +/// +/// 繝輔ぃ繧、繝ォ讀懃エ「縺ッ3譁ケ蠑上ゅ☆縺ケ縺ヲCHostFiles::Find()縺ァ蜃ヲ逅縺吶k縲 +/// 1. 繝代せ蜷阪ョ縺ソ讀懃エ「 螻樊ァ縺ッ繝繧」繝ャ繧ッ繝医Μ縺ョ縺ソ _CHKDIR _CREATE +/// 2. 繝代せ蜷+繝輔ぃ繧、繝ォ蜷+螻樊ァ縺ョ讀懃エ「 _OPEN +/// 3. 繝代せ蜷+繝ッ繧、繝ォ繝峨き繝シ繝+螻樊ァ縺ョ讀懃エ「 _FILES _NFILES +/// 讀懃エ「邨先棡縺ッ縲√ョ繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ諠蝣ア縺ィ縺励※菫晄戟縺励※縺翫¥縲 +// +//=========================================================================== +class CHostFiles { +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + CHostFiles() { SetKey(0); Init(); } + ///< 繝繝輔か繝ォ繝医さ繝ウ繧ケ繝医Λ繧ッ繧ソ + void Init(); + ///< 蛻晄悄蛹 + + void SetKey(DWORD nKey) { ASSERT(this); m_nKey = nKey; } + ///< 讀懃エ「繧ュ繝シ險ュ螳 + BOOL isSameKey(DWORD nKey) const { ASSERT(this); return m_nKey == nKey; } + ///< 讀懃エ「繧ュ繝シ豈碑シ + void SetPath(const Human68k::namests_t* pNamests); + ///< 繝代せ蜷阪サ繝輔ぃ繧、繝ォ蜷阪r蜀驛ィ縺ァ逕滓 + BOOL isRootPath() const { return m_szHumanPath[1] == '\0'; } + ///< 繝ォ繝シ繝医ョ繧」繝ャ繧ッ繝医Μ蛻、螳 + void SetPathWildcard() { m_nHumanWildcard = 1; } + ///< 繝ッ繧、繝ォ繝峨き繝シ繝峨↓繧医k繝輔ぃ繧、繝ォ讀懃エ「繧呈怏蜉ケ蛹 + void SetPathOnly() { m_nHumanWildcard = 0xFF; } + ///< 繝代せ蜷阪ョ縺ソ繧呈怏蜉ケ蛹 + BOOL isPathOnly() const { return m_nHumanWildcard == 0xFF; } + ///< 繝代せ蜷阪ョ縺ソ險ュ螳壹°蛻、螳 + void SetAttribute(DWORD nHumanAttribute) { m_nHumanAttribute = nHumanAttribute; } + ///< 讀懃エ「螻樊ァ繧定ィュ螳 + BOOL Find(DWORD nUnit, class CHostEntry* pEntry); + ///< Human68k蛛エ縺ァ繝輔ぃ繧、繝ォ繧呈、懃エ「縺励帙せ繝亥エ縺ョ諠蝣ア繧堤函謌 + const CHostFilename* Find(CHostPath* pPath); + ///< 繝輔ぃ繧、繝ォ蜷肴、懃エ「 + void SetEntry(const CHostFilename* pFilename); + ///< Human68k蛛エ縺ョ讀懃エ「邨先棡菫晏ュ + void SetResult(const TCHAR* szPath); + ///< 繝帙せ繝亥エ縺ョ蜷咲ァー繧定ィュ螳 + void AddResult(const TCHAR* szPath); + ///< 繝帙せ繝亥エ縺ョ蜷咲ァー縺ォ繝輔ぃ繧、繝ォ蜷阪r霑ス蜉 + void AddFilename(); + ///< 繝帙せ繝亥エ縺ョ蜷咲ァー縺ォHuman68k縺ョ譁ー隕上ヵ繧。繧、繝ォ蜷阪r霑ス蜉 + + const TCHAR* GetPath() const { ASSERT(this); return m_szHostResult; } + ///< 繝帙せ繝亥エ縺ョ蜷咲ァー繧貞叙蠕 + const Human68k::dirent_t* GetEntry() const { ASSERT(this); return &m_dirHuman; } + ///< Human68k繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ繧貞叙蠕 + DWORD GetAttribute() const { ASSERT(this); return m_dirHuman.attr; } + ///< Human68k螻樊ァ繧貞叙蠕 + WORD GetDate() const { ASSERT(this); return m_dirHuman.date; } + ///< Human68k譌・莉倥r蜿門セ + WORD GetTime() const { ASSERT(this); return m_dirHuman.time; } + ///< Human68k譎ょ綾繧貞叙蠕 + DWORD GetSize() const { ASSERT(this); return m_dirHuman.size; } + ///< Human68k繝輔ぃ繧、繝ォ繧オ繧、繧コ繧貞叙蠕 + const BYTE* GetHumanFilename() const { ASSERT(this); return m_szHumanFilename; } + ///< Human68k繝輔ぃ繧、繝ォ蜷阪r蜿門セ + const BYTE* GetHumanResult() const { ASSERT(this); return m_szHumanResult; } + ///< Human68k繝輔ぃ繧、繝ォ蜷肴、懃エ「邨先棡繧貞叙蠕 + const BYTE* GetHumanPath() const { ASSERT(this); return m_szHumanPath; } + ///< Human68k繝代せ蜷阪r蜿門セ + +private: + DWORD m_nKey; ///< Human68k縺ョFILES繝舌ャ繝輔ぃ繧「繝峨Ξ繧ケ 0縺ェ繧画悴菴ソ逕ィ + DWORD m_nHumanWildcard; ///< Human68k縺ョ繝ッ繧、繝ォ繝峨き繝シ繝画ュ蝣ア + DWORD m_nHumanAttribute; ///< Human68k縺ョ讀懃エ「螻樊ァ + CHostPath::find_t m_findNext; ///< 谺。蝗樊、懃エ「菴咲スョ諠蝣ア + Human68k::dirent_t m_dirHuman; ///< 讀懃エ「邨先棡 Human68k繝輔ぃ繧、繝ォ諠蝣ア + BYTE m_szHumanFilename[24]; ///< Human68k縺ョ繝輔ぃ繧、繝ォ蜷 + BYTE m_szHumanResult[24]; ///< 讀懃エ「邨先棡 Human68k繝輔ぃ繧、繝ォ蜷 + BYTE m_szHumanPath[HUMAN68K_PATH_MAX]; + ///< Human68k縺ョ繝代せ蜷 + TCHAR m_szHostResult[FILEPATH_MAX]; ///< 讀懃エ「邨先棡 繝帙せ繝亥エ縺ョ繝輔Ν繝代せ蜷 +}; + +//=========================================================================== +// +/// 繝輔ぃ繧、繝ォ讀懃エ「鬆伜沺 繝槭ロ繝シ繧ク繝」 +// +//=========================================================================== +class CHostFilesManager { +public: +#ifdef _DEBUG + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + ~CHostFilesManager(); + ///< 繝繧ケ繝医Λ繧ッ繧ソ final +#endif // _DEBUG + void Init(); + ///< 蛻晄悄蛹 (繝峨Λ繧、繝千オ霎シ縺ソ譎) + void Clean(); + ///< 隗」謾セ (襍キ蜍輔サ繝ェ繧サ繝繝域凾) + + CHostFiles* Alloc(DWORD nKey); + ///< 遒コ菫 + CHostFiles* Search(DWORD nKey); + ///< 讀懃エ「 + void Free(CHostFiles* pFiles); + ///< 隗」謾セ +private: + /// 繝。繝「繝ェ邂。逅逕ィ + struct ring_t { + CRing r; ///< 蜀迺ー + CHostFiles f; ///< 螳滉ス + }; + + CRing m_cRing; ///< CHostFiles騾」邨千畑 +}; + +//=========================================================================== +// +/// FCB蜃ヲ逅 +// +//=========================================================================== +class CHostFcb { +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + CHostFcb() { SetKey(0); Init(); } + ///< 繝繝輔か繝ォ繝医さ繝ウ繧ケ繝医Λ繧ッ繧ソ + ~CHostFcb() { Close(); } + ///< 繝繧ケ繝医Λ繧ッ繧ソ final + void Init(); + ///< 蛻晄悄蛹 + + void SetKey(DWORD nKey) { ASSERT(this); m_nKey = nKey; } + ///< 讀懃エ「繧ュ繝シ險ュ螳 + BOOL isSameKey(DWORD nKey) const { ASSERT(this); return m_nKey == nKey; } + ///< 讀懃エ「繧ュ繝シ豈碑シ + void SetUpdate() { ASSERT(this); m_bUpdate = TRUE; } + ///< 譖エ譁ー + BOOL isUpdate() const { ASSERT(this); return m_bUpdate; } + ///< 譖エ譁ー迥カ諷句叙蠕 + BOOL SetMode(DWORD nHumanMode); + ///< 繝輔ぃ繧、繝ォ繧ェ繝シ繝励Φ繝「繝シ繝峨r險ュ螳 + void SetFilename(const TCHAR* szFilename); + ///< 繝輔ぃ繧、繝ォ蜷阪r險ュ螳 + void SetHumanPath(const BYTE* szHumanPath); + ///< Human68k繝代せ蜷阪r險ュ螳 + const BYTE* GetHumanPath() const { ASSERT(this); return m_szHumanPath; } + ///< Human68k繝代せ蜷阪r蜿門セ + + BOOL Create(DWORD nHumanAttribute, BOOL bForce); + ///< 繝輔ぃ繧、繝ォ菴懈 + BOOL Open(); + ///< 繝輔ぃ繧、繝ォ繧ェ繝シ繝励Φ + BOOL Rewind(DWORD nOffset); + ///< 繝輔ぃ繧、繝ォ繧キ繝シ繧ッ + DWORD Read(BYTE* pBuffer, DWORD nSize); + ///< 繝輔ぃ繧、繝ォ隱ュ縺ソ霎シ縺ソ + DWORD Write(const BYTE* pBuffer, DWORD nSize); + ///< 繝輔ぃ繧、繝ォ譖ク縺崎セシ縺ソ + BOOL Truncate(); + ///< 繝輔ぃ繧、繝ォ蛻繧願ゥー繧 + DWORD Seek(DWORD nOffset, DWORD nHumanSeek); + ///< 繝輔ぃ繧、繝ォ繧キ繝シ繧ッ + BOOL TimeStamp(DWORD nHumanTime); + ///< 繝輔ぃ繧、繝ォ譎ょ綾險ュ螳 + BOOL Close(); + ///< 繝輔ぃ繧、繝ォ繧ッ繝ュ繝シ繧コ + +private: + DWORD m_nKey; ///< Human68k縺ョFCB繝舌ャ繝輔ぃ繧「繝峨Ξ繧ケ (0縺ェ繧画悴菴ソ逕ィ) + BOOL m_bUpdate; ///< 譖エ譁ー繝輔Λ繧ー + FILE* m_pFile; ///< 繝帙せ繝亥エ縺ョ繝輔ぃ繧、繝ォ繧ェ繝悶ず繧ァ繧ッ繝 + const char* m_pszMode; ///< 繝帙せ繝亥エ縺ョ繝輔ぃ繧、繝ォ繧ェ繝シ繝励Φ繝「繝シ繝 + bool m_bFlag; ///< 繝帙せ繝亥エ縺ョ繝輔ぃ繧、繝ォ繧ェ繝シ繝励Φ繝輔Λ繧ー + BYTE m_szHumanPath[HUMAN68K_PATH_MAX]; + ///< Human68k縺ョ繝代せ蜷 + TCHAR m_szFilename[FILEPATH_MAX]; ///< 繝帙せ繝亥エ縺ョ繝輔ぃ繧、繝ォ蜷 +}; + +//=========================================================================== +// +/// FCB蜃ヲ逅 繝槭ロ繝シ繧ク繝」 +// +//=========================================================================== +class CHostFcbManager { +public: +#ifdef _DEBUG + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + ~CHostFcbManager(); + ///< 繝繧ケ繝医Λ繧ッ繧ソ final +#endif // _DEBUG + void Init(); + ///< 蛻晄悄蛹 (繝峨Λ繧、繝千オ霎シ縺ソ譎) + void Clean(); + ///< 隗」謾セ (襍キ蜍輔サ繝ェ繧サ繝繝域凾) + + CHostFcb* Alloc(DWORD nKey); + ///< 遒コ菫 + CHostFcb* Search(DWORD nKey); + ///< 讀懃エ「 + void Free(CHostFcb* p); + ///< 隗」謾セ + +private: + /// 繝。繝「繝ェ邂。逅逕ィ + struct ring_t { + CRing r; ///< 蜀迺ー + CHostFcb f; ///< 螳滉ス + }; + + CRing m_cRing; ///< CHostFcb騾」邨千畑 +}; + +//=========================================================================== +// +/// 繝帙せ繝亥エ繝峨Λ繧、繝 +/// +/// 繝峨Λ繧、繝匁ッ弱↓蠢隕√↑諠蝣ア縺ョ菫晄戟縺ォ蟆ょソオ縺励∫ョ。逅縺ッCHostEntry縺ァ陦後↑縺縲 +// +//=========================================================================== +class CHostDrv +{ +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + CHostDrv(); + ///< 繝繝輔か繝ォ繝医さ繝ウ繧ケ繝医Λ繧ッ繧ソ + ~CHostDrv(); + ///< 繝繧ケ繝医Λ繧ッ繧ソ final + void Init(const TCHAR* szBase, DWORD nFlag); + ///< 蛻晄悄蛹 (繝繝舌う繧ケ襍キ蜍輔→繝ュ繝シ繝) + + BOOL isWriteProtect() const { ASSERT(this); return m_bWriteProtect; } + ///< 譖ク縺崎セシ縺ソ遖∵ュ「縺具シ + BOOL isEnable() const { ASSERT(this); return m_bEnable; } + ///< 繧「繧ッ繧サ繧ケ蜿ッ閭ス縺具シ + BOOL isMediaOffline(); + ///< 繝。繝繧」繧「繝√ぉ繝繧ッ + BYTE GetMediaByte() const; + ///< 繝。繝繧」繧「繝舌う繝医ョ蜿門セ + DWORD GetStatus() const; + ///< 繝峨Λ繧、繝也憾諷九ョ蜿門セ + void SetEnable(BOOL bEnable); + ///< 繝。繝繧」繧「迥カ諷玖ィュ螳 + void GetVolume(TCHAR* szLabel); + ///< 繝懊Μ繝・繝シ繝繝ゥ繝吶Ν縺ョ蜿門セ + BOOL GetVolumeCache(TCHAR* szLabel) const; + ///< 繧ュ繝」繝繧キ繝・縺九i繝懊Μ繝・繝シ繝繝ゥ繝吶Ν繧貞叙蠕 + DWORD GetCapacity(Human68k::capacity_t* pCapacity); + ///< 螳ケ驥上ョ蜿門セ + BOOL GetCapacityCache(Human68k::capacity_t* pCapacity) const; + ///< 繧ュ繝」繝繧キ繝・縺九i螳ケ驥上r蜿門セ + + // 繧ュ繝」繝繧キ繝・謫堺ス + void CleanCache(); + ///< 蜈ィ縺ヲ縺ョ繧ュ繝」繝繧キ繝・繧呈峩譁ー縺吶k + void CleanCache(const BYTE* szHumanPath); + ///< 謖螳壹&繧後◆繝代せ縺ョ繧ュ繝」繝繧キ繝・繧呈峩譁ー縺吶k + void CleanCacheChild(const BYTE* szHumanPath); + ///< 謖螳壹&繧後◆繝代せ莉・荳九ョ繧ュ繝」繝繧キ繝・繧貞ィ縺ヲ譖エ譁ー縺吶k + void DeleteCache(const BYTE* szHumanPath); + ///< 謖螳壹&繧後◆繝代せ縺ョ繧ュ繝」繝繧キ繝・繧貞炎髯、縺吶k + CHostPath* FindCache(const BYTE* szHuman); + ///< 謖螳壹&繧後◆繝代せ縺後く繝」繝繧キ繝・縺輔l縺ヲ縺繧九°讀懃エ「縺吶k + CHostPath* CopyCache(CHostFiles* pFiles); + ///< 繧ュ繝」繝繧キ繝・諠蝣ア繧貞縺ォ縲√帙せ繝亥エ縺ョ蜷咲ァー繧堤佐蠕励☆繧 + CHostPath* MakeCache(CHostFiles* pFiles); + ///< 繝帙せ繝亥エ縺ョ蜷咲ァー縺ョ讒狗ッ峨↓蠢隕√↑諠蝣ア繧偵☆縺ケ縺ヲ蜿門セ励☆繧 + BOOL Find(CHostFiles* pFiles); + ///< 繝帙せ繝亥エ縺ョ蜷咲ァー繧呈、懃エ「 (繝代せ蜷+繝輔ぃ繧、繝ォ蜷(逵∫払蜿ッ)+螻樊ァ) + +private: + // 繝代せ蜷肴桃菴 + static const BYTE* SeparateCopyFilename(const BYTE* szHuman, BYTE* szBuffer); + ///< Human68k繝輔Ν繝代せ蜷阪°繧牙磯ュ縺ョ隕∫エ繧貞髮「繝サ繧ウ繝斐シ + + // 謗剃サ門宛蠕。 + void Lock() {} + void Unlock() {} + + /// 繝。繝「繝ェ邂。逅逕ィ + struct ring_t { + CRing r; ///< 蜀迺ー + CHostPath f; ///< 螳滉ス + }; + + BOOL m_bWriteProtect; ///< 譖ク縺崎セシ縺ソ遖∵ュ「縺ェ繧欝RUE + BOOL m_bEnable; ///< 繝。繝繧」繧「縺悟茜逕ィ蜿ッ閭ス縺ェ繧欝RUE + DWORD m_nRing; ///< 繝代せ蜷堺ソ晄戟謨ー + CRing m_cRing; ///< CHostPath騾」邨千畑 + Human68k::capacity_t m_capCache; ///< 繧サ繧ッ繧ソ諠蝣ア繧ュ繝」繝繧キ繝・ sectors == 0 縺ェ繧画悴繧ュ繝」繝繧キ繝・ + BOOL m_bVolumeCache; ///< 繝懊Μ繝・繝シ繝繝ゥ繝吶Ν隱ュ縺ソ霎シ縺ソ貂医∩縺ェ繧欝RUE + TCHAR m_szVolumeCache[24]; ///< 繝懊Μ繝・繝シ繝繝ゥ繝吶Ν繧ュ繝」繝繧キ繝・ + TCHAR m_szBase[FILEPATH_MAX]; ///< 繝吶シ繧ケ繝代せ +}; + +//=========================================================================== +// +/// 繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ邂。逅 +// +//=========================================================================== +class CHostEntry { +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + CHostEntry(); + ///< 繝繝輔か繝ォ繝医さ繝ウ繧ケ繝医Λ繧ッ繧ソ + ~CHostEntry(); + ///< 繝繧ケ繝医Λ繧ッ繧ソ final + void Init(); + ///< 蛻晄悄蛹 (繝峨Λ繧、繝千オ霎シ縺ソ譎) + void Clean(); + ///< 隗」謾セ (襍キ蜍輔サ繝ェ繧サ繝繝域凾) + + // 繧ュ繝」繝繧キ繝・謫堺ス + void CleanCache(); + ///< 蜈ィ縺ヲ縺ョ繧ュ繝」繝繧キ繝・繧呈峩譁ー縺吶k + void CleanCache(DWORD nUnit); + ///< 謖螳壹&繧後◆繝ヲ繝九ャ繝医ョ繧ュ繝」繝繧キ繝・繧呈峩譁ー縺吶k + void CleanCache(DWORD nUnit, const BYTE* szHumanPath); + ///< 謖螳壹&繧後◆繝代せ縺ョ繧ュ繝」繝繧キ繝・繧呈峩譁ー縺吶k + void CleanCacheChild(DWORD nUnit, const BYTE* szHumanPath); + ///< 謖螳壹&繧後◆繝代せ莉・荳九ョ繧ュ繝」繝繧キ繝・繧貞ィ縺ヲ譖エ譁ー縺吶k + void DeleteCache(DWORD nUnit, const BYTE* szHumanPath); + ///< 謖螳壹&繧後◆繝代せ縺ョ繧ュ繝」繝繧キ繝・繧貞炎髯、縺吶k + BOOL Find(DWORD nUnit, CHostFiles* pFiles); + ///< 繝帙せ繝亥エ縺ョ蜷咲ァー繧呈、懃エ「 (繝代せ蜷+繝輔ぃ繧、繝ォ蜷(逵∫払蜿ッ)+螻樊ァ) + void ShellNotify(DWORD nEvent, const TCHAR* szPath); + ///< 繝帙せ繝亥エ繝輔ぃ繧、繝ォ繧キ繧ケ繝繝迥カ諷句、牙喧騾夂衍 + + // 繝峨Λ繧、繝悶が繝悶ず繧ァ繧ッ繝域桃菴 + void SetDrv(DWORD nUnit, CHostDrv* pDrv); + ///< 繝峨Λ繧、繝冶ィュ螳 + BOOL isWriteProtect(DWORD nUnit) const; + ///< 譖ク縺崎セシ縺ソ遖∵ュ「縺具シ + BOOL isEnable(DWORD nUnit) const; + ///< 繧「繧ッ繧サ繧ケ蜿ッ閭ス縺具シ + BOOL isMediaOffline(DWORD nUnit); + ///< 繝。繝繧」繧「繝√ぉ繝繧ッ + BYTE GetMediaByte(DWORD nUnit) const; + ///< 繝。繝繧」繧「繝舌う繝医ョ蜿門セ + DWORD GetStatus(DWORD nUnit) const; + ///< 繝峨Λ繧、繝也憾諷九ョ蜿門セ + void GetVolume(DWORD nUnit, TCHAR* szLabel); + ///< 繝懊Μ繝・繝シ繝繝ゥ繝吶Ν縺ョ蜿門セ + BOOL GetVolumeCache(DWORD nUnit, TCHAR* szLabel) const; + ///< 繧ュ繝」繝繧キ繝・縺九i繝懊Μ繝・繝シ繝繝ゥ繝吶Ν繧貞叙蠕 + DWORD GetCapacity(DWORD nUnit, Human68k::capacity_t* pCapacity); + ///< 螳ケ驥上ョ蜿門セ + BOOL GetCapacityCache(DWORD nUnit, Human68k::capacity_t* pCapacity) const; + ///< 繧ュ繝」繝繧キ繝・縺九i繧ッ繝ゥ繧ケ繧ソ繧オ繧、繧コ繧貞叙蠕 + + /// 螳壽焚 + enum { + DriveMax = 10 ///< 繝峨Λ繧、繝匁怙螟ァ蛟呵」懈焚 + }; + +private: + CHostDrv* m_pDrv[DriveMax]; ///< 繝帙せ繝亥エ繝峨Λ繧、繝悶が繝悶ず繧ァ繧ッ繝 + DWORD m_nTimeout; ///< 譛蠕後↓繧ソ繧、繝繧「繧ヲ繝医メ繧ァ繝繧ッ繧定。後↑縺」縺滓凾蛻サ +}; + +//=========================================================================== +// +/// 繝帙せ繝亥エ繝輔ぃ繧、繝ォ繧キ繧ケ繝繝 +// +//=========================================================================== +/** @note +迴セ蝨ィ縺ョ隕玖ァ」縲 + +XM6縺ョ險ュ險域晄Φ縺ィ縺ッ蜿阪☆繧九′縲…lass Windrv縺セ縺溘ッclass CWindrv縺ォ逶エ謗・ +class CFileSys縺ク縺ョ繝昴う繝ウ繧ソ繧呈戟縺溘○繧区婿豕輔r讓。邏「縺吶k縺ケ縺阪〒縺ゅk縲 +縺薙l縺ォ繧医j縲∽サ・荳九ョ繝。繝ェ繝繝医′蠕励i繧後k縲 + +繝。繝ェ繝繝医◎縺ョ1縲 +繧ウ繝槭Φ繝峨ワ繝ウ繝峨Λ縺ョ螟ァ驥上ョ繝。繧ス繝繝臥セ、繧剃ク繝カ謇縺ァ髮荳ュ邂。逅縺ァ縺阪k縲 +繧ウ繝槭Φ繝峨ワ繝ウ繝峨Λ縺ッ繝帙せ繝亥エ縺ョ莉墓ァ伜、画峩縺ェ縺ゥ縺ョ隕∝屏縺ォ繧医▲縺ヲ豼縺励¥螟牙喧縺吶k +蜿ッ閭ス諤ァ縺碁ォ倥>縺溘a縲√Γ繧ス繝繝峨ョ霑ス蜉蜑企勁繧蠑墓焚縺ョ螟画峩縺ェ縺ゥ縺ョ繝。繝ウ繝繝翫Φ繧ケ縺 +螟ァ蟷縺ォ讌ス縺ォ縺ェ繧九 + +繝。繝ェ繝繝医◎縺ョ2縲 +莉ョ諠ウ髢「謨ー縺ョ繝繝シ繝悶Ν逕滓舌サ蜿らァ蜃ヲ逅縺ォ髢「縺吶k蜃ヲ逅繧ウ繝シ繝峨r鬧騾舌〒縺阪k縲 +XM6縺ァ縺ッ隍謨ー縺ョ繝輔ぃ繧、繝ォ繧キ繧ケ繝繝繧ェ繝悶ず繧ァ繧ッ繝医r蜷梧凾縺ォ菴ソ縺繧医≧縺ェ螳溯」縺ッ +縺ゅj縺医↑縺縲ゅ▽縺セ繧翫ヵ繧。繧、繝ォ繧キ繧ケ繝繝繧ェ繝悶ず繧ァ繧ッ繝医↓繝昴Μ繝「繝シ繝輔ぅ繧コ繝縺ッ +縺セ縺」縺溘¥蠢隕√↑縺縺ゥ縺薙m縺九√◆縺繧ッ繝ュ繝繧ッ縺ョ辟。鬧縺ィ縺ェ縺」縺ヲ縺繧九□縺代〒縺ゅk縲 + +隧ヲ縺励↓螟峨∴縺ヲ縺ソ縺溘ょョ滄圀蜉ケ邇荳翫′縺」縺溘 +windrv.h蜀縺ョFILESYS_FAST_STRUCTURE縺ョ蛟、繧貞、峨∴縺ヲ繧ウ繝ウ繝代う繝ゥ縺ョ蜷舌¥繧ス繝シ繧ケ +繧呈ッ碑シ縺吶l縺ー荳逶ョ迸ュ辟カ縲ゆス墓腐遘√′縺薙s縺ェ髟キ譁繧呈嶌縺薙≧縺ィ諤昴▲縺溘ョ縺九r逅隗」縺ァ +縺阪k縺ッ縺壹 + +荳譁ケ繝ュ繧キ繧「縺ッclass CWindrv蜀縺ォclass CFileSys繧堤峩謗・險ュ鄂ョ縺励◆縲 +(譛ャ蠖薙ッclass CHost繧貞サ豁「縺励※逶エ謗・鄂ョ縺阪◆縺窶ヲ窶ヲ濶ッ縺譁ケ豕輔ッ縺ェ縺繧ゅョ縺銀ヲ窶ヲ) +*/ +class CFileSys +{ +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + CFileSys(); + ///< 繝繝輔か繝ォ繝医さ繝ウ繧ケ繝医Λ繧ッ繧ソ + virtual ~CFileSys() {}; + ///< 繝繧ケ繝医Λ繧ッ繧ソ + + // 蛻晄悄蛹悶サ邨ゆコ + void Reset(); + ///< 繝ェ繧サ繝繝 (蜈ィ繧ッ繝ュ繝シ繧コ) + void Init(); + ///< 蛻晄悄蛹 (繝繝舌う繧ケ襍キ蜍輔→繝ュ繝シ繝) + + // 繧ウ繝槭Φ繝峨ワ繝ウ繝峨Λ + DWORD InitDevice(const Human68k::argument_t* pArgument); + ///< $40 - 繝繝舌う繧ケ襍キ蜍 + int CheckDir(DWORD nUnit, const Human68k::namests_t* pNamests); + ///< $41 - 繝繧」繝ャ繧ッ繝医Μ繝√ぉ繝繧ッ + int MakeDir(DWORD nUnit, const Human68k::namests_t* pNamests); + ///< $42 - 繝繧」繝ャ繧ッ繝医Μ菴懈 + int RemoveDir(DWORD nUnit, const Human68k::namests_t* pNamests); + ///< $43 - 繝繧」繝ャ繧ッ繝医Μ蜑企勁 + int Rename(DWORD nUnit, const Human68k::namests_t* pNamests, const Human68k::namests_t* pNamestsNew); + ///< $44 - 繝輔ぃ繧、繝ォ蜷榊、画峩 + int Delete(DWORD nUnit, const Human68k::namests_t* pNamests); + ///< $45 - 繝輔ぃ繧、繝ォ蜑企勁 + int Attribute(DWORD nUnit, const Human68k::namests_t* pNamests, DWORD nHumanAttribute); + ///< $46 - 繝輔ぃ繧、繝ォ螻樊ァ蜿門セ/險ュ螳 + int Files(DWORD nUnit, DWORD nKey, const Human68k::namests_t* pNamests, Human68k::files_t* pFiles); + ///< $47 - 繝輔ぃ繧、繝ォ讀懃エ「 + int NFiles(DWORD nUnit, DWORD nKey, Human68k::files_t* pFiles); + ///< $48 - 繝輔ぃ繧、繝ォ谺。讀懃エ「 + int Create(DWORD nUnit, DWORD nKey, const Human68k::namests_t* pNamests, Human68k::fcb_t* pFcb, DWORD nHumanAttribute, BOOL bForce); + ///< $49 - 繝輔ぃ繧、繝ォ菴懈 + int Open(DWORD nUnit, DWORD nKey, const Human68k::namests_t* pNamests, Human68k::fcb_t* pFcb); + ///< $4A - 繝輔ぃ繧、繝ォ繧ェ繝シ繝励Φ + int Close(DWORD nUnit, DWORD nKey, Human68k::fcb_t* pFcb); + ///< $4B - 繝輔ぃ繧、繝ォ繧ッ繝ュ繝シ繧コ + int Read(DWORD nKey, Human68k::fcb_t* pFcb, BYTE* pAddress, DWORD nSize); + ///< $4C - 繝輔ぃ繧、繝ォ隱ュ縺ソ霎シ縺ソ + int Write(DWORD nKey, Human68k::fcb_t* pFcb, const BYTE* pAddress, DWORD nSize); + ///< $4D - 繝輔ぃ繧、繝ォ譖ク縺崎セシ縺ソ + int Seek(DWORD nKey, Human68k::fcb_t* pFcb, DWORD nSeek, int nOffset); + ///< $4E - 繝輔ぃ繧、繝ォ繧キ繝シ繧ッ + DWORD TimeStamp(DWORD nUnit, DWORD nKey, Human68k::fcb_t* pFcb, DWORD nHumanTime); + ///< $4F - 繝輔ぃ繧、繝ォ譎ょ綾蜿門セ/險ュ螳 + int GetCapacity(DWORD nUnit, Human68k::capacity_t* pCapacity); + ///< $50 - 螳ケ驥丞叙蠕 + int CtrlDrive(DWORD nUnit, Human68k::ctrldrive_t* pCtrlDrive); + ///< $51 - 繝峨Λ繧、繝也憾諷区、懈渊/蛻カ蠕。 + int GetDPB(DWORD nUnit, Human68k::dpb_t* pDpb); + ///< $52 - DPB蜿門セ + int DiskRead(DWORD nUnit, BYTE* pBuffer, DWORD nSector, DWORD nSize); + ///< $53 - 繧サ繧ッ繧ソ隱ュ縺ソ霎シ縺ソ + int DiskWrite(DWORD nUnit); + ///< $54 - 繧サ繧ッ繧ソ譖ク縺崎セシ縺ソ + int Ioctrl(DWORD nUnit, DWORD nFunction, Human68k::ioctrl_t* pIoctrl); + ///< $55 - IOCTRL + int Flush(DWORD nUnit); + ///< $56 - 繝輔Λ繝繧キ繝・ + int CheckMedia(DWORD nUnit); + ///< $57 - 繝。繝繧」繧「莠、謠帙メ繧ァ繝繧ッ + int Lock(DWORD nUnit); + ///< $58 - 謗剃サ門宛蠕。 + + void SetOption(DWORD nOption); + ///< 繧ェ繝励す繝ァ繝ウ險ュ螳 + DWORD GetOption() const { ASSERT(this); return m_nOption; } + ///< 繧ェ繝励す繝ァ繝ウ蜿門セ + DWORD GetDefault() const { ASSERT(this); return m_nOptionDefault; } + ///< 繝繝輔か繝ォ繝医が繝励す繝ァ繝ウ蜿門セ + static DWORD GetFileOption() { return g_nOption; } + ///< 繝輔ぃ繧、繝ォ蜷榊、画鋤繧ェ繝励す繝ァ繝ウ蜿門セ + void ShellNotify(DWORD nEvent, const TCHAR* szPath) + { ASSERT(this); m_cEntry.ShellNotify(nEvent, szPath); } + ///< 繝帙せ繝亥エ繝輔ぃ繧、繝ォ繧キ繧ケ繝繝迥カ諷句、牙喧騾夂衍 + + /// 螳壽焚 + enum { + DriveMax = CHostEntry::DriveMax ///< 繝峨Λ繧、繝匁怙螟ァ蛟呵」懈焚 + }; + +private: + // 蜀驛ィ陬懷勧逕ィ + void InitOption(const Human68k::argument_t* pArgument); + ///< 繧ェ繝励す繝ァ繝ウ蛻晄悄蛹 + BOOL FilesVolume(DWORD nUnit, Human68k::files_t* pFiles); + ///< 繝懊Μ繝・繝シ繝繝ゥ繝吶Ν蜿門セ + + DWORD m_nUnits; ///< 迴セ蝨ィ縺ョ繝峨Λ繧、繝悶が繝悶ず繧ァ繧ッ繝域焚 (繝ャ繧ク繝・繝シ繝豈弱↓螟牙喧) + + DWORD m_nOption; ///< 迴セ蝨ィ縺ョ蜍穂ス懊ヵ繝ゥ繧ー + DWORD m_nOptionDefault; ///< 繝ェ繧サ繝繝域凾縺ョ蜍穂ス懊ヵ繝ゥ繧ー + + DWORD m_nDrives; ///< 繝吶シ繧ケ繝代せ迥カ諷句セゥ蜈逕ィ縺ョ蛟呵」懈焚 (0縺ェ繧画ッ主屓繧ケ繧ュ繝」繝ウ) + + DWORD m_nKernel; ///< 繧ォ繝シ繝阪Ν繝√ぉ繝繧ッ逕ィ繧ォ繧ヲ繝ウ繧ソ + DWORD m_nKernelSearch; ///< NUL繝繝舌う繧ケ縺ョ蜈磯ュ繧「繝峨Ξ繧ケ + + DWORD m_nHostSectorCount; ///< 謫ャ莨シ繧サ繧ッ繧ソ逡ェ蜿キ + + CHostFilesManager m_cFiles; ///< 繝輔ぃ繧、繝ォ讀懃エ「鬆伜沺 + CHostFcbManager m_cFcb; ///< FCB謫堺ス憺伜沺 + CHostEntry m_cEntry; ///< 繝峨Λ繧、繝悶が繝悶ず繧ァ繧ッ繝医→繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ + + DWORD m_nHostSectorBuffer[XM6_HOST_PSEUDO_CLUSTER_MAX]; + ///< 謫ャ莨シ繧サ繧ッ繧ソ縺ョ謖縺吶ヵ繧。繧、繝ォ螳滉ス + + DWORD m_nFlag[DriveMax]; ///< 繝吶シ繧ケ繝代せ迥カ諷句セゥ蜈逕ィ縺ョ蜍穂ス懊ヵ繝ゥ繧ー蛟呵」 + TCHAR m_szBase[DriveMax][FILEPATH_MAX]; + ///< 繝吶シ繧ケ繝代せ迥カ諷句セゥ蜈逕ィ縺ョ蛟呵」 + static DWORD g_nOption; ///< 繝輔ぃ繧、繝ォ蜷榊、画鋤繝輔Λ繧ー +}; + +#endif // cfilesystem_h diff --git a/src/raspberrypi/cqueue.h b/src/raspberrypi/cqueue.h new file mode 100644 index 00000000..27802a51 --- /dev/null +++ b/src/raspberrypi/cqueue.h @@ -0,0 +1,68 @@ +//--------------------------------------------------------------------------- +// +// X68000 EMULATOR "XM6" +// +// Copyright (C) 2001-2004 PI.(ytanaka@ipc-tokai.or.jp) +// [ MFC キュー ] +// +//--------------------------------------------------------------------------- + +#if !defined(queue_h) +#define queue_h + +//=========================================================================== +// +// キュー +// +//=========================================================================== +class CQueue +{ +public: + // 内部データ定義 + typedef struct _QUQUEINFO { + BYTE *pBuf; // バッファ + DWORD dwSize; // サイズ + DWORD dwMask; // マスク(サイズ-1) + DWORD dwRead; // Readポインタ + DWORD dwWrite; // Writeポインタ + DWORD dwNum; // 個数 + DWORD dwTotalRead; // 合計Read + DWORD dwTotalWrite; // 合計Write + } QUEUEINFO, *LPQUEUEINFO; + + // 基本ファンクション + CQueue(); + // コンストラクタ + virtual ~CQueue(); + // デストラクタ + BOOL FASTCALL Init(DWORD dwSize); + // 初期化 + + // API + void FASTCALL Clear(); + // クリア + BOOL FASTCALL IsEmpty() const { return (BOOL)(m_Queue.dwNum == 0); } + // キューが空かチェック + DWORD FASTCALL GetNum() const { return m_Queue.dwNum; } + // キューのデータ数を取得 + DWORD FASTCALL Get(BYTE *pDest); + // キュー内のデータをすべて取得 + DWORD FASTCALL Copy(BYTE *pDest) const; + // キュー内のデータをすべて取得(キュー進めない) + void FASTCALL Discard(DWORD dwNum); + // キューを進める + void FASTCALL Back(DWORD dwNum); + // キューを戻す + DWORD FASTCALL GetFree() const; + // キューの空き個数を取得 + BOOL FASTCALL Insert(const BYTE *pSrc, DWORD dwLength); + // キューに挿入 + void FASTCALL GetQueue(QUEUEINFO *pInfo) const; + // キュー情報取得 + +private: + QUEUEINFO m_Queue; + // 内部ワーク +}; + +#endif // queue_h diff --git a/src/raspberrypi/ctapdriver.cpp b/src/raspberrypi/ctapdriver.cpp new file mode 100644 index 00000000..fbcb3d44 --- /dev/null +++ b/src/raspberrypi/ctapdriver.cpp @@ -0,0 +1,209 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technology. +// Copyright (C) 2016-2018 GIMONS +// +// Imported NetBSD support and some optimisation patch by Rin Okuyama. +// +// [ TAP繝峨Λ繧、繝 ] +// +//--------------------------------------------------------------------------- + +#include "os.h" +#include "xm6.h" +#include "ctapdriver.h" + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +CTapDriver::CTapDriver() +{ + // 蛻晄悄蛹 + m_hTAP = -1; + memset(&m_MacAddr, 0, sizeof(m_MacAddr)); +} + +//--------------------------------------------------------------------------- +// +// 蛻晄悄蛹 +// +//--------------------------------------------------------------------------- +#ifdef __linux__ +BOOL FASTCALL CTapDriver::Init() +{ + char dev[IFNAMSIZ] = "ras0"; + struct ifreq ifr; + int ret; + + ASSERT(this); + + // TAP繝繝舌う繧ケ蛻晄悄蛹 + if ((m_hTAP = open("/dev/net/tun", O_RDWR)) < 0) { + printf("Error: can't open tun\n"); + return FALSE; + } + + // IFF_NO_PI for no extra packet information + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_flags = IFF_TAP | IFF_NO_PI; + strncpy(ifr.ifr_name, dev, IFNAMSIZ); + if ((ret = ioctl(m_hTAP, TUNSETIFF, (void *)&ifr)) < 0) { + printf("Error: can't ioctl TUNSETIFF\n"); + close(m_hTAP); + return FALSE; + } + + // MAC繧「繝峨Ξ繧ケ蜿門セ + ifr.ifr_addr.sa_family = AF_INET; + if ((ret = ioctl(m_hTAP, SIOCGIFHWADDR, &ifr)) < 0) { + printf("Error: can't ioctl SIOCGIFHWADDR\n"); + close(m_hTAP); + return FALSE; + } + + // MAC繧「繝峨Ξ繧ケ菫晏ュ + memcpy(m_MacAddr, ifr.ifr_hwaddr.sa_data, sizeof(m_MacAddr)); + return TRUE; +} +#endif // __linux__ + +#ifdef __NetBSD__ +BOOL FASTCALL CTapDriver::Init() +{ + struct ifreq ifr; + struct ifaddrs *ifa, *a; + + ASSERT(this); + + // TAP繝繝舌う繧ケ蛻晄悄蛹 + if ((m_hTAP = open("/dev/tap", O_RDWR)) < 0) { + printf("Error: can't open tap\n"); + return FALSE; + } + + // 繝繝舌う繧ケ蜷榊叙蠕 + if (ioctl(m_hTAP, TAPGIFNAME, (void *)&ifr) < 0) { + printf("Error: can't ioctl TAPGIFNAME\n"); + close(m_hTAP); + return FALSE; + } + + // MAC繧「繝峨Ξ繧ケ蜿門セ + if (getifaddrs(&ifa) == -1) { + printf("Error: can't getifaddrs\n"); + close(m_hTAP); + return FALSE; + } + for (a = ifa; a != NULL; a = a->ifa_next) + if (strcmp(ifr.ifr_name, a->ifa_name) == 0 && + a->ifa_addr->sa_family == AF_LINK) + break; + if (a == NULL) { + printf("Error: can't get MAC address\n"); + close(m_hTAP); + return FALSE; + } + + // MAC繧「繝峨Ξ繧ケ菫晏ュ + memcpy(m_MacAddr, LLADDR((struct sockaddr_dl *)a->ifa_addr), + sizeof(m_MacAddr)); + freeifaddrs(ifa); + + printf("Tap device : %s\n", ifr.ifr_name); + + return TRUE; +} +#endif // __NetBSD__ + +//--------------------------------------------------------------------------- +// +// 繧ッ繝ェ繝シ繝ウ繧「繝繝 +// +//--------------------------------------------------------------------------- +void FASTCALL CTapDriver::Cleanup() +{ + ASSERT(this); + + // TAP繝繝舌う繧ケ隗」謾セ + if (m_hTAP != -1) { + close(m_hTAP); + m_hTAP = -1; + } +} + +//--------------------------------------------------------------------------- +// +// MAC繧「繝峨Ξ繧ケ蜿門セ +// +//--------------------------------------------------------------------------- +void FASTCALL CTapDriver::GetMacAddr(BYTE *mac) +{ + ASSERT(this); + ASSERT(mac); + + memcpy(mac, m_MacAddr, sizeof(m_MacAddr)); +} + +//--------------------------------------------------------------------------- +// +// 蜿嶺ソ。 +// +//--------------------------------------------------------------------------- +int FASTCALL CTapDriver::Rx(BYTE *buf) +{ + struct pollfd fds; + DWORD dwReceived; + + ASSERT(this); + ASSERT(m_hTAP != -1); + + // 蜿嶺ソ。蜿ッ閭ス縺ェ繝繝シ繧ソ縺後≠繧九°隱ソ縺ケ繧 + fds.fd = m_hTAP; + fds.events = POLLIN | POLLERR; + fds.revents = 0; + poll(&fds, 1, 0); + if (!(fds.revents & POLLIN)) { + return 0; + } + + // 蜿嶺ソ。 + dwReceived = read(m_hTAP, buf, ETH_FRAME_LEN); + if (dwReceived == (DWORD)-1) { + return 0; + } + + // 蜿嶺ソ。縺梧怏蜉ケ縺ァ縺ゅl縺ー + if (dwReceived > 0) { + // FCS繧帝勁縺乗怙蟆上ヵ繝ャ繝シ繝繧オ繧、繧コ(60繝舌う繝)縺ォ繝代ョ繧」繝ウ繧ー + if (dwReceived < 60) { + memset(buf + dwReceived, 0, 60 - dwReceived); + dwReceived = 60; + } + + // 繝繝溘シ縺ョFCS繧剃サ伜刈縺吶k + memset(buf + dwReceived, 0, 4); + dwReceived += 4; + } + + // 繝舌う繝域焚繧定ソ泌唆 + return dwReceived; +} + +//--------------------------------------------------------------------------- +// +// 騾∽ソ。 +// +//--------------------------------------------------------------------------- +int FASTCALL CTapDriver::Tx(BYTE *buf, int len) +{ + ASSERT(this); + ASSERT(m_hTAP != -1); + + // 騾∽ソ。髢句ァ + return write(m_hTAP, buf, len); +} \ No newline at end of file diff --git a/src/raspberrypi/ctapdriver.h b/src/raspberrypi/ctapdriver.h new file mode 100644 index 00000000..9f7b3f44 --- /dev/null +++ b/src/raspberrypi/ctapdriver.h @@ -0,0 +1,53 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technology. +// Copyright (C) 2016-2018 GIMONS +// +// Imported NetBSD support and some optimisation patch by Rin Okuyama. +// +// [ TAP繝峨Λ繧、繝 ] +// +//--------------------------------------------------------------------------- + +#if !defined(ctapdriver_h) +#define ctapdriver_h + +#ifndef ETH_FRAME_LEN +#define ETH_FRAME_LEN 1514 +#endif + +//=========================================================================== +// +// Tap繝峨Λ繧、繝 +// +//=========================================================================== +class CTapDriver +{ +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + CTapDriver(); + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + BOOL FASTCALL Init(); + // 蛻晄悄蛹 + void FASTCALL Cleanup(); + // 繧ッ繝ェ繝シ繝ウ繧「繝繝 + void FASTCALL GetMacAddr(BYTE *mac); + // MAC繧「繝峨Ξ繧ケ蜿門セ + int FASTCALL Rx(BYTE *buf); + // 蜿嶺ソ。 + int FASTCALL Tx(BYTE *buf, int len); + // 騾∽ソ。 + +private: + BYTE m_MacAddr[6]; + // MAC繧「繝峨Ξ繧ケ + BOOL m_bTxValid; + // 騾∽ソ。譛牙柑繝輔Λ繧ー + int m_hTAP; + // 繝繧」繧ケ繧ッ繝励Μ繧ソ +}; + +#endif // ctapdriver_h diff --git a/src/raspberrypi/disk.cpp b/src/raspberrypi/disk.cpp new file mode 100644 index 00000000..869e1284 --- /dev/null +++ b/src/raspberrypi/disk.cpp @@ -0,0 +1,9160 @@ +//--------------------------------------------------------------------------- +// +// X68000 EMULATOR "XM6" +// +// Copyright (C) 2001-2006 シーシゥシ(ytanaka@ipc-tokai.or.jp) +// Copyright (C) 2014-2018 GIMONS +// +// XM6i +// Copyright (C) 2010-2015 isaki@NetBSD.org +// Copyright (C) 2010 Y.Sugahara +// +// Imported sava's Anex86/T98Next image and MO format support patch. +// Imported NetBSD support and some optimisation patch by Rin Okuyama. +// +// [ 繝繧」繧ケ繧ッ ] +// +//--------------------------------------------------------------------------- + +#include "os.h" +#include "xm6.h" +#include "fileio.h" +#ifdef RASCSI +#include "filepath.h" +#include "ctapdriver.h" +#include "cfilesystem.h" +#include "disk.h" +#else +#include "vm.h" +#include "disk.h" +#include "windrv.h" +#include "ctapdriver.h" +#include "mfc_com.h" +#include "mfc_host.h" +#endif // RASCSI + +//=========================================================================== +// +// 繝繧」繧ケ繧ッ +// +//=========================================================================== +//#define DISK_LOG + +#ifdef RASCSI +#define BENDER_SIGNATURE "RaSCSI" +#else +#define BENDER_SIGNATURE "XM6" +#endif + +//=========================================================================== +// +// 繝繧」繧ケ繧ッ繝医Λ繝繧ッ +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +DiskTrack::DiskTrack() +{ + // 蜀驛ィ諠蝣ア縺ョ蛻晄悄蛹 + dt.track = 0; + dt.size = 0; + dt.sectors = 0; + dt.raw = FALSE; + dt.init = FALSE; + dt.changed = FALSE; + dt.length = 0; + dt.buffer = NULL; + dt.maplen = 0; + dt.changemap = NULL; + dt.imgoffset = 0; +} + +//--------------------------------------------------------------------------- +// +// 繝繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +DiskTrack::~DiskTrack() +{ + // 繝。繝「繝ェ隗」謾セ縺ッ陦後≧縺後∬ェ蜍輔そ繝シ繝悶ッ縺励↑縺 + if (dt.buffer) { +#ifdef RASCSI + free(dt.buffer); +#else + delete[] dt.buffer; +#endif // RASCSI + dt.buffer = NULL; + } + if (dt.changemap) { + delete[] dt.changemap; + dt.changemap = NULL; + } +} + +//--------------------------------------------------------------------------- +// +// 蛻晄悄蛹 +// +//--------------------------------------------------------------------------- +void FASTCALL DiskTrack::Init( + int track, int size, int sectors, BOOL raw, off64_t imgoff) +{ + ASSERT(track >= 0); + ASSERT((size == 8) || (size == 9) || (size == 11)); + ASSERT((sectors > 0) && (sectors <= 0x100)); + ASSERT(imgoff >= 0); + + // 繝代Λ繝。繝シ繧ソ繧定ィュ螳 + dt.track = track; + dt.size = size; + dt.sectors = sectors; + dt.raw = raw; + + // 蛻晄悄蛹悶&繧後※縺縺ェ縺(繝ュ繝シ繝峨☆繧句ソ隕√≠繧) + dt.init = FALSE; + + // 螟画峩縺輔l縺ヲ縺縺ェ縺 + dt.changed = FALSE; + + // 螳溘ョ繝シ繧ソ縺セ縺ァ縺ョ繧ェ繝輔そ繝繝 + dt.imgoffset = imgoff; +} + +//--------------------------------------------------------------------------- +// +// 繝ュ繝シ繝 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL DiskTrack::Load(const Filepath& path) +{ + Fileio fio; + off64_t offset; + int i; + int length; + + ASSERT(this); + + // 譌「縺ォ繝ュ繝シ繝峨&繧後※縺繧後ー荳崎ヲ + if (dt.init) { + ASSERT(dt.buffer); + ASSERT(dt.changemap); + return TRUE; + } + + // 繧ェ繝輔そ繝繝医r險育ョ(縺薙l莉・蜑阪ョ繝医Λ繝繧ッ縺ッ256繧サ繧ッ繧ソ菫晄戟縺ィ縺ソ縺ェ縺) + offset = ((off64_t)dt.track << 8); + if (dt.raw) { + ASSERT(dt.size == 11); + offset *= 0x930; + offset += 0x10; + } else { + offset <<= dt.size; + } + + // 螳溘う繝。繝シ繧ク縺セ縺ァ縺ョ繧ェ繝輔そ繝繝医r霑ス蜉 + offset += dt.imgoffset; + + // 繝ャ繝ウ繧ー繧ケ繧定ィ育ョ(縺薙ョ繝医Λ繝繧ッ縺ョ繝繝シ繧ソ繧オ繧、繧コ) + length = dt.sectors << dt.size; + + // 繝舌ャ繝輔ぃ縺ョ繝。繝「繝ェ繧堤「コ菫 + ASSERT((dt.size == 8) || (dt.size == 9) || (dt.size == 11)); + ASSERT((dt.sectors > 0) && (dt.sectors <= 0x100)); + try { + // 繝舌ャ繝輔ぃ髟キ縺檎焚縺ェ繧九↑繧芽ァ」謾セ + if (dt.length != (DWORD)length) { + if (dt.buffer) { +#ifdef RASCSI + free(dt.buffer); +#else + delete[] dt.buffer; +#endif // RASCSI + dt.buffer = NULL; + } + } + + // 繝舌ャ繝輔ぃ遒コ菫 + dt.length = length; + if (dt.buffer == NULL) { +#ifdef RASCSI + posix_memalign((void **)&dt.buffer, 512, ((dt.length + 511) / 512) * 512); +#else + dt.buffer = new BYTE[dt.length]; +#endif // RASCSI + } + } + catch (...) { + dt.length = 0; + dt.buffer = NULL; + return FALSE; + } + if (!dt.buffer) { + return FALSE; + } + + // 螟画峩繝槭ャ繝励ョ繝。繝「繝ェ繧堤「コ菫 + try { + // 繝舌ャ繝輔ぃ髟キ縺檎焚縺ェ繧九↑繧芽ァ」謾セ + if (dt.maplen != (DWORD)dt.sectors) { + if (dt.changemap) { + delete[] dt.changemap; + dt.changemap = NULL; + } + } + + // 繝舌ャ繝輔ぃ遒コ菫 + dt.maplen = dt.sectors; + if (dt.changemap == NULL) { + dt.changemap = new BOOL[dt.maplen]; + } + } + catch (...) { + dt.maplen = 0; + dt.changemap = NULL; + return FALSE; + } + if (!dt.changemap) { + return FALSE; + } + + // 螟画峩繝槭ャ繝励r繧ッ繝ェ繧「 + memset(dt.changemap, 0x00, dt.sectors * sizeof(BOOL)); + + // 繝輔ぃ繧、繝ォ縺九i隱ュ縺ソ霎シ繧 +#ifdef RASCSI + if (!fio.OpenDIO(path, Fileio::ReadOnly)) { +#else + if (!fio.Open(path, Fileio::ReadOnly)) { +#endif // RASCSI + return FALSE; + } + if (dt.raw) { + // 蛻蜑イ隱ュ縺ソ + for (i = 0; i < dt.sectors; i++) { + // 繧キ繝シ繧ッ + if (!fio.Seek(offset)) { + fio.Close(); + return FALSE; + } + + // 隱ュ縺ソ霎シ縺ソ + if (!fio.Read(&dt.buffer[i << dt.size], 1 << dt.size)) { + fio.Close(); + return FALSE; + } + + // 谺。縺ョ繧ェ繝輔そ繝繝 + offset += 0x930; + } + } else { + // 騾」邯夊ェュ縺ソ + if (!fio.Seek(offset)) { + fio.Close(); + return FALSE; + } + if (!fio.Read(dt.buffer, length)) { + fio.Close(); + return FALSE; + } + } + fio.Close(); + + // 繝輔Λ繧ー繧堤ォ九※縲∵ュ」蟶ク邨ゆコ + dt.init = TRUE; + dt.changed = FALSE; + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繧サ繝シ繝 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL DiskTrack::Save(const Filepath& path) +{ + off64_t offset; + int i; + Fileio fio; + int length; + + ASSERT(this); + + // 蛻晄悄蛹悶&繧後※縺縺ェ縺代l縺ー荳崎ヲ + if (!dt.init) { + return TRUE; + } + + // 螟画峩縺輔l縺ヲ縺縺ェ縺代l縺ー荳崎ヲ + if (!dt.changed) { + return TRUE; + } + + // 譖ク縺崎セシ繧蠢隕√′縺ゅk + ASSERT(dt.buffer); + ASSERT(dt.changemap); + ASSERT((dt.size == 8) || (dt.size == 9) || (dt.size == 11)); + ASSERT((dt.sectors > 0) && (dt.sectors <= 0x100)); + + // RAW繝「繝シ繝峨〒縺ッ譖ク縺崎セシ縺ソ縺ッ縺ゅj縺医↑縺 + ASSERT(!dt.raw); + + // 繧ェ繝輔そ繝繝医r險育ョ(縺薙l莉・蜑阪ョ繝医Λ繝繧ッ縺ッ256繧サ繧ッ繧ソ菫晄戟縺ィ縺ソ縺ェ縺) + offset = ((off64_t)dt.track << 8); + offset <<= dt.size; + + // 螳溘う繝。繝シ繧ク縺セ縺ァ縺ョ繧ェ繝輔そ繝繝医r霑ス蜉 + offset += dt.imgoffset; + + // 繧サ繧ッ繧ソ縺ゅ◆繧翫ョ繝ャ繝ウ繧ー繧ケ繧定ィ育ョ + length = 1 << dt.size; + + // 繝輔ぃ繧、繝ォ繧ェ繝シ繝励Φ + if (!fio.Open(path, Fileio::ReadWrite)) { + return FALSE; + } + + // 譖ク縺崎セシ縺ソ繝ォ繝シ繝 + for (i = 0; i < dt.sectors; i++) { + // 螟画峩縺輔l縺ヲ縺繧後ー + if (dt.changemap[i]) { + // 繧キ繝シ繧ッ縲∵嶌縺崎セシ縺ソ + if (!fio.Seek(offset + ((off64_t)i << dt.size))) { + fio.Close(); + return FALSE; + } + if (!fio.Write(&dt.buffer[i << dt.size], length)) { + fio.Close(); + return FALSE; + } + + // 螟画峩繝輔Λ繧ー繧定誠縺ィ縺 + dt.changemap[i] = FALSE; + } + } + + // 繧ッ繝ュ繝シ繧コ + fio.Close(); + + // 螟画峩繝輔Λ繧ー繧定誠縺ィ縺励∫オゆコ + dt.changed = FALSE; + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繝ェ繝シ繝峨そ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL DiskTrack::Read(BYTE *buf, int sec) const +{ + ASSERT(this); + ASSERT(buf); + ASSERT((sec >= 0) & (sec < 0x100)); + + // 蛻晄悄蛹悶&繧後※縺縺ェ縺代l縺ー繧ィ繝ゥ繝シ + if (!dt.init) { + return FALSE; + } + + // 繧サ繧ッ繧ソ縺梧怏蜉ケ謨ー繧定カ縺医※縺繧後ー繧ィ繝ゥ繝シ + if (sec >= dt.sectors) { + return FALSE; + } + + // 繧ウ繝斐シ + ASSERT(dt.buffer); + ASSERT((dt.size == 8) || (dt.size == 9) || (dt.size == 11)); + ASSERT((dt.sectors > 0) && (dt.sectors <= 0x100)); + memcpy(buf, &dt.buffer[(off64_t)sec << dt.size], (off64_t)1 << dt.size); + + // 謌仙粥 + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繝ゥ繧、繝医そ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL DiskTrack::Write(const BYTE *buf, int sec) +{ + int offset; + int length; + + ASSERT(this); + ASSERT(buf); + ASSERT((sec >= 0) & (sec < 0x100)); + ASSERT(!dt.raw); + + // 蛻晄悄蛹悶&繧後※縺縺ェ縺代l縺ー繧ィ繝ゥ繝シ + if (!dt.init) { + return FALSE; + } + + // 繧サ繧ッ繧ソ縺梧怏蜉ケ謨ー繧定カ縺医※縺繧後ー繧ィ繝ゥ繝シ + if (sec >= dt.sectors) { + return FALSE; + } + + // 繧ェ繝輔そ繝繝医√Ξ繝ウ繧ー繧ケ繧定ィ育ョ + offset = sec << dt.size; + length = 1 << dt.size; + + // 豈碑シ + ASSERT(dt.buffer); + ASSERT((dt.size == 8) || (dt.size == 9) || (dt.size == 11)); + ASSERT((dt.sectors > 0) && (dt.sectors <= 0x100)); + if (memcmp(buf, &dt.buffer[offset], length) == 0) { + // 蜷後§繧ゅョ繧呈嶌縺崎セシ繧ゅ≧縺ィ縺励※縺繧九ョ縺ァ縲∵ュ」蟶ク邨ゆコ + return TRUE; + } + + // 繧ウ繝斐シ縲∝、画峩縺ゅj + memcpy(&dt.buffer[offset], buf, length); + dt.changemap[sec] = TRUE; + dt.changed = TRUE; + + // 謌仙粥 + return TRUE; +} + +//=========================================================================== +// +// 繝繧」繧ケ繧ッ繧ュ繝」繝繧キ繝・ +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +DiskCache::DiskCache( + const Filepath& path, int size, int blocks, off64_t imgoff) +{ + int i; + + ASSERT((size == 8) || (size == 9) || (size == 11)); + ASSERT(blocks > 0); + ASSERT(imgoff >= 0); + + // 繧ュ繝」繝繧キ繝・繝ッ繝シ繧ッ + for (i = 0; i < CacheMax; i++) { + cache[i].disktrk = NULL; + cache[i].serial = 0; + } + + // 縺昴ョ莉 + serial = 0; + sec_path = path; + sec_size = size; + sec_blocks = blocks; + cd_raw = FALSE; + imgoffset = imgoff; +} + +//--------------------------------------------------------------------------- +// +// 繝繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +DiskCache::~DiskCache() +{ + // 繝医Λ繝繧ッ繧偵け繝ェ繧「 + Clear(); +} + +//--------------------------------------------------------------------------- +// +// RAW繝「繝シ繝芽ィュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL DiskCache::SetRawMode(BOOL raw) +{ + ASSERT(this); + ASSERT(sec_size == 11); + + // 險ュ螳 + cd_raw = raw; +} + +//--------------------------------------------------------------------------- +// +// 繧サ繝シ繝 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL DiskCache::Save() +{ + int i; + + ASSERT(this); + + // 繝医Λ繝繧ッ繧剃ソ晏ュ + for (i = 0; i < CacheMax; i++) { + // 譛牙柑縺ェ繝医Λ繝繧ッ縺 + if (cache[i].disktrk) { + // 菫晏ュ + if (!cache[i].disktrk->Save(sec_path)) { + return FALSE; + } + } + } + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繝繧」繧ケ繧ッ繧ュ繝」繝繧キ繝・諠蝣ア蜿門セ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL DiskCache::GetCache(int index, int& track, DWORD& aserial) const +{ + ASSERT(this); + ASSERT((index >= 0) && (index < CacheMax)); + + // 譛ェ菴ソ逕ィ縺ェ繧宇ALSE + if (!cache[index].disktrk) { + return FALSE; + } + + // 繝医Λ繝繧ッ縺ィ繧キ繝ェ繧「繝ォ繧定ィュ螳 + track = cache[index].disktrk->GetTrack(); + aserial = cache[index].serial; + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繧ッ繝ェ繧「 +// +//--------------------------------------------------------------------------- +void FASTCALL DiskCache::Clear() +{ + int i; + + ASSERT(this); + + // 繧ュ繝」繝繧キ繝・繝ッ繝シ繧ッ繧定ァ」謾セ + for (i = 0; i < CacheMax; i++) { + if (cache[i].disktrk) { + delete cache[i].disktrk; + cache[i].disktrk = NULL; + } + } +} + +//--------------------------------------------------------------------------- +// +// 繧サ繧ッ繧ソ繝ェ繝シ繝 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL DiskCache::Read(BYTE *buf, int block) +{ + int track; + DiskTrack *disktrk; + + ASSERT(this); + ASSERT(sec_size != 0); + + // 蜈医↓譖エ譁ー + Update(); + + // 繝医Λ繝繧ッ繧堤ョ怜コ(256繧サ繧ッ繧ソ/繝医Λ繝繧ッ縺ォ蝗コ螳) + track = block >> 8; + + // 縺昴ョ繝医Λ繝繧ッ繝繝シ繧ソ繧貞セ励k + disktrk = Assign(track); + if (!disktrk) { + return FALSE; + } + + // 繝医Λ繝繧ッ縺ォ莉サ縺帙k + return disktrk->Read(buf, (BYTE)block); +} + +//--------------------------------------------------------------------------- +// +// 繧サ繧ッ繧ソ繝ゥ繧、繝 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL DiskCache::Write(const BYTE *buf, int block) +{ + int track; + DiskTrack *disktrk; + + ASSERT(this); + ASSERT(sec_size != 0); + + // 蜈医↓譖エ譁ー + Update(); + + // 繝医Λ繝繧ッ繧堤ョ怜コ(256繧サ繧ッ繧ソ/繝医Λ繝繧ッ縺ォ蝗コ螳) + track = block >> 8; + + // 縺昴ョ繝医Λ繝繧ッ繝繝シ繧ソ繧貞セ励k + disktrk = Assign(track); + if (!disktrk) { + return FALSE; + } + + // 繝医Λ繝繧ッ縺ォ莉サ縺帙k + return disktrk->Write(buf, (BYTE)block); +} + +//--------------------------------------------------------------------------- +// +// 繝医Λ繝繧ッ縺ョ蜑イ繧雁ス薙※ +// +//--------------------------------------------------------------------------- +DiskTrack* FASTCALL DiskCache::Assign(int track) +{ + int i; + int c; + DWORD s; + DiskTrack *disktrk; + + ASSERT(this); + ASSERT(sec_size != 0); + ASSERT(track >= 0); + + // 縺セ縺壹∵里縺ォ蜑イ繧雁ス薙※縺輔l縺ヲ縺縺ェ縺縺玖ェソ縺ケ繧 + for (i = 0; i < CacheMax; i++) { + if (cache[i].disktrk) { + if (cache[i].disktrk->GetTrack() == track) { + // 繝医Λ繝繧ッ縺御ク閾エ + cache[i].serial = serial; + return cache[i].disktrk; + } + } + } + + // 谺。縺ォ縲∫ゥコ縺縺ヲ縺繧九b縺ョ縺後↑縺縺玖ェソ縺ケ繧 + for (i = 0; i < CacheMax; i++) { + if (!cache[i].disktrk) { + // 繝ュ繝シ繝峨r隧ヲ縺ソ繧 + if (Load(i, track)) { + // 繝ュ繝シ繝画仙粥 + cache[i].serial = serial; + return cache[i].disktrk; + } + + // 繝ュ繝シ繝牙、ア謨 + return NULL; + } + } + + // 譛蠕後↓縲√す繝ェ繧「繝ォ逡ェ蜿キ縺ョ荳逡ェ闍・縺繧ゅョ繧呈爾縺励∝炎髯、縺吶k + + // 繧、繝ウ繝繝繧ッ繧ケ0繧貞呵」彡縺ィ縺吶k + s = cache[0].serial; + c = 0; + + // 蛟呵」懊→繧キ繝ェ繧「繝ォ繧呈ッ碑シ縺励√h繧雁ー上&縺繧ゅョ縺ク譖エ譁ー縺吶k + for (i = 0; i < CacheMax; i++) { + ASSERT(cache[i].disktrk); + + // 譌「縺ォ蟄伜惠縺吶k繧キ繝ェ繧「繝ォ縺ィ豈碑シ縲∵峩譁ー + if (cache[i].serial < s) { + s = cache[i].serial; + c = i; + } + } + + // 縺薙ョ繝医Λ繝繧ッ繧剃ソ晏ュ + if (!cache[c].disktrk->Save(sec_path)) { + return NULL; + } + + // 縺薙ョ繝医Λ繝繧ッ繧貞炎髯、 + disktrk = cache[c].disktrk; + cache[c].disktrk = NULL; + + // 繝ュ繝シ繝 + if (Load(c, track, disktrk)) { + // 繝ュ繝シ繝画仙粥 + cache[c].serial = serial; + return cache[c].disktrk; + } + + // 繝ュ繝シ繝牙、ア謨 + return NULL; +} + +//--------------------------------------------------------------------------- +// +// 繝医Λ繝繧ッ縺ョ繝ュ繝シ繝 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL DiskCache::Load(int index, int track, DiskTrack *disktrk) +{ + int sectors; + + ASSERT(this); + ASSERT((index >= 0) && (index < CacheMax)); + ASSERT(track >= 0); + ASSERT(!cache[index].disktrk); + + // 縺薙ョ繝医Λ繝繧ッ縺ョ繧サ繧ッ繧ソ謨ー繧貞叙蠕 + sectors = sec_blocks - (track << 8); + ASSERT(sectors > 0); + if (sectors > 0x100) { + sectors = 0x100; + } + + // 繝繧」繧ケ繧ッ繝医Λ繝繧ッ繧剃ス懈 + if (disktrk == NULL) { + disktrk = new DiskTrack(); + } + + // 繝繧」繧ケ繧ッ繝医Λ繝繧ッ繧貞晄悄蛹 + disktrk->Init(track, sec_size, sectors, cd_raw, imgoffset); + + // 繝ュ繝シ繝峨r隧ヲ縺ソ繧 + if (!disktrk->Load(sec_path)) { + // 螟ア謨 + delete disktrk; + return FALSE; + } + + // 蜑イ繧雁ス薙※謌仙粥縲√Ρ繝シ繧ッ繧定ィュ螳 + cache[index].disktrk = disktrk; + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繧キ繝ェ繧「繝ォ逡ェ蜿キ縺ョ譖エ譁ー +// +//--------------------------------------------------------------------------- +void FASTCALL DiskCache::Update() +{ + int i; + + ASSERT(this); + + // 譖エ譁ー縺励※縲0莉・螟悶ッ菴輔b縺励↑縺 + serial++; + if (serial != 0) { + return; + } + + // 蜈ィ繧ュ繝」繝繧キ繝・縺ョ繧キ繝ェ繧「繝ォ繧偵け繝ェ繧「(32bit繝ォ繝シ繝励@縺ヲ縺繧) + for (i = 0; i < CacheMax; i++) { + cache[i].serial = 0; + } +} + + +//=========================================================================== +// +// 繝繧」繧ケ繧ッ +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +Disk::Disk() +{ + // 繝ッ繝シ繧ッ蛻晄悄蛹 + disk.id = MAKEID('N', 'U', 'L', 'L'); + disk.ready = FALSE; + disk.writep = FALSE; + disk.readonly = FALSE; + disk.removable = FALSE; + disk.lock = FALSE; + disk.attn = FALSE; + disk.reset = FALSE; + disk.size = 0; + disk.blocks = 0; + disk.lun = 0; + disk.code = 0; + disk.dcache = NULL; + disk.imgoffset = 0; + + // 縺昴ョ莉 + cache_wb = TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繝繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +Disk::~Disk() +{ + // 繝繧」繧ケ繧ッ繧ュ繝」繝繧キ繝・縺ョ菫晏ュ + if (disk.ready) { + // 繝ャ繝繧」縺ョ蝣エ蜷医ョ縺ソ + if (disk.dcache) { + disk.dcache->Save(); + } + } + + // 繝繧」繧ケ繧ッ繧ュ繝」繝繧キ繝・縺ョ蜑企勁 + if (disk.dcache) { + delete disk.dcache; + disk.dcache = NULL; + } +} + +//--------------------------------------------------------------------------- +// +// 繝ェ繧サ繝繝 +// +//--------------------------------------------------------------------------- +void FASTCALL Disk::Reset() +{ + ASSERT(this); + + // 繝ュ繝繧ッ縺ェ縺励√い繝繝ウ繧キ繝ァ繝ウ縺ェ縺励√Μ繧サ繝繝医≠繧 + disk.lock = FALSE; + disk.attn = FALSE; + disk.reset = TRUE; +} + +#ifndef RASCSI +//--------------------------------------------------------------------------- +// +// 繧サ繝シ繝 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::Save(Fileio *fio, int ver) +{ + DWORD sz; + DWORD padding; + + ASSERT(this); + ASSERT(fio); + + // 繧オ繧、繧コ繧偵そ繝シ繝 + sz = 52; + if (!fio->Write(&sz, sizeof(sz))) { + return FALSE; + } + + // 螳滉ス薙r繧サ繝シ繝 + PROP_EXPORT(fio, disk.id); + PROP_EXPORT(fio, disk.ready); + PROP_EXPORT(fio, disk.writep); + PROP_EXPORT(fio, disk.readonly); + PROP_EXPORT(fio, disk.removable); + PROP_EXPORT(fio, disk.lock); + PROP_EXPORT(fio, disk.attn); + PROP_EXPORT(fio, disk.reset); + PROP_EXPORT(fio, disk.size); + PROP_EXPORT(fio, disk.blocks); + PROP_EXPORT(fio, disk.lun); + PROP_EXPORT(fio, disk.code); + PROP_EXPORT(fio, padding); + + // 繝代せ繧偵そ繝シ繝 + if (!diskpath.Save(fio, ver)) { + return FALSE; + } + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繝ュ繝シ繝 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::Load(Fileio *fio, int ver) +{ + DWORD sz; + disk_t buf; + DWORD padding; + Filepath path; + + ASSERT(this); + ASSERT(fio); + + // version2.03繧医j蜑阪ッ縲√ョ繧」繧ケ繧ッ縺ッ繧サ繝シ繝悶@縺ヲ縺縺ェ縺 + if (ver <= 0x0202) { + return TRUE; + } + + // 迴セ蝨ィ縺ョ繝繧」繧ケ繧ッ繧ュ繝」繝繧キ繝・繧貞炎髯、 + if (disk.dcache) { + disk.dcache->Save(); + delete disk.dcache; + disk.dcache = NULL; + } + + // 繧オ繧、繧コ繧偵Ο繝シ繝峨∫ァ蜷 + if (!fio->Read(&sz, sizeof(sz))) { + return FALSE; + } + if (sz != 52) { + return FALSE; + } + + // 繝舌ャ繝輔ぃ縺ク繝ュ繝シ繝 + PROP_IMPORT(fio, buf.id); + PROP_IMPORT(fio, buf.ready); + PROP_IMPORT(fio, buf.writep); + PROP_IMPORT(fio, buf.readonly); + PROP_IMPORT(fio, buf.removable); + PROP_IMPORT(fio, buf.lock); + PROP_IMPORT(fio, buf.attn); + PROP_IMPORT(fio, buf.reset); + PROP_IMPORT(fio, buf.size); + PROP_IMPORT(fio, buf.blocks); + PROP_IMPORT(fio, buf.lun); + PROP_IMPORT(fio, buf.code); + PROP_IMPORT(fio, padding); + + // 繝代せ繧偵Ο繝シ繝 + if (!path.Load(fio, ver)) { + return FALSE; + } + + // ID縺御ク閾エ縺励◆蝣エ蜷医ョ縺ソ縲∫ァサ蜍 + if (disk.id == buf.id) { + // NULL縺ェ繧我ス輔b縺励↑縺 + if (IsNULL()) { + return TRUE; + } + + // 繧サ繝シ繝悶@縺滓凾縺ィ蜷後§遞ョ鬘槭ョ繝繝舌う繧ケ + disk.ready = FALSE; + if (Open(path)) { + // Open蜀縺ァ繝繧」繧ケ繧ッ繧ュ繝」繝繧キ繝・縺ッ菴懈舌&繧後※縺繧 + // 繝励Ο繝代ユ繧」縺ョ縺ソ遘サ蜍 + if (!disk.readonly) { + disk.writep = buf.writep; + } + disk.lock = buf.lock; + disk.attn = buf.attn; + disk.reset = buf.reset; + disk.lun = buf.lun; + disk.code = buf.code; + + // 豁」蟶ク縺ォ繝ュ繝シ繝峨〒縺阪◆ + return TRUE; + } + } + + // 繝繧」繧ケ繧ッ繧ュ繝」繝繧キ繝・蜀堺ス懈 + if (!IsReady()) { + disk.dcache = NULL; + } else { + disk.dcache = new DiskCache(diskpath, disk.size, disk.blocks); + } + + return TRUE; +} +#endif // RASCSI + +//--------------------------------------------------------------------------- +// +// NULL繝√ぉ繝繧ッ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::IsNULL() const +{ + ASSERT(this); + + if (disk.id == MAKEID('N', 'U', 'L', 'L')) { + return TRUE; + } + return FALSE; +} + +//--------------------------------------------------------------------------- +// +// SASI繝√ぉ繝繧ッ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::IsSASI() const +{ + ASSERT(this); + + if (disk.id == MAKEID('S', 'A', 'H', 'D')) { + return TRUE; + } + return FALSE; +} + +//--------------------------------------------------------------------------- +// +// 繧ェ繝シ繝励Φ +// 窶サ豢セ逕溘け繝ゥ繧ケ縺ァ縲√が繝シ繝励Φ謌仙粥蠕後ョ蠕悟ヲ逅縺ィ縺励※蜻シ縺ウ蜃コ縺吶%縺ィ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::Open(const Filepath& path, BOOL /*attn*/) +{ + Fileio fio; + + ASSERT(this); + ASSERT((disk.size == 8) || (disk.size == 9) || (disk.size == 11)); + ASSERT(disk.blocks > 0); + + // 繝ャ繝繧」 + disk.ready = TRUE; + + // 繧ュ繝」繝繧キ繝・蛻晄悄蛹 + ASSERT(!disk.dcache); + disk.dcache = new DiskCache( + path, disk.size, disk.blocks, disk.imgoffset); + + // 隱ュ縺ソ譖ク縺阪が繝シ繝励Φ蜿ッ閭ス縺 + if (fio.Open(path, Fileio::ReadWrite)) { + // 譖ク縺崎セシ縺ソ險ア蜿ッ縲√Μ繝シ繝峨が繝ウ繝ェ繝シ縺ァ縺ェ縺 + disk.writep = FALSE; + disk.readonly = FALSE; + fio.Close(); + } else { + // 譖ク縺崎セシ縺ソ遖∵ュ「縲√Μ繝シ繝峨が繝ウ繝ェ繝シ + disk.writep = TRUE; + disk.readonly = TRUE; + } + + // 繝ュ繝繧ッ縺輔l縺ヲ縺縺ェ縺 + disk.lock = FALSE; + + // 繝代せ菫晏ュ + diskpath = path; + + // 謌仙粥 + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繧、繧ク繧ァ繧ッ繝 +// +//--------------------------------------------------------------------------- +void FASTCALL Disk::Eject(BOOL force) +{ + ASSERT(this); + + // 繝ェ繝繝シ繝舌ヶ繝ォ縺ァ縺ェ縺代l縺ー繧、繧ク繧ァ繧ッ繝医〒縺阪↑縺 + if (!disk.removable) { + return; + } + + // 繝ャ繝繧」縺ァ縺ェ縺代l縺ー繧、繧ク繧ァ繧ッ繝亥ソ隕√↑縺 + if (!disk.ready) { + return; + } + + // 蠑キ蛻カ繝輔Λ繧ー縺後↑縺蝣エ蜷医√Ο繝繧ッ縺輔l縺ヲ縺縺ェ縺縺薙→縺悟ソ隕 + if (!force) { + if (disk.lock) { + return; + } + } + + // 繝繧」繧ケ繧ッ繧ュ繝」繝繧キ繝・繧貞炎髯、 + disk.dcache->Save(); + delete disk.dcache; + disk.dcache = NULL; + + // 繝弱ャ繝医Ξ繝繧」縲√い繝繝ウ繧キ繝ァ繝ウ縺ェ縺 + disk.ready = FALSE; + disk.writep = FALSE; + disk.readonly = FALSE; + disk.attn = FALSE; +} + +//--------------------------------------------------------------------------- +// +// 譖ク縺崎セシ縺ソ遖∵ュ「 +// +//--------------------------------------------------------------------------- +void FASTCALL Disk::WriteP(BOOL writep) +{ + ASSERT(this); + + // 繝ャ繝繧」縺ァ縺ゅk縺薙→ + if (!disk.ready) { + return; + } + + // Read Only縺ョ蝣エ蜷医ッ縲√励Ο繝繧ッ繝育憾諷九ョ縺ソ + if (disk.readonly) { + ASSERT(disk.writep); + return; + } + + // 繝輔Λ繧ー險ュ螳 + disk.writep = writep; +} + +//--------------------------------------------------------------------------- +// +// 蜀驛ィ繝ッ繝シ繧ッ蜿門セ +// +//--------------------------------------------------------------------------- +void FASTCALL Disk::GetDisk(disk_t *buffer) const +{ + ASSERT(this); + ASSERT(buffer); + + // 蜀驛ィ繝ッ繝シ繧ッ繧偵さ繝斐シ + *buffer = disk; +} + +//--------------------------------------------------------------------------- +// +// 繝代せ蜿門セ +// +//--------------------------------------------------------------------------- +void FASTCALL Disk::GetPath(Filepath& path) const +{ + path = diskpath; +} + +//--------------------------------------------------------------------------- +// +// 繝輔Λ繝繧キ繝・ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::Flush() +{ + ASSERT(this); + + // 繧ュ繝」繝繧キ繝・縺後↑縺代l縺ー菴輔b縺励↑縺 + if (!disk.dcache) { + return TRUE; + } + + // 繧ュ繝」繝繧キ繝・繧剃ソ晏ュ + return disk.dcache->Save(); +} + +//--------------------------------------------------------------------------- +// +// 繝ャ繝繧」繝√ぉ繝繧ッ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::CheckReady() +{ + ASSERT(this); + + // 繝ェ繧サ繝繝医↑繧峨√せ繝繝シ繧ソ繧ケ繧定ソ斐☆ + if (disk.reset) { + disk.code = DISK_DEVRESET; + disk.reset = FALSE; + return FALSE; + } + + // 繧「繝繝ウ繧キ繝ァ繝ウ縺ェ繧峨√せ繝繝シ繧ソ繧ケ繧定ソ斐☆ + if (disk.attn) { + disk.code = DISK_ATTENTION; + disk.attn = FALSE; + return FALSE; + } + + // 繝弱ャ繝医Ξ繝繧」縺ェ繧峨√せ繝繝シ繧ソ繧ケ繧定ソ斐☆ + if (!disk.ready) { + disk.code = DISK_NOTREADY; + return FALSE; + } + + // 繧ィ繝ゥ繝シ縺ェ縺励↓蛻晄悄蛹 + disk.code = DISK_NOERROR; + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// INQUIRY +// 窶サ蟶ク譎よ仙粥縺吶k蠢隕√′縺ゅk +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::Inquiry( + const DWORD* /*cdb*/, BYTE* /*buf*/, DWORD /*major*/, DWORD /*minor*/) +{ + ASSERT(this); + + // 繝繝輔か繝ォ繝医ッINQUIRY螟ア謨 + disk.code = DISK_INVALIDCMD; + return 0; +} + +//--------------------------------------------------------------------------- +// +// REQUEST SENSE +// 窶サSASI縺ッ蛻・蜃ヲ逅 +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::RequestSense(const DWORD *cdb, BYTE *buf) +{ + int size; + + ASSERT(this); + ASSERT(cdb); + ASSERT(buf); + + // 繧ィ繝ゥ繝シ縺後↑縺蝣エ蜷医↓髯舌j縲√ヮ繝繝医Ξ繝繧」繧偵メ繧ァ繝繧ッ + if (disk.code == DISK_NOERROR) { + if (!disk.ready) { + disk.code = DISK_NOTREADY; + } + } + + // 繧オ繧、繧コ豎コ螳(繧「繝ュ繧ア繝シ繧キ繝ァ繝ウ繝ャ繝ウ繧ー繧ケ縺ォ蠕薙≧) + size = (int)cdb[4]; + ASSERT((size >= 0) && (size < 0x100)); + + // SCSI-1縺ァ縺ッ縲√し繧、繧コ0縺ョ縺ィ縺阪↓4繝舌う繝郁サ「騾√☆繧(SCSI-2縺ァ縺ッ縺薙ョ莉墓ァ倥ッ蜑企勁) + if (size == 0) { + size = 4; + } + + // 繝舌ャ繝輔ぃ繧偵け繝ェ繧「 + memset(buf, 0, size); + + // 諡。蠑オ繧サ繝ウ繧ケ繝繝シ繧ソ繧貞性繧√◆縲18繝舌う繝医r險ュ螳 + buf[0] = 0x70; + buf[2] = (BYTE)(disk.code >> 16); + buf[7] = 10; + buf[12] = (BYTE)(disk.code >> 8); + buf[13] = (BYTE)disk.code; + + // 繧ウ繝シ繝峨r繧ッ繝ェ繧「 + disk.code = 0x00; + + return size; +} + +//--------------------------------------------------------------------------- +// +// MODE SELECT繝√ぉ繝繧ッ +// 窶サdisk.code縺ョ蠖ア髻ソ繧貞女縺代↑縺 +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::SelectCheck(const DWORD *cdb) +{ + int length; + + ASSERT(this); + ASSERT(cdb); + + // SCSIHD縺ァ縺ェ縺上そ繝シ繝悶ヱ繝ゥ繝。繝シ繧ソ縺瑚ィュ螳壹&繧後※縺繧後ー繧ィ繝ゥ繝シ + if (disk.id != MAKEID('S', 'C', 'H', 'D')) { + // 繧サ繝シ繝悶ヱ繝ゥ繝。繝シ繧ソ縺瑚ィュ螳壹&繧後※縺繧後ー繧ィ繝ゥ繝シ + if (cdb[1] & 0x01) { + disk.code = DISK_INVALIDCDB; + return 0; + } + } + + // 繝代Λ繝。繝シ繧ソ繝ャ繝ウ繧ー繧ケ縺ァ謖螳壹&繧後◆繝繝シ繧ソ繧貞女縺大叙繧 + length = (int)cdb[4]; + return length; +} + + +//--------------------------------------------------------------------------- +// +// MODE SELECT(10)繝√ぉ繝繧ッ +// 窶サdisk.code縺ョ蠖ア髻ソ繧貞女縺代↑縺 +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::SelectCheck10(const DWORD *cdb) +{ + DWORD length; + + ASSERT(this); + ASSERT(cdb); + + // SCSIHD縺ァ縺ェ縺上そ繝シ繝悶ヱ繝ゥ繝。繝シ繧ソ縺瑚ィュ螳壹&繧後※縺繧後ー繧ィ繝ゥ繝シ + if (disk.id != MAKEID('S', 'C', 'H', 'D')) { + if (cdb[1] & 0x01) { + disk.code = DISK_INVALIDCDB; + return 0; + } + } + + // 繝代Λ繝。繝シ繧ソ繝ャ繝ウ繧ー繧ケ縺ァ謖螳壹&繧後◆繝繝シ繧ソ繧貞女縺大叙繧 + length = cdb[7]; + length <<= 8; + length |= cdb[8]; + if (length > 0x800) { + length = 0x800; + } + + return (int)length; +} + +//--------------------------------------------------------------------------- +// +// MODE SELECT +// 窶サdisk.code縺ョ蠖ア髻ソ繧貞女縺代↑縺 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::ModeSelect(const DWORD *cdb, const BYTE *buf, int length) +{ + ASSERT(this); + ASSERT(buf); + ASSERT(length >= 0); + + // 險ュ螳壹〒縺阪↑縺 + disk.code = DISK_INVALIDPRM; + + return FALSE; +} + +//--------------------------------------------------------------------------- +// +// MODE SENSE +// 窶サdisk.code縺ョ蠖ア髻ソ繧貞女縺代↑縺 +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::ModeSense(const DWORD *cdb, BYTE *buf) +{ + int page; + int length; + int size; + BOOL valid; + BOOL change; + int ret; + + ASSERT(this); + ASSERT(cdb); + ASSERT(buf); + ASSERT(cdb[0] == 0x1a); + + // 繝ャ繝ウ繧ー繧ケ蜿門セ励√ヰ繝繝輔ぃ繧ッ繝ェ繧「 + length = (int)cdb[4]; + ASSERT((length >= 0) && (length < 0x100)); + memset(buf, 0, length); + + // 螟画峩蜿ッ閭ス繝輔Λ繧ー蜿門セ + if ((cdb[2] & 0xc0) == 0x40) { + change = TRUE; + } else { + change = FALSE; + } + + // 繝壹シ繧ク繧ウ繝シ繝牙叙蠕(0x00縺ッ譛蛻昴°繧益alid) + page = cdb[2] & 0x3f; + if (page == 0x00) { + valid = TRUE; + } else { + valid = FALSE; + } + + // 蝓コ譛ャ諠蝣ア + size = 4; + + // MEDIUM TYPE + if (disk.id == MAKEID('S', 'C', 'M', 'O')) { + buf[1] = 0x03; // optical reversible or erasable + } + + // DEVICE SPECIFIC PARAMETER + if (disk.writep) { + buf[2] = 0x80; + } + + // DBD縺0縺ェ繧峨√ヶ繝ュ繝繧ッ繝繧」繧ケ繧ッ繝ェ繝励ち繧定ソス蜉 + if ((cdb[1] & 0x08) == 0) { + // 繝「繝シ繝峨ヱ繝ゥ繝。繝シ繧ソ繝倥ャ繝 + buf[3] = 0x08; + + // 繝ャ繝繧」縺ョ蝣エ蜷医↓髯舌j + if (disk.ready) { + // 繝悶Ο繝繧ッ繝繧」繧ケ繧ッ繝ェ繝励ち(繝悶Ο繝繧ッ謨ー) + buf[5] = (BYTE)(disk.blocks >> 16); + buf[6] = (BYTE)(disk.blocks >> 8); + buf[7] = (BYTE)disk.blocks; + + // 繝悶Ο繝繧ッ繝繧」繧ケ繧ッ繝ェ繝励ち(繝悶Ο繝繧ッ繝ャ繝ウ繧ー繧ケ) + size = 1 << disk.size; + buf[9] = (BYTE)(size >> 16); + buf[10] = (BYTE)(size >> 8); + buf[11] = (BYTE)size; + } + + // 繧オ繧、繧コ蜀崎ィュ螳 + size = 12; + } + + // 繝壹シ繧ク繧ウ繝シ繝1(read-write error recovery) + if ((page == 0x01) || (page == 0x3f)) { + size += AddError(change, &buf[size]); + valid = TRUE; + } + + // 繝壹シ繧ク繧ウ繝シ繝3(format device) + if ((page == 0x03) || (page == 0x3f)) { + size += AddFormat(change, &buf[size]); + valid = TRUE; + } + + // 繝壹シ繧ク繧ウ繝シ繝4(drive parameter) + if ((page == 0x04) || (page == 0x3f)) { + size += AddDrive(change, &buf[size]); + valid = TRUE; + } + + // 繝壹シ繧ク繧ウ繝シ繝6(optical) + if (disk.id == MAKEID('S', 'C', 'M', 'O')) { + if ((page == 0x06) || (page == 0x3f)) { + size += AddOpt(change, &buf[size]); + valid = TRUE; + } + } + + // 繝壹シ繧ク繧ウ繝シ繝8(caching) + if ((page == 0x08) || (page == 0x3f)) { + size += AddCache(change, &buf[size]); + valid = TRUE; + } + + // 繝壹シ繧ク繧ウ繝シ繝13(CD-ROM) + if (disk.id == MAKEID('S', 'C', 'C', 'D')) { + if ((page == 0x0d) || (page == 0x3f)) { + size += AddCDROM(change, &buf[size]); + valid = TRUE; + } + } + + // 繝壹シ繧ク繧ウ繝シ繝14(CD-DA) + if (disk.id == MAKEID('S', 'C', 'C', 'D')) { + if ((page == 0x0e) || (page == 0x3f)) { + size += AddCDDA(change, &buf[size]); + valid = TRUE; + } + } + + // 繝壹シ繧ク(繝吶Φ繝迚ケ谿) + ret = AddVendor(page, change, &buf[size]); + if (ret > 0) { + size += ret; + valid = TRUE; + } + + // 繝「繝シ繝峨ョ繝シ繧ソ繝ャ繝ウ繧ー繧ケ繧呈怙邨りィュ螳 + buf[0] = (BYTE)(size - 1); + + // 繧オ繝昴シ繝医@縺ヲ縺縺ェ縺繝壹シ繧ク縺 + if (!valid) { + disk.code = DISK_INVALIDCDB; + return 0; + } + + // MODE SENSE謌仙粥 + disk.code = DISK_NOERROR; + return length; +} + +//--------------------------------------------------------------------------- +// +// MODE SENSE(10) +// 窶サdisk.code縺ョ蠖ア髻ソ繧貞女縺代↑縺 +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::ModeSense10(const DWORD *cdb, BYTE *buf) +{ + int page; + int length; + int size; + BOOL valid; + BOOL change; + int ret; + + ASSERT(this); + ASSERT(cdb); + ASSERT(buf); + ASSERT(cdb[0] == 0x5a); + + // 繝ャ繝ウ繧ー繧ケ蜿門セ励√ヰ繝繝輔ぃ繧ッ繝ェ繧「 + length = cdb[7]; + length <<= 8; + length |= cdb[8]; + if (length > 0x800) { + length = 0x800; + } + ASSERT((length >= 0) && (length < 0x800)); + memset(buf, 0, length); + + // 螟画峩蜿ッ閭ス繝輔Λ繧ー蜿門セ + if ((cdb[2] & 0xc0) == 0x40) { + change = TRUE; + } else { + change = FALSE; + } + + // 繝壹シ繧ク繧ウ繝シ繝牙叙蠕(0x00縺ッ譛蛻昴°繧益alid) + page = cdb[2] & 0x3f; + if (page == 0x00) { + valid = TRUE; + } else { + valid = FALSE; + } + + // 蝓コ譛ャ諠蝣ア + size = 4; + if (disk.writep) { + buf[2] = 0x80; + } + + // DBD縺0縺ェ繧峨√ヶ繝ュ繝繧ッ繝繧」繧ケ繧ッ繝ェ繝励ち繧定ソス蜉 + if ((cdb[1] & 0x08) == 0) { + // 繝「繝シ繝峨ヱ繝ゥ繝。繝シ繧ソ繝倥ャ繝 + buf[3] = 0x08; + + // 繝ャ繝繧」縺ョ蝣エ蜷医↓髯舌j + if (disk.ready) { + // 繝悶Ο繝繧ッ繝繧」繧ケ繧ッ繝ェ繝励ち(繝悶Ο繝繧ッ謨ー) + buf[5] = (BYTE)(disk.blocks >> 16); + buf[6] = (BYTE)(disk.blocks >> 8); + buf[7] = (BYTE)disk.blocks; + + // 繝悶Ο繝繧ッ繝繧」繧ケ繧ッ繝ェ繝励ち(繝悶Ο繝繧ッ繝ャ繝ウ繧ー繧ケ) + size = 1 << disk.size; + buf[9] = (BYTE)(size >> 16); + buf[10] = (BYTE)(size >> 8); + buf[11] = (BYTE)size; + } + + // 繧オ繧、繧コ蜀崎ィュ螳 + size = 12; + } + + // 繝壹シ繧ク繧ウ繝シ繝1(read-write error recovery) + if ((page == 0x01) || (page == 0x3f)) { + size += AddError(change, &buf[size]); + valid = TRUE; + } + + // 繝壹シ繧ク繧ウ繝シ繝3(format device) + if ((page == 0x03) || (page == 0x3f)) { + size += AddFormat(change, &buf[size]); + valid = TRUE; + } + + // 繝壹シ繧ク繧ウ繝シ繝4(drive parameter) + if ((page == 0x04) || (page == 0x3f)) { + size += AddDrive(change, &buf[size]); + valid = TRUE; + } + + // 繝壹シ繧ク繧ウ繝シ繝6(optical) + if (disk.id == MAKEID('S', 'C', 'M', 'O')) { + if ((page == 0x06) || (page == 0x3f)) { + size += AddOpt(change, &buf[size]); + valid = TRUE; + } + } + + // 繝壹シ繧ク繧ウ繝シ繝8(caching) + if ((page == 0x08) || (page == 0x3f)) { + size += AddCache(change, &buf[size]); + valid = TRUE; + } + + // 繝壹シ繧ク繧ウ繝シ繝13(CD-ROM) + if (disk.id == MAKEID('S', 'C', 'C', 'D')) { + if ((page == 0x0d) || (page == 0x3f)) { + size += AddCDROM(change, &buf[size]); + valid = TRUE; + } + } + + // 繝壹シ繧ク繧ウ繝シ繝14(CD-DA) + if (disk.id == MAKEID('S', 'C', 'C', 'D')) { + if ((page == 0x0e) || (page == 0x3f)) { + size += AddCDDA(change, &buf[size]); + valid = TRUE; + } + } + + // 繝壹シ繧ク(繝吶Φ繝迚ケ谿) + ret = AddVendor(page, change, &buf[size]); + if (ret > 0) { + size += ret; + valid = TRUE; + } + + // 繝「繝シ繝峨ョ繝シ繧ソ繝ャ繝ウ繧ー繧ケ繧呈怙邨りィュ螳 + buf[0] = (BYTE)(size - 1); + + // 繧オ繝昴シ繝医@縺ヲ縺縺ェ縺繝壹シ繧ク縺 + if (!valid) { + disk.code = DISK_INVALIDCDB; + return 0; + } + + // MODE SENSE謌仙粥 + disk.code = DISK_NOERROR; + return length; +} + +//--------------------------------------------------------------------------- +// +// 繧ィ繝ゥ繝シ繝壹シ繧ク霑ス蜉 +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::AddError(BOOL change, BYTE *buf) +{ + ASSERT(this); + ASSERT(buf); + + // 繧ウ繝シ繝峨サ繝ャ繝ウ繧ー繧ケ繧定ィュ螳 + buf[0] = 0x01; + buf[1] = 0x0a; + + // 螟画峩蜿ッ閭ス鬆伜沺縺ッ縺ェ縺 + if (change) { + return 12; + } + + // 繝ェ繝医Λ繧、繧ォ繧ヲ繝ウ繝医ッ0縲√Μ繝溘ャ繝医ち繧、繝縺ッ陬鄂ョ蜀驛ィ縺ョ繝繝輔か繝ォ繝亥、繧剃スソ逕ィ + return 12; +} + +//--------------------------------------------------------------------------- +// +// 繝輔か繝シ繝槭ャ繝医壹シ繧ク霑ス蜉 +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::AddFormat(BOOL change, BYTE *buf) +{ + int size; + + ASSERT(this); + ASSERT(buf); + + // 繧ウ繝シ繝峨サ繝ャ繝ウ繧ー繧ケ繧定ィュ螳 + buf[0] = 0x80 | 0x03; + buf[1] = 0x16; + + // 迚ゥ逅繧サ繧ッ繧ソ縺ョ繝舌う繝域焚縺ッ螟画峩蜿ッ閭ス縺ォ隕九○繧(螳滄圀縺ォ縺ッ螟画峩縺ァ縺阪↑縺縺) + if (change) { + buf[0xc] = 0xff; + buf[0xd] = 0xff; + return 24; + } + + if (disk.ready) { + // 1繧セ繝シ繝ウ縺ョ繝医Λ繝繧ッ謨ー繧8縺ォ險ュ螳(TODO) + buf[0x3] = 0x08; + + // 繧サ繧ッ繧ソ/繝医Λ繝繧ッ繧25縺ォ險ュ螳(TODO) + buf[0xa] = 0x00; + buf[0xb] = 0x19; + + // 迚ゥ逅繧サ繧ッ繧ソ縺ョ繝舌う繝域焚繧定ィュ螳 + size = 1 << disk.size; + buf[0xc] = (BYTE)(size >> 8); + buf[0xd] = (BYTE)size; + } + + // 繝ェ繝繝シ繝舌ヶ繝ォ螻樊ァ繧定ィュ螳 + if (disk.removable) { + buf[20] = 0x20; + } + + return 24; +} + +//--------------------------------------------------------------------------- +// +// 繝峨Λ繧、繝悶壹シ繧ク霑ス蜉 +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::AddDrive(BOOL change, BYTE *buf) +{ + DWORD cylinder; + + ASSERT(this); + ASSERT(buf); + + // 繧ウ繝シ繝峨サ繝ャ繝ウ繧ー繧ケ繧定ィュ螳 + buf[0] = 0x04; + buf[1] = 0x16; + + // 螟画峩蜿ッ閭ス鬆伜沺縺ッ縺ェ縺 + if (change) { + return 24; + } + + if (disk.ready) { + // 繧キ繝ェ繝ウ繝謨ー繧定ィュ螳(邱上ヶ繝ュ繝繧ッ謨ー繧25繧サ繧ッ繧ソ/繝医Λ繝繧ッ縺ィ8繝倥ャ繝峨〒髯、邂) + cylinder = disk.blocks; + cylinder >>= 3; + cylinder /= 25; + buf[0x2] = (BYTE)(cylinder >> 16); + buf[0x3] = (BYTE)(cylinder >> 8); + buf[0x4] = (BYTE)cylinder; + + // 繝倥ャ繝峨r8縺ァ蝗コ螳 + buf[0x5] = 0x8; + } + + return 24; +} + +//--------------------------------------------------------------------------- +// +// 繧ェ繝励ユ繧」繧ォ繝ォ繝壹シ繧ク霑ス蜉 +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::AddOpt(BOOL change, BYTE *buf) +{ + ASSERT(this); + ASSERT(buf); + + // 繧ウ繝シ繝峨サ繝ャ繝ウ繧ー繧ケ繧定ィュ螳 + buf[0] = 0x06; + buf[1] = 0x02; + + // 螟画峩蜿ッ閭ス鬆伜沺縺ッ縺ェ縺 + if (change) { + return 4; + } + + // 譖エ譁ー繝悶Ο繝繧ッ縺ョ繝ャ繝昴シ繝医ッ陦後o縺ェ縺 + return 4; +} + +//--------------------------------------------------------------------------- +// +// 繧ュ繝」繝繧キ繝・繝壹シ繧ク霑ス蜉 +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::AddCache(BOOL change, BYTE *buf) +{ + ASSERT(this); + ASSERT(buf); + + // 繧ウ繝シ繝峨サ繝ャ繝ウ繧ー繧ケ繧定ィュ螳 + buf[0] = 0x08; + buf[1] = 0x0a; + + // 螟画峩蜿ッ閭ス鬆伜沺縺ッ縺ェ縺 + if (change) { + return 12; + } + + // 隱ュ縺ソ霎シ縺ソ繧ュ繝」繝繧キ繝・縺ョ縺ソ譛牙柑縲√励Μ繝輔ぉ繝繝√ッ陦後o縺ェ縺 + return 12; +} + +//--------------------------------------------------------------------------- +// +// CD-ROM繝壹シ繧ク霑ス蜉 +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::AddCDROM(BOOL change, BYTE *buf) +{ + ASSERT(this); + ASSERT(buf); + + // 繧ウ繝シ繝峨サ繝ャ繝ウ繧ー繧ケ繧定ィュ螳 + buf[0] = 0x0d; + buf[1] = 0x06; + + // 螟画峩蜿ッ閭ス鬆伜沺縺ッ縺ェ縺 + if (change) { + return 8; + } + + // 繧、繝ウ繧「繧ッ繝繧」繝悶ち繧、繝槭ッ2sec + buf[3] = 0x05; + + // MSF蛟肴焚縺ッ縺昴l縺槭l60, 75 + buf[5] = 60; + buf[7] = 75; + + return 8; +} + +//--------------------------------------------------------------------------- +// +// CD-DA繝壹シ繧ク霑ス蜉 +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::AddCDDA(BOOL change, BYTE *buf) +{ + ASSERT(this); + ASSERT(buf); + + // 繧ウ繝シ繝峨サ繝ャ繝ウ繧ー繧ケ繧定ィュ螳 + buf[0] = 0x0e; + buf[1] = 0x0e; + + // 螟画峩蜿ッ閭ス鬆伜沺縺ッ縺ェ縺 + if (change) { + return 16; + } + + // 繧ェ繝シ繝繧」繧ェ縺ッ謫堺ス懷ョ御コ繧貞セ縺。縲 隍謨ー繝医Λ繝繧ッ縺ォ縺セ縺溘′繧輝LAY繧定ィア蜿ッ縺吶k + return 16; +} + +//--------------------------------------------------------------------------- +// +// Vendor迚ケ谿翫壹シ繧ク霑ス蜉 +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::AddVendor(int page, BOOL change, BYTE *buf) +{ + ASSERT(this); + ASSERT(buf); + + return 0; +} + +//--------------------------------------------------------------------------- +// +// READ DEFECT DATA(10) +// 窶サdisk.code縺ョ蠖ア髻ソ繧貞女縺代↑縺 +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::ReadDefectData10(const DWORD *cdb, BYTE *buf) +{ + DWORD length; + + ASSERT(this); + ASSERT(cdb); + ASSERT(buf); + ASSERT(cdb[0] == 0x37); + + // 繝ャ繝ウ繧ー繧ケ蜿門セ励√ヰ繝繝輔ぃ繧ッ繝ェ繧「 + length = cdb[7]; + length <<= 8; + length |= cdb[8]; + if (length > 0x800) { + length = 0x800; + } + ASSERT((length >= 0) && (length < 0x800)); + memset(buf, 0, length); + + // P/G/FORMAT + buf[1] = (cdb[1] & 0x18) | 5; + buf[3] = 8; + + buf[4] = 0xff; + buf[5] = 0xff; + buf[6] = 0xff; + buf[7] = 0xff; + + buf[8] = 0xff; + buf[9] = 0xff; + buf[10] = 0xff; + buf[11] = 0xff; + + // 繝ェ繧ケ繝育┌縺 + disk.code = DISK_NODEFECT; + return 4; +} + +//--------------------------------------------------------------------------- +// +// 繧ウ繝槭Φ繝 +// +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// +// TEST UNIT READY +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::TestUnitReady(const DWORD* /*cdb*/) +{ + ASSERT(this); + + // 迥カ諷九メ繧ァ繝繧ッ + if (!CheckReady()) { + return FALSE; + } + + // TEST UNIT READY謌仙粥 + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// REZERO UNIT +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::Rezero(const DWORD* /*cdb*/) +{ + ASSERT(this); + + // 迥カ諷九メ繧ァ繝繧ッ + if (!CheckReady()) { + return FALSE; + } + + // REZERO謌仙粥 + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// FORMAT UNIT +// 窶サSASI縺ッ繧ェ繝壹さ繝シ繝$06縲ヾCSI縺ッ繧ェ繝壹さ繝シ繝$04 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::Format(const DWORD *cdb) +{ + ASSERT(this); + + // 迥カ諷九メ繧ァ繝繧ッ + if (!CheckReady()) { + return FALSE; + } + + // FMTDATA=1縺ッ繧オ繝昴シ繝医@縺ェ縺(菴縺優EFECT LIST縺檎┌縺縺ェ繧碓K) + if ((cdb[1] & 0x10) != 0 && cdb[4] != 0) { + disk.code = DISK_INVALIDCDB; + return FALSE; + } + + // FORMAT謌仙粥 + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// REASSIGN BLOCKS +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::Reassign(const DWORD* /*cdb*/) +{ + ASSERT(this); + + // 迥カ諷九メ繧ァ繝繧ッ + if (!CheckReady()) { + return FALSE; + } + + // REASSIGN BLOCKS謌仙粥 + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// READ +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::Read(BYTE *buf, DWORD block) +{ + ASSERT(this); + ASSERT(buf); + + // 迥カ諷九メ繧ァ繝繧ッ + if (!CheckReady()) { + return 0; + } + + // 繝医シ繧ソ繝ォ繝悶Ο繝繧ッ謨ー繧定カ縺医※縺繧後ー繧ィ繝ゥ繝シ + if (block >= disk.blocks) { + disk.code = DISK_INVALIDLBA; + return 0; + } + + // 繧ュ繝」繝繧キ繝・縺ォ莉サ縺帙k + if (!disk.dcache->Read(buf, block)) { + disk.code = DISK_READFAULT; + return 0; + } + + // 謌仙粥 + return (1 << disk.size); +} + +//--------------------------------------------------------------------------- +// +// WRITE繝√ぉ繝繧ッ +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::WriteCheck(DWORD block) +{ + ASSERT(this); + + // 迥カ諷九メ繧ァ繝繧ッ + if (!CheckReady()) { + return 0; + } + + // 繝医シ繧ソ繝ォ繝悶Ο繝繧ッ謨ー繧定カ縺医※縺繧後ー繧ィ繝ゥ繝シ + if (block >= disk.blocks) { + return 0; + } + + // 譖ク縺崎セシ縺ソ遖∵ュ「縺ェ繧峨お繝ゥ繝シ + if (disk.writep) { + disk.code = DISK_WRITEPROTECT; + return 0; + } + + // 謌仙粥 + return (1 << disk.size); +} + +//--------------------------------------------------------------------------- +// +// WRITE +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::Write(const BYTE *buf, DWORD block) +{ + ASSERT(this); + ASSERT(buf); + + // 繝ャ繝繧」縺ァ縺ェ縺代l縺ー繧ィ繝ゥ繝シ + if (!disk.ready) { + disk.code = DISK_NOTREADY; + return FALSE; + } + + // 繝医シ繧ソ繝ォ繝悶Ο繝繧ッ謨ー繧定カ縺医※縺繧後ー繧ィ繝ゥ繝シ + if (block >= disk.blocks) { + disk.code = DISK_INVALIDLBA; + return FALSE; + } + + // 譖ク縺崎セシ縺ソ遖∵ュ「縺ェ繧峨お繝ゥ繝シ + if (disk.writep) { + disk.code = DISK_WRITEPROTECT; + return FALSE; + } + + // 繧ュ繝」繝繧キ繝・縺ォ莉サ縺帙k + if (!disk.dcache->Write(buf, block)) { + disk.code = DISK_WRITEFAULT; + return FALSE; + } + + // 繝ゥ繧、繝医せ繝ォ繝シ繧ュ繝」繝繧キ繝・ + if (!cache_wb) { + Flush(); + } + + // 謌仙粥 + disk.code = DISK_NOERROR; + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// SEEK +// 窶サLBA縺ョ繝√ぉ繝繧ッ縺ッ陦後o縺ェ縺(SASI IOCS) +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::Seek(const DWORD* /*cdb*/) +{ + ASSERT(this); + + // 迥カ諷九メ繧ァ繝繧ッ + if (!CheckReady()) { + return FALSE; + } + + // SEEK謌仙粥 + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// ASSIGN +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::Assign(const DWORD* /*cdb*/) +{ + ASSERT(this); + + // 迥カ諷九メ繧ァ繝繧ッ + if (!CheckReady()) { + return FALSE; + } + + // 謌仙粥 + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// SPECIFY +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::Specify(const DWORD* /*cdb*/) +{ + ASSERT(this); + + // 迥カ諷九メ繧ァ繝繧ッ + if (!CheckReady()) { + return FALSE; + } + + // 謌仙粥 + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// START STOP UNIT +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::StartStop(const DWORD *cdb) +{ + ASSERT(this); + ASSERT(cdb); + ASSERT(cdb[0] == 0x1b); + + // 繧、繧ク繧ァ繧ッ繝医ン繝繝医r隕九※縲∝ソ隕√↑繧峨う繧ク繧ァ繧ッ繝 + if (cdb[4] & 0x02) { + if (disk.lock) { + // 繝ュ繝繧ッ縺輔l縺ヲ縺繧九ョ縺ァ縲√う繧ク繧ァ繧ッ繝医〒縺阪↑縺 + disk.code = DISK_PREVENT; + return FALSE; + } + + // 繧、繧ク繧ァ繧ッ繝 + Eject(FALSE); + } + + // OK + disk.code = DISK_NOERROR; + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// SEND DIAGNOSTIC +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::SendDiag(const DWORD *cdb) +{ + ASSERT(this); + ASSERT(cdb); + ASSERT(cdb[0] == 0x1d); + + // PF繝薙ャ繝医ッ繧オ繝昴シ繝医@縺ェ縺 + if (cdb[1] & 0x10) { + disk.code = DISK_INVALIDCDB; + return FALSE; + } + + // 繝代Λ繝。繝シ繧ソ繝ェ繧ケ繝医ッ繧オ繝昴シ繝医@縺ェ縺 + if ((cdb[3] != 0) || (cdb[4] != 0)) { + disk.code = DISK_INVALIDCDB; + return FALSE; + } + + // 蟶ク縺ォ謌仙粥 + disk.code = DISK_NOERROR; + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// PREVENT/ALLOW MEDIUM REMOVAL +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::Removal(const DWORD *cdb) +{ + ASSERT(this); + ASSERT(cdb); + ASSERT(cdb[0] == 0x1e); + + // 迥カ諷九メ繧ァ繝繧ッ + if (!CheckReady()) { + return FALSE; + } + + // 繝ュ繝繧ッ繝輔Λ繧ー繧定ィュ螳 + if (cdb[4] & 0x01) { + disk.lock = TRUE; + } else { + disk.lock = FALSE; + } + + // REMOVAL謌仙粥 + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// READ CAPACITY +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::ReadCapacity(const DWORD* /*cdb*/, BYTE *buf) +{ + DWORD blocks; + DWORD length; + + ASSERT(this); + ASSERT(buf); + + // 繝舌ャ繝輔ぃ繧ッ繝ェ繧「 + memset(buf, 0, 8); + + // 迥カ諷九メ繧ァ繝繧ッ + if (!CheckReady()) { + return 0; + } + + // 隲也炊繝悶Ο繝繧ッ繧「繝峨Ξ繧ケ縺ョ邨らォッ(disk.blocks - 1)繧剃ス懈 + ASSERT(disk.blocks > 0); + blocks = disk.blocks - 1; + buf[0] = (BYTE)(blocks >> 24); + buf[1] = (BYTE)(blocks >> 16); + buf[2] = (BYTE)(blocks >> 8); + buf[3] = (BYTE)blocks; + + // 繝悶Ο繝繧ッ繝ャ繝ウ繧ー繧ケ(1 << disk.size)繧剃ス懈 + length = 1 << disk.size; + buf[4] = (BYTE)(length >> 24); + buf[5] = (BYTE)(length >> 16); + buf[6] = (BYTE)(length >> 8); + buf[7] = (BYTE)length; + + // 霑秘√し繧、繧コ繧定ソ斐☆ + return 8; +} + +//--------------------------------------------------------------------------- +// +// VERIFY +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::Verify(const DWORD *cdb) +{ + DWORD record; + DWORD blocks; + + ASSERT(this); + ASSERT(cdb); + ASSERT(cdb[0] == 0x2f); + + // 繝代Λ繝。繝シ繧ソ蜿門セ + record = cdb[2]; + record <<= 8; + record |= cdb[3]; + record <<= 8; + record |= cdb[4]; + record <<= 8; + record |= cdb[5]; + blocks = cdb[7]; + blocks <<= 8; + blocks |= cdb[8]; + + // 迥カ諷九メ繧ァ繝繧ッ + if (!CheckReady()) { + return 0; + } + + // 繝代Λ繝。繝シ繧ソ繝√ぉ繝繧ッ + if (disk.blocks < (record + blocks)) { + disk.code = DISK_INVALIDLBA; + return FALSE; + } + + // 謌仙粥 + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// READ TOC +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::ReadToc(const DWORD *cdb, BYTE *buf) +{ + ASSERT(this); + ASSERT(cdb); + ASSERT(cdb[0] == 0x43); + ASSERT(buf); + + // 縺薙ョ繧ウ繝槭Φ繝峨ッ繧オ繝昴シ繝医@縺ェ縺 + disk.code = DISK_INVALIDCMD; + return FALSE; +} + +//--------------------------------------------------------------------------- +// +// PLAY AUDIO +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::PlayAudio(const DWORD *cdb) +{ + ASSERT(this); + ASSERT(cdb); + ASSERT(cdb[0] == 0x45); + + // 縺薙ョ繧ウ繝槭Φ繝峨ッ繧オ繝昴シ繝医@縺ェ縺 + disk.code = DISK_INVALIDCMD; + return FALSE; +} + +//--------------------------------------------------------------------------- +// +// PLAY AUDIO MSF +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::PlayAudioMSF(const DWORD *cdb) +{ + ASSERT(this); + ASSERT(cdb); + ASSERT(cdb[0] == 0x47); + + // 縺薙ョ繧ウ繝槭Φ繝峨ッ繧オ繝昴シ繝医@縺ェ縺 + disk.code = DISK_INVALIDCMD; + return FALSE; +} + +//--------------------------------------------------------------------------- +// +// PLAY AUDIO TRACK +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::PlayAudioTrack(const DWORD *cdb) +{ + ASSERT(this); + ASSERT(cdb); + ASSERT(cdb[0] == 0x48); + + // 縺薙ョ繧ウ繝槭Φ繝峨ッ繧オ繝昴シ繝医@縺ェ縺 + disk.code = DISK_INVALIDCMD; + return FALSE; +} + +//=========================================================================== +// +// SASI 繝上シ繝峨ョ繧」繧ケ繧ッ +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +SASIHD::SASIHD() : Disk() +{ + // SASI 繝上シ繝峨ョ繧」繧ケ繧ッ + disk.id = MAKEID('S', 'A', 'H', 'D'); +} + +//--------------------------------------------------------------------------- +// +// 繝ェ繧サ繝繝 +// +//--------------------------------------------------------------------------- +void FASTCALL SASIHD::Reset() +{ + // 繝ュ繝繧ッ迥カ諷玖ァ」髯、縲√い繝繝ウ繧キ繝ァ繝ウ隗」髯、 + disk.lock = FALSE; + disk.attn = FALSE; + + // 繝ェ繧サ繝繝医↑縺励√さ繝シ繝峨r繧ッ繝ェ繧「 + disk.reset = FALSE; + disk.code = 0x00; +} + +//--------------------------------------------------------------------------- +// +// 繧ェ繝シ繝励Φ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SASIHD::Open(const Filepath& path, BOOL /*attn*/) +{ + Fileio fio; + off64_t size; + + ASSERT(this); + ASSERT(!disk.ready); + + // 隱ュ縺ソ霎シ縺ソ繧ェ繝シ繝励Φ縺悟ソ隕 + if (!fio.Open(path, Fileio::ReadOnly)) { + return FALSE; + } + + // 繝輔ぃ繧、繝ォ繧オ繧、繧コ縺ョ蜿門セ + size = fio.GetFileSize(); + fio.Close(); + + // 10MB, 20MB, 40MB縺ョ縺ソ + switch (size) { + // 10MB + case 0x9f5400: + break; + + // 20MB + case 0x13c9800: + break; + + // 40MB + case 0x2793000: + break; + + // 縺昴ョ莉(繧オ繝昴シ繝医@縺ェ縺) + default: + return FALSE; + } + + // 繧サ繧ッ繧ソ繧オ繧、繧コ縺ィ繝悶Ο繝繧ッ謨ー + disk.size = 8; + disk.blocks = (DWORD)(size >> 8); + + // 蝓コ譛ャ繧ッ繝ゥ繧ケ + return Disk::Open(path); +} + +//--------------------------------------------------------------------------- +// +// REQUEST SENSE +// +//--------------------------------------------------------------------------- +int FASTCALL SASIHD::RequestSense(const DWORD *cdb, BYTE *buf) +{ + int size; + + ASSERT(this); + ASSERT(cdb); + ASSERT(buf); + + // 繧オ繧、繧コ豎コ螳 + size = (int)cdb[4]; + ASSERT((size >= 0) && (size < 0x100)); + + // SASI縺ッ髱樊僑蠑オ繝輔か繝シ繝槭ャ繝医↓蝗コ螳 + memset(buf, 0, size); + buf[0] = (BYTE)(disk.code >> 16); + buf[1] = (BYTE)(disk.lun << 5); + + // 繧ウ繝シ繝峨r繧ッ繝ェ繧「 + disk.code = 0x00; + + return size; +} + +//=========================================================================== +// +// SCSI 繝上シ繝峨ョ繧」繧ケ繧ッ +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +SCSIHD::SCSIHD() : Disk() +{ + // SCSI 繝上シ繝峨ョ繧」繧ケ繧ッ + disk.id = MAKEID('S', 'C', 'H', 'D'); +} + +//--------------------------------------------------------------------------- +// +// 繝ェ繧サ繝繝 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIHD::Reset() +{ + // 繝ュ繝繧ッ迥カ諷玖ァ」髯、縲√い繝繝ウ繧キ繝ァ繝ウ隗」髯、 + disk.lock = FALSE; + disk.attn = FALSE; + + // 繝ェ繧サ繝繝医↑縺励√さ繝シ繝峨r繧ッ繝ェ繧「 + disk.reset = FALSE; + disk.code = 0x00; +} + +//--------------------------------------------------------------------------- +// +// 繧ェ繝シ繝励Φ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSIHD::Open(const Filepath& path, BOOL /*attn*/) +{ + Fileio fio; + off64_t size; + + ASSERT(this); + ASSERT(!disk.ready); + + // 隱ュ縺ソ霎シ縺ソ繧ェ繝シ繝励Φ縺悟ソ隕 + if (!fio.Open(path, Fileio::ReadOnly)) { + return FALSE; + } + + // 繝輔ぃ繧、繝ォ繧オ繧、繧コ縺ョ蜿門セ + size = fio.GetFileSize(); + fio.Close(); + + // 512繝舌う繝亥腰菴阪〒縺ゅk縺薙→ + if (size & 0x1ff) { + return FALSE; + } + + // 10MB莉・荳 + if (size < 0x9f5400) { + return FALSE; + } + // xm6i縺ォ貅悶§縺ヲ2TB + // 繧医¥莨シ縺溘b縺ョ縺 wxw/wxw_cfg.cpp 縺ォ繧ゅ≠繧 + if (size > 2LL * 1024 * 1024 * 1024 * 1024) { + return FALSE; + } + + // 繧サ繧ッ繧ソ繧オ繧、繧コ縺ィ繝悶Ο繝繧ッ謨ー + disk.size = 9; + disk.blocks = (DWORD)(size >> 9); + + // 蝓コ譛ャ繧ッ繝ゥ繧ケ + return Disk::Open(path); +} + +//--------------------------------------------------------------------------- +// +// INQUIRY +// +//--------------------------------------------------------------------------- +int FASTCALL SCSIHD::Inquiry( + const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor) +{ + char vendor[32]; + char product[32]; + char rev[32]; + int size; + + ASSERT(this); + ASSERT(cdb); + ASSERT(buf); + ASSERT(cdb[0] == 0x12); + + // EVPD繝√ぉ繝繧ッ + if (cdb[1] & 0x01) { + disk.code = DISK_INVALIDCDB; + return 0; + } + + // 繝ャ繝繧」繝√ぉ繝繧ッ(繧、繝。繝シ繧ク繝輔ぃ繧、繝ォ縺後↑縺蝣エ蜷医√お繝ゥ繝シ縺ィ縺吶k) + if (!disk.ready) { + disk.code = DISK_NOTREADY; + return 0; + } + + // 蝓コ譛ャ繝繝シ繧ソ + // buf[0] ... Direct Access Device + // buf[2] ... SCSI-2貅匁侠縺ョ繧ウ繝槭Φ繝我ス鍋ウサ + // buf[3] ... SCSI-2貅匁侠縺ョInquiry繝ャ繧ケ繝昴Φ繧ケ + // buf[4] ... Inquiry霑ス蜉繝繝シ繧ソ + memset(buf, 0, 8); + + // SCSI-2 譛ャ縺ョ p.104 4.4.3 荳榊ス薙↑繝ュ繧ク繧ォ繝ォ繝ヲ繝九ャ繝医ョ蜃ヲ逅 + if (((cdb[1] >> 5) & 0x07) != disk.lun) { + buf[0] = 0x7f; + } + + buf[2] = 0x02; + buf[3] = 0x02; + buf[4] = 122 + 3; // 螳櫞DD縺ォ霑代>蛟、 + + // 遨コ逋ス縺ァ蝓九a繧 + memset(&buf[8], 0x20, buf[4] - 3); + + // 繝吶Φ繝蜷/陬ス蜩∝錐繧呈アコ螳 + sprintf(vendor, BENDER_SIGNATURE); + size = disk.blocks >> 11; + if (size < 300) + sprintf(product, "PRODRIVE LPS%dS", size); + else if (size < 600) + sprintf(product, "MAVERICK%dS", size); + else if (size < 800) + sprintf(product, "LIGHTNING%dS", size); + else if (size < 1000) + sprintf(product, "TRAILBRAZER%dS", size); + else if (size < 2000) + sprintf(product, "FIREBALL%dS", size); + else + sprintf(product, "FBSE%d.%dS", size / 1000, (size % 1000) / 100); + + // 繝吶Φ繝蜷 + memcpy(&buf[8], vendor, strlen(vendor)); + + // 陬ス蜩∝錐 + memcpy(&buf[16], product, strlen(product)); + + // 繝ェ繝薙ず繝ァ繝ウ + sprintf(rev, "0%01d%01d%01d", + (int)major, (int)(minor >> 4), (int)(minor & 0x0f)); + memcpy(&buf[32], rev, 4); + + // 霑泌唆縺ァ縺阪k繝繝シ繧ソ縺ョ繧オ繧、繧コ + size = (buf[4] + 5); + + // 逶ク謇九ョ繝舌ャ繝輔ぃ縺悟ー代↑縺代l縺ー蛻カ髯舌☆繧 + if (size > (int)cdb[4]) { + size = (int)cdb[4]; + } + + // 謌仙粥 + disk.code = DISK_NOERROR; + return size; +} + +//--------------------------------------------------------------------------- +// +// MODE SELECT +// 窶サdisk.code縺ョ蠖ア髻ソ繧貞女縺代↑縺 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSIHD::ModeSelect(const DWORD *cdb, const BYTE *buf, int length) +{ + int page; + int size; + + ASSERT(this); + ASSERT(buf); + ASSERT(length >= 0); + + // PF + if (cdb[1] & 0x10) { + // Mode Parameter header + if (length >= 12) { + // 繝悶Ο繝繧ッ繝ャ繝ウ繧ー繧ケ縺ョ繝舌う繝域焚繧偵メ繧ァ繝繧ッ + size = 1 << disk.size; + if (buf[9] != (BYTE)(size >> 16) || + buf[10] != (BYTE)(size >> 8) || buf[11] != (BYTE)size) { + // 莉翫ョ縺ィ縺薙m繧サ繧ッ繧ソ髟キ縺ョ螟画峩縺ッ險ア縺輔↑縺 + disk.code = DISK_INVALIDPRM; + return FALSE; + } + buf += 12; + length -= 12; + } + + // 繝壹シ繧ク縺ョ隗」譫 + while (length > 0) { + // 繝壹シ繧ク縺ョ蜿門セ + page = buf[0]; + + switch (page) { + // format device + case 0x03: + // 迚ゥ逅繧サ繧ッ繧ソ縺ョ繝舌う繝域焚繧偵メ繧ァ繝繧ッ + size = 1 << disk.size; + if (buf[0xc] != (BYTE)(size >> 8) || buf[0xd] != (BYTE)size) { + // 莉翫ョ縺ィ縺薙m繧サ繧ッ繧ソ髟キ縺ョ螟画峩縺ッ險ア縺輔↑縺 + disk.code = DISK_INVALIDPRM; + return FALSE; + } + break; + + // 縺昴ョ莉悶壹シ繧ク + default: + break; + } + + // 谺。縺ョ繝壹シ繧ク縺ク + size = buf[1] + 2; + length -= size; + buf += size; + } + } + + // 縺ィ繧翫≠縺医★繧ィ繝ゥ繝シ縺ッ逋コ逕溘&縺帙↑縺(MINIX) + disk.code = DISK_NOERROR; + + return TRUE; +} + +//=========================================================================== +// +// SCSI 繝上シ繝峨ョ繧」繧ケ繧ッ(PC-9801-55 NEC邏疲ュ」/Anex86/T98Next) +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +SCSIHD_NEC::SCSIHD_NEC() : SCSIHD() +{ + // 繝ッ繝シ繧ッ蛻晄悄蛹 + cylinders = 0; + heads = 0; + sectors = 0; + sectorsize = 0; + imgoffset = 0; + imgsize = 0; +} + +static inline WORD getWordLE(const BYTE *b) +{ + return ((WORD)(b[1]) << 8) | b[0]; +} +static inline DWORD getDwordLE(const BYTE *b) +{ + return ((DWORD)(b[3]) << 24) | ((DWORD)(b[2]) << 16) | + ((DWORD)(b[1]) << 8) | b[0]; +} + +//--------------------------------------------------------------------------- +// +// 繧ェ繝シ繝励Φ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSIHD_NEC::Open(const Filepath& path, BOOL attn) +{ + Fileio fio; + off64_t size; + BYTE hdr[512]; + LPCTSTR ext; + + ASSERT(this); + ASSERT(!disk.ready); + + // 隱ュ縺ソ霎シ縺ソ繧ェ繝シ繝励Φ縺悟ソ隕 + if (!fio.Open(path, Fileio::ReadOnly)) { + return FALSE; + } + + // 繝輔ぃ繧、繝ォ繧オ繧、繧コ縺ョ蜿門セ + size = fio.GetFileSize(); + + // 繝倥ャ繝繝シ隱ュ縺ソ霎シ縺ソ + if (size >= sizeof(hdr)) { + if (!fio.Read(hdr, sizeof(hdr))) { + fio.Close(); + return FALSE; + } + } + fio.Close(); + + // 512繝舌う繝亥腰菴阪〒縺ゅk縺薙→ + if (size & 0x1ff) { + return FALSE; + } + + // 10MB莉・荳 + if (size < 0x9f5400) { + return FALSE; + } + // xm6i縺ォ貅悶§縺ヲ2TB + // 繧医¥莨シ縺溘b縺ョ縺 wxw/wxw_cfg.cpp 縺ォ繧ゅ≠繧 + if (size > 2LL * 1024 * 1024 * 1024 * 1024) { + return FALSE; + } + + // 諡。蠑オ蟄仙挨縺ォ繝代Λ繝。繝シ繧ソ繧呈アコ螳 + ext = path.GetFileExt(); + if (xstrcasecmp(ext, ".HDN") == 0) { + // 繝繝輔か繝ォ繝郁ィュ螳壹→縺励※繧サ繧ッ繧ソ繧オ繧、繧コ512,繧サ繧ッ繧ソ謨ー25,繝倥ャ繝画焚8繧呈Φ螳 + imgoffset = 0; + imgsize = size; + sectorsize = 512; + sectors = 25; + heads = 8; + cylinders = (int)(size >> 9); + cylinders >>= 3; + cylinders /= 25; + } else if (xstrcasecmp(ext, ".HDI") == 0) { // Anex86 HD image? + imgoffset = getDwordLE(&hdr[4 + 4]); + imgsize = getDwordLE(&hdr[4 + 4 + 4]); + sectorsize = getDwordLE(&hdr[4 + 4 + 4 + 4]); + sectors = getDwordLE(&hdr[4 + 4 + 4 + 4 + 4]); + heads = getDwordLE(&hdr[4 + 4 + 4 + 4 + 4 + 4]); + cylinders = getDwordLE(&hdr[4 + 4 + 4 + 4 + 4 + 4 + 4]); + } else if (xstrcasecmp(ext, ".NHD") == 0 && + memcmp(hdr, "T98HDDIMAGE.R0\0", 15) == 0) { // T98Next HD image? + imgoffset = getDwordLE(&hdr[0x10 + 0x100]); + cylinders = getDwordLE(&hdr[0x10 + 0x100 + 4]); + heads = getWordLE(&hdr[0x10 + 0x100 + 4 + 4]); + sectors = getWordLE(&hdr[0x10 + 0x100 + 4 + 4 + 2]); + sectorsize = getWordLE(&hdr[0x10 + 0x100 + 4 + 4 + 2 + 2]); + imgsize = (off64_t)cylinders * heads * sectors * sectorsize; + } + + // 繧サ繧ッ繧ソ繧オ繧、繧コ縺ッ256縺セ縺溘ッ512繧偵し繝昴シ繝 + if (sectorsize != 256 && sectorsize != 512) { + return FALSE; + } + + // 繧、繝。繝シ繧ク繧オ繧、繧コ縺ョ謨エ蜷域ァ繝√ぉ繝繧ッ + if (imgoffset + imgsize > size || (imgsize % sectorsize != 0)) { + return FALSE; + } + + // 繧サ繧ッ繧ソ繧オ繧、繧コ + for(disk.size = 16; disk.size > 0; --(disk.size)) { + if ((1 << disk.size) == sectorsize) + break; + } + if (disk.size <= 0 || disk.size > 16) { + return FALSE; + } + + // 繝悶Ο繝繧ッ謨ー + disk.blocks = (DWORD)(imgsize >> disk.size); + disk.imgoffset = imgoffset; + + // 蝓コ譛ャ繧ッ繝ゥ繧ケ + return Disk::Open(path); +} + +//--------------------------------------------------------------------------- +// +// INQUIRY +// +//--------------------------------------------------------------------------- +int FASTCALL SCSIHD_NEC::Inquiry( + const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor) +{ + int size; + + // 蝓コ蠎輔け繝ゥ繧ケ + size = SCSIHD::Inquiry(cdb, buf, major, minor); + + // 蝓コ蠎輔け繝ゥ繧ケ縺ァ繧ィ繝ゥ繝シ縺ェ繧臥オゆコ + if (size == 0) { + return 0; + } + + // SCSI1逶ク蠖薙↓螟画峩 + buf[2] = 0x01; + buf[3] = 0x01; + + // 繝吶Φ繝繝シ蜷榊キョ縺玲崛縺 + buf[8] = 'N'; + buf[9] = 'E'; + buf[10] = 'C'; + + return size; +} + +//--------------------------------------------------------------------------- +// +// 繧ィ繝ゥ繝シ繝壹シ繧ク霑ス蜉 +// +//--------------------------------------------------------------------------- +int FASTCALL SCSIHD_NEC::AddError(BOOL change, BYTE *buf) +{ + ASSERT(this); + ASSERT(buf); + + // 繧ウ繝シ繝峨サ繝ャ繝ウ繧ー繧ケ繧定ィュ螳 + buf[0] = 0x01; + buf[1] = 0x06; + + // 螟画峩蜿ッ閭ス鬆伜沺縺ッ縺ェ縺 + if (change) { + return 8; + } + + // 繝ェ繝医Λ繧、繧ォ繧ヲ繝ウ繝医ッ0縲√Μ繝溘ャ繝医ち繧、繝縺ッ陬鄂ョ蜀驛ィ縺ョ繝繝輔か繝ォ繝亥、繧剃スソ逕ィ + return 8; +} + +//--------------------------------------------------------------------------- +// +// 繝輔か繝シ繝槭ャ繝医壹シ繧ク霑ス蜉 +// +//--------------------------------------------------------------------------- +int FASTCALL SCSIHD_NEC::AddFormat(BOOL change, BYTE *buf) +{ + int size; + + ASSERT(this); + ASSERT(buf); + + // 繧ウ繝シ繝峨サ繝ャ繝ウ繧ー繧ケ繧定ィュ螳 + buf[0] = 0x80 | 0x03; + buf[1] = 0x16; + + // 迚ゥ逅繧サ繧ッ繧ソ縺ョ繝舌う繝域焚縺ッ螟画峩蜿ッ閭ス縺ォ隕九○繧(螳滄圀縺ォ縺ッ螟画峩縺ァ縺阪↑縺縺) + if (change) { + buf[0xc] = 0xff; + buf[0xd] = 0xff; + return 24; + } + + if (disk.ready) { + // 1繧セ繝シ繝ウ縺ョ繝医Λ繝繧ッ謨ー繧定ィュ螳(PC-9801-55縺ッ縺薙ョ蛟、繧定ヲ九※縺繧九h縺縺) + buf[0x2] = (BYTE)(heads >> 8); + buf[0x3] = (BYTE)heads; + + // 1繝医Λ繝繧ッ縺ョ繧サ繧ッ繧ソ謨ー繧定ィュ螳 + buf[0xa] = (BYTE)(sectors >> 8); + buf[0xb] = (BYTE)sectors; + + // 迚ゥ逅繧サ繧ッ繧ソ縺ョ繝舌う繝域焚繧定ィュ螳 + size = 1 << disk.size; + buf[0xc] = (BYTE)(size >> 8); + buf[0xd] = (BYTE)size; + } + + // 繝ェ繝繝シ繝舌ヶ繝ォ螻樊ァ繧定ィュ螳(譏斐ョ蜷肴ョ) + if (disk.removable) { + buf[20] = 0x20; + } + + return 24; +} + +//--------------------------------------------------------------------------- +// +// 繝峨Λ繧、繝悶壹シ繧ク霑ス蜉 +// +//--------------------------------------------------------------------------- +int FASTCALL SCSIHD_NEC::AddDrive(BOOL change, BYTE *buf) +{ + DWORD cylinder; + + ASSERT(this); + ASSERT(buf); + + // 繧ウ繝シ繝峨サ繝ャ繝ウ繧ー繧ケ繧定ィュ螳 + buf[0] = 0x04; + buf[1] = 0x12; + + // 螟画峩蜿ッ閭ス鬆伜沺縺ッ縺ェ縺 + if (change) { + return 20; + } + + if (disk.ready) { + // 繧キ繝ェ繝ウ繝謨ー繧定ィュ螳 + buf[0x2] = (BYTE)(cylinders >> 16); + buf[0x3] = (BYTE)(cylinders >> 8); + buf[0x4] = (BYTE)cylinders; + + // 繝倥ャ繝画焚繧定ィュ螳 + buf[0x5] = (BYTE)heads; + } + + return 20; +} + +//=========================================================================== +// +// SCSI 繝上シ繝峨ョ繧」繧ケ繧ッ(Macintosh Apple邏疲ュ」) +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +SCSIHD_APPLE::SCSIHD_APPLE() : SCSIHD() +{ +} + +//--------------------------------------------------------------------------- +// +// INQUIRY +// +//--------------------------------------------------------------------------- +int FASTCALL SCSIHD_APPLE::Inquiry( + const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor) +{ + int size; + char vendor[32]; + char product[32]; + + // 蝓コ蠎輔け繝ゥ繧ケ + size = SCSIHD::Inquiry(cdb, buf, major, minor); + + // 蝓コ蠎輔け繝ゥ繧ケ縺ァ繧ィ繝ゥ繝シ縺ェ繧臥オゆコ + if (size == 0) { + return 0; + } + + // 繝吶Φ繝蜷 + sprintf(vendor, " SEAGATE"); + memcpy(&buf[8], vendor, strlen(vendor)); + + // 陬ス蜩∝錐 + sprintf(product, " ST225N"); + memcpy(&buf[16], product, strlen(product)); + + return size; +} + +//--------------------------------------------------------------------------- +// +// Vendor迚ケ谿翫壹シ繧ク霑ス蜉 +// +//--------------------------------------------------------------------------- +int FASTCALL SCSIHD_APPLE::AddVendor(int page, BOOL change, BYTE *buf) +{ + ASSERT(this); + ASSERT(buf); + + // 繝壹シ繧ク繧ウ繝シ繝48 + if ((page != 0x30) && (page != 0x3f)) { + return 0; + } + + // 繧ウ繝シ繝峨サ繝ャ繝ウ繧ー繧ケ繧定ィュ螳 + buf[0] = 0x30; + buf[1] = 0x1c; + + // 螟画峩蜿ッ閭ス鬆伜沺縺ッ縺ェ縺 + if (change) { + return 30; + } + + // APPLE COMPUTER, INC. + memcpy(&buf[0xa], "APPLE COMPUTER, INC.", 20); + + return 30; +} + +//=========================================================================== +// +// SCSI 蜈臥」∵ー励ョ繧」繧ケ繧ッ +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +SCSIMO::SCSIMO() : Disk() +{ + // SCSI 蜈臥」∵ー励ョ繧」繧ケ繧ッ + disk.id = MAKEID('S', 'C', 'M', 'O'); + + // 繝ェ繝繝シ繝舌ヶ繝ォ + disk.removable = TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繧ェ繝シ繝励Φ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSIMO::Open(const Filepath& path, BOOL attn) +{ + Fileio fio; + off64_t size; + + ASSERT(this); + ASSERT(!disk.ready); + + // 隱ュ縺ソ霎シ縺ソ繧ェ繝シ繝励Φ縺悟ソ隕 + if (!fio.Open(path, Fileio::ReadOnly)) { + return FALSE; + } + + // 繝輔ぃ繧、繝ォ繧オ繧、繧コ縺ョ蜿門セ + size = fio.GetFileSize(); + fio.Close(); + + switch (size) { + // 128MB + case 0x797f400: + disk.size = 9; + disk.blocks = 248826; + break; + + // 230MB + case 0xd9eea00: + disk.size = 9; + disk.blocks = 446325; + break; + + // 540MB + case 0x1fc8b800: + disk.size = 9; + disk.blocks = 1041500; + break; + + // 640MB + case 0x25e28000: + disk.size = 11; + disk.blocks = 310352; + break; + + // 縺昴ョ莉(繧ィ繝ゥ繝シ) + default: + return FALSE; + } + + // 蝓コ譛ャ繧ッ繝ゥ繧ケ + Disk::Open(path); + + // 繝ャ繝繧」縺ェ繧峨い繝繝ウ繧キ繝ァ繝ウ + if (disk.ready && attn) { + disk.attn = TRUE; + } + + return TRUE; +} + +#ifndef RASCSI +//--------------------------------------------------------------------------- +// +// 繝ュ繝シ繝 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSIMO::Load(Fileio *fio, int ver) +{ + DWORD sz; + disk_t buf; + DWORD padding; + Filepath path; + + ASSERT(this); + ASSERT(fio); + ASSERT(ver >= 0x0200); + + // version2.03繧医j蜑阪ッ縲√ョ繧」繧ケ繧ッ縺ッ繧サ繝シ繝悶@縺ヲ縺縺ェ縺 + if (ver <= 0x0202) { + return TRUE; + } + + // 繧オ繧、繧コ繧偵Ο繝シ繝峨∫ァ蜷 + if (!fio->Read(&sz, sizeof(sz))) { + return FALSE; + } + if (sz != 52) { + return FALSE; + } + + // 繝舌ャ繝輔ぃ縺ク繝ュ繝シ繝 + PROP_IMPORT(fio, buf.id); + PROP_IMPORT(fio, buf.ready); + PROP_IMPORT(fio, buf.writep); + PROP_IMPORT(fio, buf.readonly); + PROP_IMPORT(fio, buf.removable); + PROP_IMPORT(fio, buf.lock); + PROP_IMPORT(fio, buf.attn); + PROP_IMPORT(fio, buf.reset); + PROP_IMPORT(fio, buf.size); + PROP_IMPORT(fio, buf.blocks); + PROP_IMPORT(fio, buf.lun); + PROP_IMPORT(fio, buf.code); + PROP_IMPORT(fio, padding); + + // 繝代せ繧偵Ο繝シ繝 + if (!path.Load(fio, ver)) { + return FALSE; + } + + // 蠢縺壹う繧ク繧ァ繧ッ繝 + Eject(TRUE); + + // ID縺御ク閾エ縺励◆蝣エ蜷医ョ縺ソ縲∫ァサ蜍 + if (disk.id != buf.id) { + // 繧サ繝シ繝匁凾縺ォMO縺ァ縺ェ縺九▲縺溘ゅう繧ク繧ァ繧ッ繝育憾諷九r邯ュ謖 + return TRUE; + } + + // 蜀阪が繝シ繝励Φ繧定ゥヲ縺ソ繧 + if (!Open(path, FALSE)) { + // 蜀阪が繝シ繝励Φ縺ァ縺阪↑縺縲ゅう繧ク繧ァ繧ッ繝育憾諷九r邯ュ謖 + return TRUE; + } + + // Open蜀縺ァ繝繧」繧ケ繧ッ繧ュ繝」繝繧キ繝・縺ッ菴懈舌&繧後※縺繧九ゅ励Ο繝代ユ繧」縺ョ縺ソ遘サ蜍 + if (!disk.readonly) { + disk.writep = buf.writep; + } + disk.lock = buf.lock; + disk.attn = buf.attn; + disk.reset = buf.reset; + disk.lun = buf.lun; + disk.code = buf.code; + + // 豁」蟶ク縺ォ繝ュ繝シ繝峨〒縺阪◆ + return TRUE; +} +#endif // RASCSI + +//--------------------------------------------------------------------------- +// +// INQUIRY +// +//--------------------------------------------------------------------------- +int FASTCALL SCSIMO::Inquiry( + const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor) +{ + int size; + char rev[32]; + + ASSERT(this); + ASSERT(cdb); + ASSERT(buf); + ASSERT(cdb[0] == 0x12); + + // EVPD繝√ぉ繝繧ッ + if (cdb[1] & 0x01) { + disk.code = DISK_INVALIDCDB; + return FALSE; + } + + // 蝓コ譛ャ繝繝シ繧ソ + // buf[0] ... Optical Memory Device + // buf[1] ... 繝ェ繝繝シ繝舌ヶ繝ォ + // buf[2] ... SCSI-2貅匁侠縺ョ繧ウ繝槭Φ繝我ス鍋ウサ + // buf[3] ... SCSI-2貅匁侠縺ョInquiry繝ャ繧ケ繝昴Φ繧ケ + // buf[4] ... Inquiry霑ス蜉繝繝シ繧ソ + memset(buf, 0, 8); + buf[0] = 0x07; + + // SCSI-2 譛ャ縺ョ p.104 4.4.3 荳榊ス薙↑繝ュ繧ク繧ォ繝ォ繝ヲ繝九ャ繝医ョ蜃ヲ逅 + if (((cdb[1] >> 5) & 0x07) != disk.lun) { + buf[0] = 0x7f; + } + + buf[1] = 0x80; + buf[2] = 0x02; + buf[3] = 0x02; + buf[4] = 36 - 5; // 蠢鬆 + + // 遨コ逋ス縺ァ蝓九a繧 + memset(&buf[8], 0x20, buf[4] - 3); + + // 繝吶Φ繝 + memcpy(&buf[8], BENDER_SIGNATURE, strlen(BENDER_SIGNATURE)); + + // 陬ス蜩∝錐 + memcpy(&buf[16], "M2513A", 6); + + // 繝ェ繝薙ず繝ァ繝ウ(XM6縺ョ繝舌シ繧ク繝ァ繝ウNo) + sprintf(rev, "0%01d%01d%01d", + (int)major, (int)(minor >> 4), (int)(minor & 0x0f)); + memcpy(&buf[32], rev, 4); + + // 霑泌唆縺ァ縺阪k繝繝シ繧ソ縺ョ繧オ繧、繧コ + size = (buf[4] + 5); + + // 逶ク謇九ョ繝舌ャ繝輔ぃ縺悟ー代↑縺代l縺ー蛻カ髯舌☆繧 + if (size > (int)cdb[4]) { + size = (int)cdb[4]; + } + + // 謌仙粥 + disk.code = DISK_NOERROR; + return size; +} + +//--------------------------------------------------------------------------- +// +// MODE SELECT +// 窶サdisk.code縺ョ蠖ア髻ソ繧貞女縺代↑縺 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSIMO::ModeSelect(const DWORD *cdb, const BYTE *buf, int length) +{ + int page; + int size; + + ASSERT(this); + ASSERT(buf); + ASSERT(length >= 0); + + // PF + if (cdb[1] & 0x10) { + // Mode Parameter header + if (length >= 12) { + // 繝悶Ο繝繧ッ繝ャ繝ウ繧ー繧ケ縺ョ繝舌う繝域焚繧偵メ繧ァ繝繧ッ + size = 1 << disk.size; + if (buf[9] != (BYTE)(size >> 16) || + buf[10] != (BYTE)(size >> 8) || buf[11] != (BYTE)size) { + // 莉翫ョ縺ィ縺薙m繧サ繧ッ繧ソ髟キ縺ョ螟画峩縺ッ險ア縺輔↑縺 + disk.code = DISK_INVALIDPRM; + return FALSE; + } + buf += 12; + length -= 12; + } + + // 繝壹シ繧ク縺ョ隗」譫 + while (length > 0) { + // 繝壹シ繧ク縺ョ蜿門セ + page = buf[0]; + + switch (page) { + // format device + case 0x03: + // 迚ゥ逅繧サ繧ッ繧ソ縺ョ繝舌う繝域焚繧偵メ繧ァ繝繧ッ + size = 1 << disk.size; + if (buf[0xc] != (BYTE)(size >> 8) || buf[0xd] != (BYTE)size) { + // 莉翫ョ縺ィ縺薙m繧サ繧ッ繧ソ髟キ縺ョ螟画峩縺ッ險ア縺輔↑縺 + disk.code = DISK_INVALIDPRM; + return FALSE; + } + break; + // vendor unique format + case 0x20: + // just ignore, for now + break; + + // 縺昴ョ莉悶壹シ繧ク + default: + break; + } + + // 谺。縺ョ繝壹シ繧ク縺ク + size = buf[1] + 2; + length -= size; + buf += size; + } + } + + // 縺ィ繧翫≠縺医★繧ィ繝ゥ繝シ縺ッ逋コ逕溘&縺帙↑縺(MINIX) + disk.code = DISK_NOERROR; + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// Vendor Unique Format Page 20h (MO) +// +//--------------------------------------------------------------------------- +int FASTCALL SCSIMO::AddVendor(int page, BOOL change, BYTE *buf) +{ + ASSERT(this); + ASSERT(buf); + + // 繝壹シ繧ク繧ウ繝シ繝20h + if ((page != 0x20) && (page != 0x3f)) { + return 0; + } + + // 繧ウ繝シ繝峨サ繝ャ繝ウ繧ー繧ケ繧定ィュ螳 + buf[0] = 0x20; + buf[1] = 0x0a; + + // 螟画峩蜿ッ閭ス鬆伜沺縺ッ縺ェ縺 + if (change) { + return 12; + } + + /* + mode page code 20h - Vendor Unique Format Page + format mode XXh type 0 + information: http://h20628.www2.hp.com/km-ext/kmcsdirect/emr_na-lpg28560-1.pdf + + offset description + 02h format mode + 03h type of format (0) + 04~07h size of user band (total sectors?) + 08~09h size of spare band (spare sectors?) + 0A~0Bh number of bands + + actual value of each 3.5inches optical medium (grabbed by Fujitsu M2513EL) + + 128M 230M 540M 640M + --------------------------------------------------- + size of user band 3CBFAh 6CF75h FE45Ch 4BC50h + size of spare band 0400h 0401h 08CAh 08C4h + number of bands 0001h 000Ah 0012h 000Bh + + further information: http://r2089.blog36.fc2.com/blog-entry-177.html + */ + + if (disk.ready) { + unsigned spare = 0; + unsigned bands = 0; + + if (disk.size == 9) switch (disk.blocks) { + // 128MB + case 248826: + spare = 1024; + bands = 1; + break; + + // 230MB + case 446325: + spare = 1025; + bands = 10; + break; + + // 540MB + case 1041500: + spare = 2250; + bands = 18; + break; + } + + if (disk.size == 11) switch (disk.blocks) { + // 640MB + case 310352: + spare = 2244; + bands = 11; + break; + + // 1.3GB (lpproj: not tested with real device) + case 605846: + spare = 4437; + bands = 18; + break; + } + + buf[2] = 0; // format mode + buf[3] = 0; // type of format + buf[4] = (BYTE)(disk.blocks >> 24); + buf[5] = (BYTE)(disk.blocks >> 16); + buf[6] = (BYTE)(disk.blocks >> 8); + buf[7] = (BYTE)disk.blocks; + buf[8] = (BYTE)(spare >> 8); + buf[9] = (BYTE)spare; + buf[10] = (BYTE)(bands >> 8); + buf[11] = (BYTE)bands; + } + + return 12; +} + +//=========================================================================== +// +// CD繝医Λ繝繧ッ +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +CDTrack::CDTrack(SCSICD *scsicd) +{ + ASSERT(scsicd); + + // 隕ェ縺ィ縺ェ繧気D-ROM繝繝舌う繧ケ繧定ィュ螳 + cdrom = scsicd; + + // 繝医Λ繝繧ッ辟。蜉ケ + valid = FALSE; + + // 縺昴ョ莉悶ョ繝繝シ繧ソ繧貞晄悄蛹 + track_no = -1; + first_lba = 0; + last_lba = 0; + audio = FALSE; + raw = FALSE; +} + +//--------------------------------------------------------------------------- +// +// 繝繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +CDTrack::~CDTrack() +{ +} + +//--------------------------------------------------------------------------- +// +// 蛻晄悄蛹 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL CDTrack::Init(int track, DWORD first, DWORD last) +{ + ASSERT(this); + ASSERT(!valid); + ASSERT(track >= 1); + ASSERT(first < last); + + // 繝医Λ繝繧ッ逡ェ蜿キ繧定ィュ螳壹∵怏蜉ケ蛹 + track_no = track; + valid = TRUE; + + // LBA繧定ィ俶カ + first_lba = first; + last_lba = last; + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繝代せ險ュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL CDTrack::SetPath(BOOL cdda, const Filepath& path) +{ + ASSERT(this); + ASSERT(valid); + + // CD-DA縺九√ョ繝シ繧ソ縺 + audio = cdda; + + // 繝代せ險俶カ + imgpath = path; +} + +//--------------------------------------------------------------------------- +// +// 繝代せ蜿門セ +// +//--------------------------------------------------------------------------- +void FASTCALL CDTrack::GetPath(Filepath& path) const +{ + ASSERT(this); + ASSERT(valid); + + // 繝代せ繧定ソ斐☆ + path = imgpath; +} + +//--------------------------------------------------------------------------- +// +// 繧、繝ウ繝繝繧ッ繧ケ霑ス蜉 +// +//--------------------------------------------------------------------------- +void FASTCALL CDTrack::AddIndex(int index, DWORD lba) +{ + ASSERT(this); + ASSERT(valid); + ASSERT(index > 0); + ASSERT(first_lba <= lba); + ASSERT(lba <= last_lba); + + // 迴セ蝨ィ縺ッ繧、繝ウ繝繝繧ッ繧ケ縺ッ繧オ繝昴シ繝医@縺ェ縺 + ASSERT(FALSE); +} + +//--------------------------------------------------------------------------- +// +// 髢句ァ記BA蜿門セ +// +//--------------------------------------------------------------------------- +DWORD FASTCALL CDTrack::GetFirst() const +{ + ASSERT(this); + ASSERT(valid); + ASSERT(first_lba < last_lba); + + return first_lba; +} + +//--------------------------------------------------------------------------- +// +// 邨らォッLBA蜿門セ +// +//--------------------------------------------------------------------------- +DWORD FASTCALL CDTrack::GetLast() const +{ + ASSERT(this); + ASSERT(valid); + ASSERT(first_lba < last_lba); + + return last_lba; +} + +//--------------------------------------------------------------------------- +// +// 繝悶Ο繝繧ッ謨ー蜿門セ +// +//--------------------------------------------------------------------------- +DWORD FASTCALL CDTrack::GetBlocks() const +{ + ASSERT(this); + ASSERT(valid); + ASSERT(first_lba < last_lba); + + // 髢句ァ記BA縺ィ譛邨LBA縺九i邂怜コ + return (DWORD)(last_lba - first_lba + 1); +} + +//--------------------------------------------------------------------------- +// +// 繝医Λ繝繧ッ逡ェ蜿キ蜿門セ +// +//--------------------------------------------------------------------------- +int FASTCALL CDTrack::GetTrackNo() const +{ + ASSERT(this); + ASSERT(valid); + ASSERT(track_no >= 1); + + return track_no; +} + +//--------------------------------------------------------------------------- +// +// 譛牙柑縺ェ繝悶Ο繝繧ッ縺 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL CDTrack::IsValid(DWORD lba) const +{ + ASSERT(this); + + // 繝医Λ繝繧ッ閾ェ菴薙′辟。蜉ケ縺ェ繧峨:ALSE + if (!valid) { + return FALSE; + } + + // first繧医j蜑阪↑繧峨:ALSE + if (lba < first_lba) { + return FALSE; + } + + // last繧医j蠕後↑繧峨:ALSE + if (last_lba < lba) { + return FALSE; + } + + // 縺薙ョ繝医Λ繝繧ッ + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繧ェ繝シ繝繧」繧ェ繝医Λ繝繧ッ縺 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL CDTrack::IsAudio() const +{ + ASSERT(this); + ASSERT(valid); + + return audio; +} + +//=========================================================================== +// +// CD-DA繝舌ャ繝輔ぃ +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +CDDABuf::CDDABuf() +{ +} + +//--------------------------------------------------------------------------- +// +// 繝繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +CDDABuf::~CDDABuf() +{ +} + +//=========================================================================== +// +// SCSI CD-ROM +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +SCSICD::SCSICD() : Disk() +{ + int i; + + // SCSI CD-ROM + disk.id = MAKEID('S', 'C', 'C', 'D'); + + // 繝ェ繝繝シ繝舌ヶ繝ォ縲∵嶌霎シ縺ソ遖∵ュ「 + disk.removable = TRUE; + disk.writep = TRUE; + + // RAW蠖「蠑上〒縺ェ縺 + rawfile = FALSE; + + // 繝輔Ξ繝シ繝蛻晄悄蛹 + frame = 0; + + // 繝医Λ繝繧ッ蛻晄悄蛹 + for (i = 0; i < TrackMax; i++) { + track[i] = NULL; + } + tracks = 0; + dataindex = -1; + audioindex = -1; +} + +//--------------------------------------------------------------------------- +// +// 繝繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +SCSICD::~SCSICD() +{ + // 繝医Λ繝繧ッ繧ッ繝ェ繧「 + ClearTrack(); +} + +#ifndef RASCSI +//--------------------------------------------------------------------------- +// +// 繝ュ繝シ繝 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSICD::Load(Fileio *fio, int ver) +{ + DWORD sz; + disk_t buf; + DWORD padding; + Filepath path; + + ASSERT(this); + ASSERT(fio); + ASSERT(ver >= 0x0200); + + // version2.03繧医j蜑阪ッ縲√ョ繧」繧ケ繧ッ縺ッ繧サ繝シ繝悶@縺ヲ縺縺ェ縺 + if (ver <= 0x0202) { + return TRUE; + } + + // 繧オ繧、繧コ繧偵Ο繝シ繝峨∫ァ蜷 + if (!fio->Read(&sz, sizeof(sz))) { + return FALSE; + } + if (sz != 52) { + return FALSE; + } + + // 繝舌ャ繝輔ぃ縺ク繝ュ繝シ繝 + PROP_IMPORT(fio, buf.id); + PROP_IMPORT(fio, buf.ready); + PROP_IMPORT(fio, buf.writep); + PROP_IMPORT(fio, buf.readonly); + PROP_IMPORT(fio, buf.removable); + PROP_IMPORT(fio, buf.lock); + PROP_IMPORT(fio, buf.attn); + PROP_IMPORT(fio, buf.reset); + PROP_IMPORT(fio, buf.size); + PROP_IMPORT(fio, buf.blocks); + PROP_IMPORT(fio, buf.lun); + PROP_IMPORT(fio, buf.code); + PROP_IMPORT(fio, padding); + + // 繝代せ繧偵Ο繝シ繝 + if (!path.Load(fio, ver)) { + return FALSE; + } + + // 蠢縺壹う繧ク繧ァ繧ッ繝 + Eject(TRUE); + + // ID縺御ク閾エ縺励◆蝣エ蜷医ョ縺ソ縲∫ァサ蜍 + if (disk.id != buf.id) { + // 繧サ繝シ繝匁凾縺ォCD-ROM縺ァ縺ェ縺九▲縺溘ゅう繧ク繧ァ繧ッ繝育憾諷九r邯ュ謖 + return TRUE; + } + + // 蜀阪が繝シ繝励Φ繧定ゥヲ縺ソ繧 + if (!Open(path, FALSE)) { + // 蜀阪が繝シ繝励Φ縺ァ縺阪↑縺縲ゅう繧ク繧ァ繧ッ繝育憾諷九r邯ュ謖 + return TRUE; + } + + // Open蜀縺ァ繝繧」繧ケ繧ッ繧ュ繝」繝繧キ繝・縺ッ菴懈舌&繧後※縺繧九ゅ励Ο繝代ユ繧」縺ョ縺ソ遘サ蜍 + if (!disk.readonly) { + disk.writep = buf.writep; + } + disk.lock = buf.lock; + disk.attn = buf.attn; + disk.reset = buf.reset; + disk.lun = buf.lun; + disk.code = buf.code; + + // 蜀榊コヲ縲√ョ繧」繧ケ繧ッ繧ュ繝」繝繧キ繝・繧堤エ譽 + if (disk.dcache) { + delete disk.dcache; + disk.dcache = NULL; + } + disk.dcache = NULL; + + // 證ォ螳 + disk.blocks = track[0]->GetBlocks(); + if (disk.blocks > 0) { + // 繝繧」繧ケ繧ッ繧ュ繝」繝繧キ繝・繧剃ス懊j逶エ縺 + track[0]->GetPath(path); + disk.dcache = new DiskCache(path, disk.size, disk.blocks); + disk.dcache->SetRawMode(rawfile); + + // 繝繝シ繧ソ繧、繝ウ繝繝繧ッ繧ケ繧貞崎ィュ螳 + dataindex = 0; + } + + return TRUE; +} +#endif // RASCSI + +//--------------------------------------------------------------------------- +// +// 繧ェ繝シ繝励Φ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSICD::Open(const Filepath& path, BOOL attn) +{ + Fileio fio; + off64_t size; + char file[5]; + + ASSERT(this); + ASSERT(!disk.ready); + + // 蛻晄悄蛹悶√ヨ繝ゥ繝繧ッ繧ッ繝ェ繧「 + disk.blocks = 0; + rawfile = FALSE; + ClearTrack(); + + // 隱ュ縺ソ霎シ縺ソ繧ェ繝シ繝励Φ縺悟ソ隕 + if (!fio.Open(path, Fileio::ReadOnly)) { + return FALSE; + } + + // 迚ゥ逅CD繧「繧ッ繧サ繧ケ縺ェ繧峨け繝ュ繝シ繧コ縺励※蟋碑ュイ縺吶k + if (path.GetPath()[0] == _T('\\')) { + // 繧ッ繝ュ繝シ繧コ + fio.Close(); + + // 迚ゥ逅CD繧ェ繝シ繝励Φ + if (!OpenPhysical(path)) { + return FALSE; + } + } else { + // 繧オ繧、繧コ蜿門セ + size = fio.GetFileSize(); + if (size <= 4) { + fio.Close(); + return FALSE; + } + + // CUE繧キ繝シ繝医°縲!SO繝輔ぃ繧、繝ォ縺九ョ蛻、螳壹r陦後≧ + fio.Read(file, 4); + file[4] = '\0'; + fio.Close(); + + // FILE縺ァ蟋九∪縺」縺ヲ縺繧後ー縲,UE繧キ繝シ繝医→縺ソ縺ェ縺 + if (xstrncasecmp(file, "FILE", 4) == 0) { + // CUE縺ィ縺励※繧ェ繝シ繝励Φ + if (!OpenCue(path)) { + return FALSE; + } + } else { + // ISO縺ィ縺励※繧ェ繝シ繝励Φ + if (!OpenIso(path)) { + return FALSE; + } + } + } + + // 繧ェ繝シ繝励Φ謌仙粥 + ASSERT(disk.blocks > 0); + disk.size = 11; + + // 蝓コ譛ャ繧ッ繝ゥ繧ケ + Disk::Open(path); + + // RAW繝輔Λ繧ー繧定ィュ螳 + ASSERT(disk.dcache); + disk.dcache->SetRawMode(rawfile); + + // ROM繝。繝繧」繧「縺ェ縺ョ縺ァ縲∵嶌縺崎セシ縺ソ縺ッ縺ァ縺阪↑縺 + disk.writep = TRUE; + + // 繝ャ繝繧」縺ェ繧峨い繝繝ウ繧キ繝ァ繝ウ + if (disk.ready && attn) { + disk.attn = TRUE; + } + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繧ェ繝シ繝励Φ(CUE) +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSICD::OpenCue(const Filepath& /*path*/) +{ + ASSERT(this); + + // 蟶ク縺ォ螟ア謨 + return FALSE; +} + +//--------------------------------------------------------------------------- +// +// 繧ェ繝シ繝励Φ(ISO) +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSICD::OpenIso(const Filepath& path) +{ + Fileio fio; + off64_t size; + BYTE header[12]; + BYTE sync[12]; + + ASSERT(this); + + // 隱ュ縺ソ霎シ縺ソ繧ェ繝シ繝励Φ縺悟ソ隕 + if (!fio.Open(path, Fileio::ReadOnly)) { + return FALSE; + } + + // 繧オ繧、繧コ蜿門セ + size = fio.GetFileSize(); + if (size < 0x800) { + fio.Close(); + return FALSE; + } + + // 譛蛻昴ョ12繝舌う繝医r隱ュ縺ソ蜿悶▲縺ヲ縲√け繝ュ繝シ繧コ + if (!fio.Read(header, sizeof(header))) { + fio.Close(); + return FALSE; + } + + // RAW蠖「蠑上°繝√ぉ繝繧ッ + memset(sync, 0xff, sizeof(sync)); + sync[0] = 0x00; + sync[11] = 0x00; + rawfile = FALSE; + if (memcmp(header, sync, sizeof(sync)) == 0) { + // 00,FFx10,00縺ェ縺ョ縺ァ縲ヽAW蠖「蠑上→謗ィ螳壹&繧後k + if (!fio.Read(header, 4)) { + fio.Close(); + return FALSE; + } + + // MODE1/2048縺セ縺溘ッMODE1/2352縺ョ縺ソ繧オ繝昴シ繝 + if (header[3] != 0x01) { + // 繝「繝シ繝峨′驕輔≧ + fio.Close(); + return FALSE; + } + + // RAW繝輔ぃ繧、繝ォ縺ォ險ュ螳 + rawfile = TRUE; + } + fio.Close(); + + if (rawfile) { + // 繧オ繧、繧コ縺2536縺ョ蛟肴焚縺ァ縲700MB莉・荳九〒縺ゅk縺薙→ + if (size % 0x930) { + return FALSE; + } + if (size > 912579600) { + return FALSE; + } + + // 繝悶Ο繝繧ッ謨ー繧定ィュ螳 + disk.blocks = (DWORD)(size / 0x930); + } else { + // 繧オ繧、繧コ縺2048縺ョ蛟肴焚縺ァ縲700MB莉・荳九〒縺ゅk縺薙→ + if (size & 0x7ff) { + return FALSE; + } + if (size > 0x2bed5000) { + return FALSE; + } + + // 繝悶Ο繝繧ッ謨ー繧定ィュ螳 + disk.blocks = (DWORD)(size >> 11); + } + + // 繝繝シ繧ソ繝医Λ繝繧ッ1縺、縺ョ縺ソ菴懈 + ASSERT(!track[0]); + track[0] = new CDTrack(this); + track[0]->Init(1, 0, disk.blocks - 1); + track[0]->SetPath(FALSE, path); + tracks = 1; + dataindex = 0; + + // 繧ェ繝シ繝励Φ謌仙粥 + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繧ェ繝シ繝励Φ(Physical) +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSICD::OpenPhysical(const Filepath& path) +{ + Fileio fio; + off64_t size; + + ASSERT(this); + + // 隱ュ縺ソ霎シ縺ソ繧ェ繝シ繝励Φ縺悟ソ隕 + if (!fio.Open(path, Fileio::ReadOnly)) { + return FALSE; + } + + // 繧オ繧、繧コ蜿門セ + size = fio.GetFileSize(); + if (size < 0x800) { + fio.Close(); + return FALSE; + } + + // 繧ッ繝ュ繝シ繧コ + fio.Close(); + + // 繧オ繧、繧コ縺2048縺ョ蛟肴焚縺ァ縲700MB莉・荳九〒縺ゅk縺薙→ + if (size & 0x7ff) { + return FALSE; + } + if (size > 0x2bed5000) { + return FALSE; + } + + // 繝悶Ο繝繧ッ謨ー繧定ィュ螳 + disk.blocks = (DWORD)(size >> 11); + + // 繝繝シ繧ソ繝医Λ繝繧ッ1縺、縺ョ縺ソ菴懈 + ASSERT(!track[0]); + track[0] = new CDTrack(this); + track[0]->Init(1, 0, disk.blocks - 1); + track[0]->SetPath(FALSE, path); + tracks = 1; + dataindex = 0; + + // 繧ェ繝シ繝励Φ謌仙粥 + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// INQUIRY +// +//--------------------------------------------------------------------------- +int FASTCALL SCSICD::Inquiry( + const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor) +{ + char rev[32]; + int size; + + ASSERT(this); + ASSERT(cdb); + ASSERT(buf); + ASSERT(cdb[0] == 0x12); + + // EVPD繝√ぉ繝繧ッ + if (cdb[1] & 0x01) { + disk.code = DISK_INVALIDCDB; + return FALSE; + } + + // 蝓コ譛ャ繝繝シ繧ソ + // buf[0] ... CD-ROM Device + // buf[1] ... 繝ェ繝繝シ繝舌ヶ繝ォ + // buf[2] ... SCSI-2貅匁侠縺ョ繧ウ繝槭Φ繝我ス鍋ウサ + // buf[3] ... SCSI-2貅匁侠縺ョInquiry繝ャ繧ケ繝昴Φ繧ケ + // buf[4] ... Inquiry霑ス蜉繝繝シ繧ソ + memset(buf, 0, 8); + buf[0] = 0x05; + + // SCSI-2 譛ャ縺ョ p.104 4.4.3 荳榊ス薙↑繝ュ繧ク繧ォ繝ォ繝ヲ繝九ャ繝医ョ蜃ヲ逅 + if (((cdb[1] >> 5) & 0x07) != disk.lun) { + buf[0] = 0x7f; + } + + buf[1] = 0x80; + buf[2] = 0x02; + buf[3] = 0x02; + buf[4] = 36 - 5; // 蠢鬆 + + // 遨コ逋ス縺ァ蝓九a繧 + memset(&buf[8], 0x20, buf[4] - 3); + + // 繝吶Φ繝 + memcpy(&buf[8], BENDER_SIGNATURE, strlen(BENDER_SIGNATURE)); + + // 陬ス蜩∝錐 + memcpy(&buf[16], "CD-ROM CDU-55S", 14); + + // 繝ェ繝薙ず繝ァ繝ウ(XM6縺ョ繝舌シ繧ク繝ァ繝ウNo) + sprintf(rev, "0%01d%01d%01d", + (int)major, (int)(minor >> 4), (int)(minor & 0x0f)); + memcpy(&buf[32], rev, 4); + + // 霑泌唆縺ァ縺阪k繝繝シ繧ソ縺ョ繧オ繧、繧コ + size = (buf[4] + 5); + + // 逶ク謇九ョ繝舌ャ繝輔ぃ縺悟ー代↑縺代l縺ー蛻カ髯舌☆繧 + if (size > (int)cdb[4]) { + size = (int)cdb[4]; + } + + // 謌仙粥 + disk.code = DISK_NOERROR; + return size; +} + +//--------------------------------------------------------------------------- +// +// READ +// +//--------------------------------------------------------------------------- +int FASTCALL SCSICD::Read(BYTE *buf, DWORD block) +{ + int index; + Filepath path; + + ASSERT(this); + ASSERT(buf); + + // 迥カ諷九メ繧ァ繝繧ッ + if (!CheckReady()) { + return 0; + } + + // 繝医Λ繝繧ッ讀懃エ「 + index = SearchTrack(block); + + // 辟。蜉ケ縺ェ繧峨∫ッ蝗イ螟 + if (index < 0) { + disk.code = DISK_INVALIDLBA; + return 0; + } + ASSERT(track[index]); + + // 迴セ蝨ィ縺ョ繝繝シ繧ソ繝医Λ繝繧ッ縺ィ逡ー縺ェ縺」縺ヲ縺繧後ー + if (dataindex != index) { + // 迴セ蝨ィ縺ョ繝繧」繧ケ繧ッ繧ュ繝」繝繧キ繝・繧貞炎髯、(Save縺ョ蠢隕√ッ縺ェ縺) + delete disk.dcache; + disk.dcache = NULL; + + // 繝悶Ο繝繧ッ謨ー繧貞崎ィュ螳 + disk.blocks = track[index]->GetBlocks(); + ASSERT(disk.blocks > 0); + + // 繝繧」繧ケ繧ッ繧ュ繝」繝繧キ繝・繧剃ス懊j逶エ縺 + track[index]->GetPath(path); + disk.dcache = new DiskCache(path, disk.size, disk.blocks); + disk.dcache->SetRawMode(rawfile); + + // 繝繝シ繧ソ繧、繝ウ繝繝繧ッ繧ケ繧貞崎ィュ螳 + dataindex = index; + } + + // 蝓コ譛ャ繧ッ繝ゥ繧ケ + ASSERT(dataindex >= 0); + return Disk::Read(buf, block); +} + +//--------------------------------------------------------------------------- +// +// READ TOC +// +//--------------------------------------------------------------------------- +int FASTCALL SCSICD::ReadToc(const DWORD *cdb, BYTE *buf) +{ + int last; + int index; + int length; + int loop; + int i; + BOOL msf; + DWORD lba; + + ASSERT(this); + ASSERT(cdb); + ASSERT(cdb[0] == 0x43); + ASSERT(buf); + + // 繝ャ繝繧」繝√ぉ繝繧ッ + if (!CheckReady()) { + return 0; + } + + // 繝ャ繝繧」縺ァ縺ゅk縺ェ繧峨√ヨ繝ゥ繝繧ッ縺梧怙菴1縺、莉・荳雁ュ伜惠縺吶k + ASSERT(tracks > 0); + ASSERT(track[0]); + + // 繧「繝ュ繧ア繝シ繧キ繝ァ繝ウ繝ャ繝ウ繧ー繧ケ蜿門セ励√ヰ繝繝輔ぃ繧ッ繝ェ繧「 + length = cdb[7] << 8; + length |= cdb[8]; + memset(buf, 0, length); + + // MSF繝輔Λ繧ー蜿門セ + if (cdb[1] & 0x02) { + msf = TRUE; + } else { + msf = FALSE; + } + + // 譛邨ゅヨ繝ゥ繝繧ッ逡ェ蜿キ繧貞叙蠕励√メ繧ァ繝繧ッ + last = track[tracks - 1]->GetTrackNo(); + if ((int)cdb[6] > last) { + // 縺溘□縺輸A縺ッ髯、螟 + if (cdb[6] != 0xaa) { + disk.code = DISK_INVALIDCDB; + return 0; + } + } + + // 髢句ァ九う繝ウ繝繝繧ッ繧ケ繧偵メ繧ァ繝繧ッ + index = 0; + if (cdb[6] != 0x00) { + // 繝医Λ繝繧ッ逡ェ蜿キ縺御ク閾エ縺吶k縺セ縺ァ縲√ヨ繝ゥ繝繧ッ繧帝イ繧√k + while (track[index]) { + if ((int)cdb[6] == track[index]->GetTrackNo()) { + break; + } + index++; + } + + // 隕九▽縺九i縺ェ縺代l縺ーAA縺九∝驛ィ繧ィ繝ゥ繝シ + if (!track[index]) { + if (cdb[6] == 0xaa) { + // AA縺ェ縺ョ縺ァ縲∵怙邨LBA+1繧定ソ斐☆ + buf[0] = 0x00; + buf[1] = 0x0a; + buf[2] = (BYTE)track[0]->GetTrackNo(); + buf[3] = (BYTE)last; + buf[6] = 0xaa; + lba = track[tracks - 1]->GetLast() + 1; + if (msf) { + LBAtoMSF(lba, &buf[8]); + } else { + buf[10] = (BYTE)(lba >> 8); + buf[11] = (BYTE)lba; + } + return length; + } + + // 縺昴l莉・螟悶ッ繧ィ繝ゥ繝シ + disk.code = DISK_INVALIDCDB; + return 0; + } + } + + // 莉雁屓霑斐☆繝医Λ繝繧ッ繝繧」繧ケ繧ッ繝ェ繝励ち縺ョ蛟区焚(繝ォ繝シ繝玲焚) + loop = last - track[index]->GetTrackNo() + 1; + ASSERT(loop >= 1); + + // 繝倥ャ繝菴懈 + buf[0] = (BYTE)(((loop << 3) + 2) >> 8); + buf[1] = (BYTE)((loop << 3) + 2); + buf[2] = (BYTE)track[0]->GetTrackNo(); + buf[3] = (BYTE)last; + buf += 4; + + // 繝ォ繝シ繝 + for (i = 0; i < loop; i++) { + // ADR縺ィControl + if (track[index]->IsAudio()) { + // 繧ェ繝シ繝繧」繧ェ繝医Λ繝繧ッ + buf[1] = 0x10; + } else { + // 繝繝シ繧ソ繝医Λ繝繧ッ + buf[1] = 0x14; + } + + // 繝医Λ繝繧ッ逡ェ蜿キ + buf[2] = (BYTE)track[index]->GetTrackNo(); + + // 繝医Λ繝繧ッ繧「繝峨Ξ繧ケ + if (msf) { + LBAtoMSF(track[index]->GetFirst(), &buf[4]); + } else { + buf[6] = (BYTE)(track[index]->GetFirst() >> 8); + buf[7] = (BYTE)(track[index]->GetFirst()); + } + + // 繝舌ャ繝輔ぃ縺ィ繧、繝ウ繝繝繧ッ繧ケ繧帝イ繧√k + buf += 8; + index++; + } + + // 繧「繝ュ繧ア繝シ繧キ繝ァ繝ウ繝ャ繝ウ繧ー繧ケ縺縺大ソ縺夊ソ斐☆ + return length; +} + +//--------------------------------------------------------------------------- +// +// PLAY AUDIO +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSICD::PlayAudio(const DWORD* /*cdb*/) +{ + ASSERT(this); + + disk.code = DISK_INVALIDCDB; + return FALSE; +} + +//--------------------------------------------------------------------------- +// +// PLAY AUDIO MSF +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSICD::PlayAudioMSF(const DWORD* /*cdb*/) +{ + ASSERT(this); + + disk.code = DISK_INVALIDCDB; + return FALSE; +} + +//--------------------------------------------------------------------------- +// +// PLAY AUDIO TRACK +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSICD::PlayAudioTrack(const DWORD* /*cdb*/) +{ + ASSERT(this); + + disk.code = DISK_INVALIDCDB; + return FALSE; +} + +//--------------------------------------------------------------------------- +// +// LBA竊樽SF螟画鋤 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSICD::LBAtoMSF(DWORD lba, BYTE *msf) const +{ + DWORD m; + DWORD s; + DWORD f; + + ASSERT(this); + + // 75縲75*60縺ァ縺昴l縺槭l菴吶j繧貞コ縺 + m = lba / (75 * 60); + s = lba % (75 * 60); + f = s % 75; + s /= 75; + + // 蝓コ轤ケ縺ッM=0,S=2,F=0 + s += 2; + if (s >= 60) { + s -= 60; + m++; + } + + // 譬シ邏 + ASSERT(m < 0x100); + ASSERT(s < 60); + ASSERT(f < 75); + msf[0] = 0x00; + msf[1] = (BYTE)m; + msf[2] = (BYTE)s; + msf[3] = (BYTE)f; +} + +//--------------------------------------------------------------------------- +// +// MSF竊鱈BA螟画鋤 +// +//--------------------------------------------------------------------------- +DWORD FASTCALL SCSICD::MSFtoLBA(const BYTE *msf) const +{ + DWORD lba; + + ASSERT(this); + ASSERT(msf[2] < 60); + ASSERT(msf[3] < 75); + + // 1, 75, 75*60縺ョ蛟肴焚縺ァ蜷育ョ + lba = msf[1]; + lba *= 60; + lba += msf[2]; + lba *= 75; + lba += msf[3]; + + // 蝓コ轤ケ縺ッM=0,S=2,F=0縺ェ縺ョ縺ァ縲150繧貞シ輔¥ + lba -= 150; + + return lba; +} + +//--------------------------------------------------------------------------- +// +// 繝医Λ繝繧ッ繧ッ繝ェ繧「 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSICD::ClearTrack() +{ + int i; + + ASSERT(this); + + // 繝医Λ繝繧ッ繧ェ繝悶ず繧ァ繧ッ繝医r蜑企勁 + for (i = 0; i < TrackMax; i++) { + if (track[i]) { + delete track[i]; + track[i] = NULL; + } + } + + // 繝医Λ繝繧ッ謨ー0 + tracks = 0; + + // 繝繝シ繧ソ縲√が繝シ繝繧」繧ェ縺ィ繧りィュ螳壹↑縺 + dataindex = -1; + audioindex = -1; +} + +//--------------------------------------------------------------------------- +// +// 繝医Λ繝繧ッ讀懃エ「 +// 窶サ隕九▽縺九i縺ェ縺代l縺ー-1繧定ソ斐☆ +// +//--------------------------------------------------------------------------- +int FASTCALL SCSICD::SearchTrack(DWORD lba) const +{ + int i; + + ASSERT(this); + + // 繝医Λ繝繧ッ繝ォ繝シ繝 + for (i = 0; i < tracks; i++) { + // 繝医Λ繝繧ッ縺ォ閨槭¥ + ASSERT(track[i]); + if (track[i]->IsValid(lba)) { + return i; + } + } + + // 隕九▽縺九i縺ェ縺九▲縺 + return -1; +} + +//--------------------------------------------------------------------------- +// +// 繝輔Ξ繝シ繝騾夂衍 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSICD::NextFrame() +{ + ASSERT(this); + ASSERT((frame >= 0) && (frame < 75)); + + // 繝輔Ξ繝シ繝繧0ス74縺ョ遽蝗イ縺ァ險ュ螳 + frame = (frame + 1) % 75; + + // 1蜻ィ縺励◆繧宇ALSE + if (frame != 0) { + return TRUE; + } else { + return FALSE; + } +} + +//--------------------------------------------------------------------------- +// +// CD-DA繝舌ャ繝輔ぃ蜿門セ +// +//--------------------------------------------------------------------------- +void FASTCALL SCSICD::GetBuf(DWORD* /*buffer*/, int /*samples*/, DWORD /*rate*/) +{ + ASSERT(this); +} + +//=========================================================================== +// +// SCSI 繝帙せ繝医ヶ繝ェ繝繧ク +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +SCSIBR::SCSIBR() : Disk() +{ + // 繝帙せ繝医ヶ繝ェ繝繧ク + disk.id = MAKEID('S', 'C', 'B', 'R'); + + // TAP繝峨Λ繧、繝千函謌 + tap = new CTapDriver(); + m_bTapEnable = tap->Init(); + + // MAC繧「繝峨Ξ繧ケ繧堤函謌 + memset(mac_addr, 0x00, 6); + if (m_bTapEnable) { + tap->GetMacAddr(mac_addr); + mac_addr[5]++; + } + + // 繝代こ繝繝亥女菫。繝輔Λ繧ー繧ェ繝 + packet_enable = FALSE; + + // 繝帙せ繝医ヵ繧。繧、繝ォ繧キ繧ケ繝繝逕滓 + fs = new CFileSys(); + fs->Reset(); +} + +//--------------------------------------------------------------------------- +// +// 繝繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +SCSIBR::~SCSIBR() +{ + // TAP繝峨Λ繧、繝占ァ」謾セ + if (tap) { + tap->Cleanup(); + delete tap; + } + + // 繝帙せ繝医ヵ繧。繧、繝ォ繧キ繧ケ繝繝隗」謾セ + if (fs) { + fs->Reset(); + delete fs; + } +} + +//--------------------------------------------------------------------------- +// +// INQUIRY +// +//--------------------------------------------------------------------------- +int FASTCALL SCSIBR::Inquiry( + const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor) +{ + char rev[32]; + int size; + + ASSERT(this); + ASSERT(cdb); + ASSERT(buf); + ASSERT(cdb[0] == 0x12); + + // EVPD繝√ぉ繝繧ッ + if (cdb[1] & 0x01) { + disk.code = DISK_INVALIDCDB; + return FALSE; + } + + // 蝓コ譛ャ繝繝シ繧ソ + // buf[0] ... Communication Device + // buf[2] ... SCSI-2貅匁侠縺ョ繧ウ繝槭Φ繝我ス鍋ウサ + // buf[3] ... SCSI-2貅匁侠縺ョInquiry繝ャ繧ケ繝昴Φ繧ケ + // buf[4] ... Inquiry霑ス蜉繝繝シ繧ソ + memset(buf, 0, 8); + buf[0] = 0x09; + + // SCSI-2 譛ャ縺ョ p.104 4.4.3 荳榊ス薙↑繝ュ繧ク繧ォ繝ォ繝ヲ繝九ャ繝医ョ蜃ヲ逅 + if (((cdb[1] >> 5) & 0x07) != disk.lun) { + buf[0] = 0x7f; + } + + buf[2] = 0x02; + buf[3] = 0x02; + buf[4] = 36 - 5 + 8; // 蠢鬆 + 8繝舌う繝域僑蠑オ + + // 遨コ逋ス縺ァ蝓九a繧 + memset(&buf[8], 0x20, buf[4] - 3); + + // 繝吶Φ繝 + memcpy(&buf[8], BENDER_SIGNATURE, strlen(BENDER_SIGNATURE)); + + // 陬ス蜩∝錐 + memcpy(&buf[16], "RASCSI BRIDGE", 13); + + // 繝ェ繝薙ず繝ァ繝ウ(XM6縺ョ繝舌シ繧ク繝ァ繝ウNo) + sprintf(rev, "0%01d%01d%01d", + (int)major, (int)(minor >> 4), (int)(minor & 0x0f)); + memcpy(&buf[32], rev, 4); + + // 繧ェ繝励す繝ァ繝ウ讖溯ス譛牙柑繝輔Λ繧ー + buf[36] = '0'; + + // TAP譛牙柑 + if (m_bTapEnable) { + buf[37] = '1'; + } + + // CFileSys譛牙柑 + buf[38] = '1'; + + // 霑泌唆縺ァ縺阪k繝繝シ繧ソ縺ョ繧オ繧、繧コ + size = (buf[4] + 5); + + // 逶ク謇九ョ繝舌ャ繝輔ぃ縺悟ー代↑縺代l縺ー蛻カ髯舌☆繧 + if (size > (int)cdb[4]) { + size = (int)cdb[4]; + } + + // 謌仙粥 + disk.code = DISK_NOERROR; + return size; +} + +//--------------------------------------------------------------------------- +// +// TEST UNIT READY +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSIBR::TestUnitReady(const DWORD* /*cdb*/) +{ + ASSERT(this); + + // TEST UNIT READY謌仙粥 + disk.code = DISK_NOERROR; + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// GET MESSAGE(10) +// +//--------------------------------------------------------------------------- +int FASTCALL SCSIBR::GetMessage10(const DWORD *cdb, BYTE *buf) +{ + int type; + int func; + int phase; + int total_len; + int i; + + ASSERT(this); + + // 繧ソ繧、繝 + type = cdb[2]; + + // 讖溯ス逡ェ蜿キ + func = cdb[3]; + + // 繝輔ぉ繝シ繧コ + phase = cdb[9]; + + switch (type) { + case 1: // 繧、繝シ繧オ繝阪ャ繝 + // TAP辟。蜉ケ縺ェ繧牙ヲ逅縺励↑縺 + if (!m_bTapEnable) { + return 0; + } + + switch (func) { + case 0: // MAC繧「繝峨Ξ繧ケ蜿門セ + return GetMacAddr(buf); + + case 1: // 蜿嶺ソ。繝代こ繝繝亥叙蠕(繧オ繧、繧コ/繝舌ャ繝輔ぃ蛻・) + if (phase == 0) { + // 繝代こ繝繝医し繧、繧コ蜿門セ + ReceivePacket(); + buf[0] = (BYTE)(packet_len >> 8); + buf[1] = (BYTE)packet_len; + return 2; + } else { + // 繝代こ繝繝医ョ繝シ繧ソ蜿門セ + GetPacketBuf(buf); + return packet_len; + } + + case 2: // 蜿嶺ソ。繝代こ繝繝亥叙蠕(繧オ繧、繧コシ九ヰ繝繝輔ぃ蜷梧凾) + ReceivePacket(); + buf[0] = (BYTE)(packet_len >> 8); + buf[1] = (BYTE)packet_len; + GetPacketBuf(&buf[2]); + return packet_len + 2; + + case 3: // 隍謨ー繝代こ繝繝亥酔譎ょ叙蠕(繧オ繧、繧コシ九ヰ繝繝輔ぃ蜷梧凾) + // 繝代こ繝繝域焚縺ョ荳企剞縺ッ迴セ迥カ10蛟九↓豎コ繧∵遠縺。 + // 縺薙l莉・荳雁「励d縺励※繧ゅ≠縺セ繧企溘¥縺ェ繧峨↑縺? + total_len = 0; + for (i = 0; i < 10; i++) { + ReceivePacket(); + *buf++ = (BYTE)(packet_len >> 8); + *buf++ = (BYTE)packet_len; + total_len += 2; + if (packet_len == 0) + break; + GetPacketBuf(buf); + buf += packet_len; + total_len += packet_len; + } + return total_len; + } + break; + + case 2: // 繝帙せ繝医ラ繝ゥ繧、繝 + switch (phase) { + case 0: // 邨先棡繧ウ繝シ繝牙叙蠕 + return ReadFsResult(buf); + + case 1: // 霑泌唆繝繝シ繧ソ蜿門セ + return ReadFsOut(buf); + + case 2: // 霑泌唆霑ス蜉繝繝シ繧ソ蜿門セ + return ReadFsOpt(buf); + } + break; + } + + // 繧ィ繝ゥ繝シ + ASSERT(FALSE); + return 0; +} + +//--------------------------------------------------------------------------- +// +// SEND MESSAGE(10) +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSIBR::SendMessage10(const DWORD *cdb, BYTE *buf) +{ + int type; + int func; + int phase; + int len; + + ASSERT(this); + ASSERT(cdb); + ASSERT(buf); + + // 繧ソ繧、繝 + type = cdb[2]; + + // 讖溯ス逡ェ蜿キ + func = cdb[3]; + + // 繝輔ぉ繝シ繧コ + phase = cdb[9]; + + // 繝ゥ繧、繝域焚繧貞叙蠕 + len = cdb[6]; + len <<= 8; + len |= cdb[7]; + len <<= 8; + len |= cdb[8]; + + switch (type) { + case 1: // 繧、繝シ繧オ繝阪ャ繝 + // TAP辟。蜉ケ縺ェ繧牙ヲ逅縺励↑縺 + if (!m_bTapEnable) { + return FALSE; + } + + switch (func) { + case 0: // MAC繧「繝峨Ξ繧ケ險ュ螳 + SetMacAddr(buf); + return TRUE; + + case 1: // 繝代こ繝繝磯∽ソ。 + SendPacket(buf, len); + return TRUE; + } + break; + + case 2: // 繝帙せ繝医ラ繝ゥ繧、繝 + switch (phase) { + case 0: // 繧ウ繝槭Φ繝臥匱陦 + WriteFs(func, buf); + return TRUE; + + case 1: // 霑ス蜉繝繝シ繧ソ譖ク縺崎セシ縺ソ + WriteFsOpt(buf, len); + return TRUE; + } + break; + } + + // 繧ィ繝ゥ繝シ + ASSERT(FALSE); + return FALSE; +} + +//--------------------------------------------------------------------------- +// +// MAC繧「繝峨Ξ繧ケ蜿門セ +// +//--------------------------------------------------------------------------- +int FASTCALL SCSIBR::GetMacAddr(BYTE *mac) +{ + ASSERT(this); + ASSERT(mac); + + memcpy(mac, mac_addr, 6); + return 6; +} + +//--------------------------------------------------------------------------- +// +// MAC繧「繝峨Ξ繧ケ險ュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::SetMacAddr(BYTE *mac) +{ + ASSERT(this); + ASSERT(mac); + + memcpy(mac_addr, mac, 6); +} + +//--------------------------------------------------------------------------- +// +// 繝代こ繝繝亥女菫。 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::ReceivePacket() +{ + static const BYTE bcast_addr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + BYTE buf[0x1000]; + + ASSERT(this); + ASSERT(tap); + + // 蜑阪ョ繝代こ繝繝医′蜿嶺ソ。縺輔l縺ヲ縺縺ェ縺 + if (packet_enable) { + return; + } + + // 繝代こ繝繝亥女菫。 + packet_len = tap->Rx(packet_buf); + + // 蜿嶺ソ。繝代こ繝繝医°讀懈渊 + if (memcmp(packet_buf, mac_addr, 6) != 0) { + if (memcmp(packet_buf, bcast_addr, 6) != 0) { + packet_len = 0; + return; + } + } + + // 繝舌ャ繝輔ぃ繧オ繧、繧コ繧定カ翫∴縺溘i謐ィ縺ヲ繧 + if (packet_len > 2048) { + packet_len = 0; + return; + } + + // 蜿嶺ソ。繝舌ャ繝輔ぃ縺ォ譬シ邏 + if (packet_len > 0) { + packet_enable = TRUE; + } +} + +//--------------------------------------------------------------------------- +// +// 繝代こ繝繝亥叙蠕 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::GetPacketBuf(BYTE *buf) +{ + int len; + + ASSERT(this); + ASSERT(tap); + ASSERT(buf); + + // 繧オ繧、繧コ蛻カ髯 + len = packet_len; + if (len > 2048) { + len = 2048; + } + + // 繧ウ繝斐シ + memcpy(buf, packet_buf, len); + + // 蜿嶺ソ。貂医∩ + packet_enable = FALSE; +} + +//--------------------------------------------------------------------------- +// +// 繝代こ繝繝磯∽ソ。 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::SendPacket(BYTE *buf, int len) +{ + ASSERT(this); + ASSERT(tap); + ASSERT(buf); + + tap->Tx(buf, len); +} + +//--------------------------------------------------------------------------- +// +// $40 - 繝繝舌う繧ケ襍キ蜍 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_InitDevice(BYTE *buf) +{ + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + fs->Reset(); + fsresult = fs->InitDevice((Human68k::argument_t*)buf); +} + +//--------------------------------------------------------------------------- +// +// $41 - 繝繧」繝ャ繧ッ繝医Μ繝√ぉ繝繧ッ +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_CheckDir(BYTE *buf) +{ + DWORD nUnit; + Human68k::namests_t *pNamests; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + pNamests = (Human68k::namests_t*)&buf[i]; + i += sizeof(Human68k::namests_t); + + fsresult = fs->CheckDir(nUnit, pNamests); +} + +//--------------------------------------------------------------------------- +// +// $42 - 繝繧」繝ャ繧ッ繝医Μ菴懈 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_MakeDir(BYTE *buf) +{ + DWORD nUnit; + Human68k::namests_t *pNamests; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + pNamests = (Human68k::namests_t*)&buf[i]; + i += sizeof(Human68k::namests_t); + + fsresult = fs->MakeDir(nUnit, pNamests); +} + +//--------------------------------------------------------------------------- +// +// $43 - 繝繧」繝ャ繧ッ繝医Μ蜑企勁 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_RemoveDir(BYTE *buf) +{ + DWORD nUnit; + Human68k::namests_t *pNamests; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + pNamests = (Human68k::namests_t*)&buf[i]; + i += sizeof(Human68k::namests_t); + + fsresult = fs->RemoveDir(nUnit, pNamests); +} + +//--------------------------------------------------------------------------- +// +// $44 - 繝輔ぃ繧、繝ォ蜷榊、画峩 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_Rename(BYTE *buf) +{ + DWORD nUnit; + Human68k::namests_t *pNamests; + Human68k::namests_t* pNamestsNew; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + pNamests = (Human68k::namests_t*)&buf[i]; + i += sizeof(Human68k::namests_t); + + pNamestsNew = (Human68k::namests_t*)&buf[i]; + i += sizeof(Human68k::namests_t); + + fsresult = fs->Rename(nUnit, pNamests, pNamestsNew); +} + +//--------------------------------------------------------------------------- +// +// $45 - 繝輔ぃ繧、繝ォ蜑企勁 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_Delete(BYTE *buf) +{ + DWORD nUnit; + Human68k::namests_t *pNamests; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + pNamests = (Human68k::namests_t*)&buf[i]; + i += sizeof(Human68k::namests_t); + + fsresult = fs->Delete(nUnit, pNamests); +} + +//--------------------------------------------------------------------------- +// +// $46 - 繝輔ぃ繧、繝ォ螻樊ァ蜿門セ/險ュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_Attribute(BYTE *buf) +{ + DWORD nUnit; + Human68k::namests_t *pNamests; + DWORD nHumanAttribute; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + pNamests = (Human68k::namests_t*)&buf[i]; + i += sizeof(Human68k::namests_t); + + dp = (DWORD*)&buf[i]; + nHumanAttribute = ntohl(*dp); + i += sizeof(DWORD); + + fsresult = fs->Attribute(nUnit, pNamests, nHumanAttribute); +} + +//--------------------------------------------------------------------------- +// +// $47 - 繝輔ぃ繧、繝ォ讀懃エ「 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_Files(BYTE *buf) +{ + DWORD nUnit; + DWORD nKey; + Human68k::namests_t *pNamests; + Human68k::files_t *files; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + nKey = ntohl(*dp); + i += sizeof(DWORD); + + pNamests = (Human68k::namests_t*)&buf[i]; + i += sizeof(Human68k::namests_t); + + files = (Human68k::files_t*)&buf[i]; + i += sizeof(Human68k::files_t); + + files->sector = ntohl(files->sector); + files->offset = ntohs(files->offset); + files->time = ntohs(files->time); + files->date = ntohs(files->date); + files->size = ntohl(files->size); + + fsresult = fs->Files(nUnit, nKey, pNamests, files); + + files->sector = htonl(files->sector); + files->offset = htons(files->offset); + files->time = htons(files->time); + files->date = htons(files->date); + files->size = htonl(files->size); + + i = 0; + memcpy(&fsout[i], files, sizeof(Human68k::files_t)); + i += sizeof(Human68k::files_t); + + fsoutlen = i; +} + +//--------------------------------------------------------------------------- +// +// $48 - 繝輔ぃ繧、繝ォ谺。讀懃エ「 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_NFiles(BYTE *buf) +{ + DWORD nUnit; + DWORD nKey; + Human68k::files_t *files; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + nKey = ntohl(*dp); + i += sizeof(DWORD); + + files = (Human68k::files_t*)&buf[i]; + i += sizeof(Human68k::files_t); + + files->sector = ntohl(files->sector); + files->offset = ntohs(files->offset); + files->time = ntohs(files->time); + files->date = ntohs(files->date); + files->size = ntohl(files->size); + + fsresult = fs->NFiles(nUnit, nKey, files); + + files->sector = htonl(files->sector); + files->offset = htons(files->offset); + files->time = htons(files->time); + files->date = htons(files->date); + files->size = htonl(files->size); + + i = 0; + memcpy(&fsout[i], files, sizeof(Human68k::files_t)); + i += sizeof(Human68k::files_t); + + fsoutlen = i; +} + +//--------------------------------------------------------------------------- +// +// $49 - 繝輔ぃ繧、繝ォ菴懈 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_Create(BYTE *buf) +{ + DWORD nUnit; + DWORD nKey; + Human68k::namests_t *pNamests; + Human68k::fcb_t *pFcb; + DWORD nAttribute; + BOOL bForce; + DWORD *dp; + BOOL *bp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + nKey = ntohl(*dp); + i += sizeof(DWORD); + + pNamests = (Human68k::namests_t*)&buf[i]; + i += sizeof(Human68k::namests_t); + + pFcb = (Human68k::fcb_t*)&buf[i]; + i += sizeof(Human68k::fcb_t); + + dp = (DWORD*)&buf[i]; + nAttribute = ntohl(*dp); + i += sizeof(DWORD); + + bp = (BOOL*)&buf[i]; + bForce = ntohl(*bp); + i += sizeof(BOOL); + + pFcb->fileptr = ntohl(pFcb->fileptr); + pFcb->mode = ntohs(pFcb->mode); + pFcb->time = ntohs(pFcb->time); + pFcb->date = ntohs(pFcb->date); + pFcb->size = ntohl(pFcb->size); + + fsresult = fs->Create(nUnit, nKey, pNamests, pFcb, nAttribute, bForce); + + pFcb->fileptr = htonl(pFcb->fileptr); + pFcb->mode = htons(pFcb->mode); + pFcb->time = htons(pFcb->time); + pFcb->date = htons(pFcb->date); + pFcb->size = htonl(pFcb->size); + + i = 0; + memcpy(&fsout[i], pFcb, sizeof(Human68k::fcb_t)); + i += sizeof(Human68k::fcb_t); + + fsoutlen = i; +} + +//--------------------------------------------------------------------------- +// +// $4A - 繝輔ぃ繧、繝ォ繧ェ繝シ繝励Φ +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_Open(BYTE *buf) +{ + DWORD nUnit; + DWORD nKey; + Human68k::namests_t *pNamests; + Human68k::fcb_t *pFcb; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + nKey = ntohl(*dp); + i += sizeof(DWORD); + + pNamests = (Human68k::namests_t*)&buf[i]; + i += sizeof(Human68k::namests_t); + + pFcb = (Human68k::fcb_t*)&buf[i]; + i += sizeof(Human68k::fcb_t); + + pFcb->fileptr = ntohl(pFcb->fileptr); + pFcb->mode = ntohs(pFcb->mode); + pFcb->time = ntohs(pFcb->time); + pFcb->date = ntohs(pFcb->date); + pFcb->size = ntohl(pFcb->size); + + fsresult = fs->Open(nUnit, nKey, pNamests, pFcb); + + pFcb->fileptr = htonl(pFcb->fileptr); + pFcb->mode = htons(pFcb->mode); + pFcb->time = htons(pFcb->time); + pFcb->date = htons(pFcb->date); + pFcb->size = htonl(pFcb->size); + + i = 0; + memcpy(&fsout[i], pFcb, sizeof(Human68k::fcb_t)); + i += sizeof(Human68k::fcb_t); + + fsoutlen = i; +} + +//--------------------------------------------------------------------------- +// +// $4B - 繝輔ぃ繧、繝ォ繧ッ繝ュ繝シ繧コ +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_Close(BYTE *buf) +{ + DWORD nUnit; + DWORD nKey; + Human68k::fcb_t *pFcb; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + nKey = ntohl(*dp); + i += sizeof(DWORD); + + pFcb = (Human68k::fcb_t*)&buf[i]; + i += sizeof(Human68k::fcb_t); + + pFcb->fileptr = ntohl(pFcb->fileptr); + pFcb->mode = ntohs(pFcb->mode); + pFcb->time = ntohs(pFcb->time); + pFcb->date = ntohs(pFcb->date); + pFcb->size = ntohl(pFcb->size); + + fsresult = fs->Close(nUnit, nKey, pFcb); + + pFcb->fileptr = htonl(pFcb->fileptr); + pFcb->mode = htons(pFcb->mode); + pFcb->time = htons(pFcb->time); + pFcb->date = htons(pFcb->date); + pFcb->size = htonl(pFcb->size); + + i = 0; + memcpy(&fsout[i], pFcb, sizeof(Human68k::fcb_t)); + i += sizeof(Human68k::fcb_t); + + fsoutlen = i; +} + +//--------------------------------------------------------------------------- +// +// $4C - 繝輔ぃ繧、繝ォ隱ュ縺ソ霎シ縺ソ +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_Read(BYTE *buf) +{ + DWORD nKey; + Human68k::fcb_t *pFcb; + DWORD nSize; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nKey = ntohl(*dp); + i += sizeof(DWORD); + + pFcb = (Human68k::fcb_t*)&buf[i]; + i += sizeof(Human68k::fcb_t); + + dp = (DWORD*)&buf[i]; + nSize = ntohl(*dp); + i += sizeof(DWORD); + + pFcb->fileptr = ntohl(pFcb->fileptr); + pFcb->mode = ntohs(pFcb->mode); + pFcb->time = ntohs(pFcb->time); + pFcb->date = ntohs(pFcb->date); + pFcb->size = ntohl(pFcb->size); + + fsresult = fs->Read(nKey, pFcb, fsopt, nSize); + + pFcb->fileptr = htonl(pFcb->fileptr); + pFcb->mode = htons(pFcb->mode); + pFcb->time = htons(pFcb->time); + pFcb->date = htons(pFcb->date); + pFcb->size = htonl(pFcb->size); + + i = 0; + memcpy(&fsout[i], pFcb, sizeof(Human68k::fcb_t)); + i += sizeof(Human68k::fcb_t); + + fsoutlen = i; + + fsoptlen = fsresult; +} + +//--------------------------------------------------------------------------- +// +// $4D - 繝輔ぃ繧、繝ォ譖ク縺崎セシ縺ソ +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_Write(BYTE *buf) +{ + DWORD nKey; + Human68k::fcb_t *pFcb; + DWORD nSize; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nKey = ntohl(*dp); + i += sizeof(DWORD); + + pFcb = (Human68k::fcb_t*)&buf[i]; + i += sizeof(Human68k::fcb_t); + + dp = (DWORD*)&buf[i]; + nSize = ntohl(*dp); + i += sizeof(DWORD); + + pFcb->fileptr = ntohl(pFcb->fileptr); + pFcb->mode = ntohs(pFcb->mode); + pFcb->time = ntohs(pFcb->time); + pFcb->date = ntohs(pFcb->date); + pFcb->size = ntohl(pFcb->size); + + fsresult = fs->Write(nKey, pFcb, fsopt, nSize); + + pFcb->fileptr = htonl(pFcb->fileptr); + pFcb->mode = htons(pFcb->mode); + pFcb->time = htons(pFcb->time); + pFcb->date = htons(pFcb->date); + pFcb->size = htonl(pFcb->size); + + i = 0; + memcpy(&fsout[i], pFcb, sizeof(Human68k::fcb_t)); + i += sizeof(Human68k::fcb_t); + + fsoutlen = i; +} + +//--------------------------------------------------------------------------- +// +// $4E - 繝輔ぃ繧、繝ォ繧キ繝シ繧ッ +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_Seek(BYTE *buf) +{ + DWORD nKey; + Human68k::fcb_t *pFcb; + DWORD nMode; + int nOffset; + DWORD *dp; + int *ip; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nKey = ntohl(*dp); + i += sizeof(DWORD); + + pFcb = (Human68k::fcb_t*)&buf[i]; + i += sizeof(Human68k::fcb_t); + + dp = (DWORD*)&buf[i]; + nMode = ntohl(*dp); + i += sizeof(DWORD); + + ip = (int*)&buf[i]; + nOffset = ntohl(*ip); + i += sizeof(int); + + pFcb->fileptr = ntohl(pFcb->fileptr); + pFcb->mode = ntohs(pFcb->mode); + pFcb->time = ntohs(pFcb->time); + pFcb->date = ntohs(pFcb->date); + pFcb->size = ntohl(pFcb->size); + + fsresult = fs->Seek(nKey, pFcb, nMode, nOffset); + + pFcb->fileptr = htonl(pFcb->fileptr); + pFcb->mode = htons(pFcb->mode); + pFcb->time = htons(pFcb->time); + pFcb->date = htons(pFcb->date); + pFcb->size = htonl(pFcb->size); + + i = 0; + memcpy(&fsout[i], pFcb, sizeof(Human68k::fcb_t)); + i += sizeof(Human68k::fcb_t); + + fsoutlen = i; +} + +//--------------------------------------------------------------------------- +// +// $4F - 繝輔ぃ繧、繝ォ譎ょ綾蜿門セ/險ュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_TimeStamp(BYTE *buf) +{ + DWORD nUnit; + DWORD nKey; + Human68k::fcb_t *pFcb; + DWORD nHumanTime; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + nKey = ntohl(*dp); + i += sizeof(DWORD); + + pFcb = (Human68k::fcb_t*)&buf[i]; + i += sizeof(Human68k::fcb_t); + + dp = (DWORD*)&buf[i]; + nHumanTime = ntohl(*dp); + i += sizeof(DWORD); + + pFcb->fileptr = ntohl(pFcb->fileptr); + pFcb->mode = ntohs(pFcb->mode); + pFcb->time = ntohs(pFcb->time); + pFcb->date = ntohs(pFcb->date); + pFcb->size = ntohl(pFcb->size); + + fsresult = fs->TimeStamp(nUnit, nKey, pFcb, nHumanTime); + + pFcb->fileptr = htonl(pFcb->fileptr); + pFcb->mode = htons(pFcb->mode); + pFcb->time = htons(pFcb->time); + pFcb->date = htons(pFcb->date); + pFcb->size = htonl(pFcb->size); + + i = 0; + memcpy(&fsout[i], pFcb, sizeof(Human68k::fcb_t)); + i += sizeof(Human68k::fcb_t); + + fsoutlen = i; +} + +//--------------------------------------------------------------------------- +// +// $50 - 螳ケ驥丞叙蠕 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_GetCapacity(BYTE *buf) +{ + DWORD nUnit; + Human68k::capacity_t cap; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + fsresult = fs->GetCapacity(nUnit, &cap); + + cap.freearea = htons(cap.freearea); + cap.clusters = htons(cap.clusters); + cap.sectors = htons(cap.sectors); + cap.bytes = htons(cap.bytes); + + memcpy(fsout, &cap, sizeof(Human68k::capacity_t)); + fsoutlen = sizeof(Human68k::capacity_t); +} + +//--------------------------------------------------------------------------- +// +// $51 - 繝峨Λ繧、繝也憾諷区、懈渊/蛻カ蠕。 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_CtrlDrive(BYTE *buf) +{ + DWORD nUnit; + Human68k::ctrldrive_t *pCtrlDrive; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + pCtrlDrive = (Human68k::ctrldrive_t*)&buf[i]; + i += sizeof(Human68k::ctrldrive_t); + + fsresult = fs->CtrlDrive(nUnit, pCtrlDrive); + + memcpy(fsout, pCtrlDrive, sizeof(Human68k::ctrldrive_t)); + fsoutlen = sizeof(Human68k::ctrldrive_t); +} + +//--------------------------------------------------------------------------- +// +// $52 - DPB蜿門セ +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_GetDPB(BYTE *buf) +{ + DWORD nUnit; + Human68k::dpb_t dpb; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + fsresult = fs->GetDPB(nUnit, &dpb); + + dpb.sector_size = htons(dpb.sector_size); + dpb.fat_sector = htons(dpb.fat_sector); + dpb.file_max = htons(dpb.file_max); + dpb.data_sector = htons(dpb.data_sector); + dpb.cluster_max = htons(dpb.cluster_max); + dpb.root_sector = htons(dpb.root_sector); + + memcpy(fsout, &dpb, sizeof(Human68k::dpb_t)); + fsoutlen = sizeof(Human68k::dpb_t); +} + +//--------------------------------------------------------------------------- +// +// $53 - 繧サ繧ッ繧ソ隱ュ縺ソ霎シ縺ソ +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_DiskRead(BYTE *buf) +{ + DWORD nUnit; + DWORD nSector; + DWORD nSize; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + nSector = ntohl(*dp); + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + nSize = ntohl(*dp); + i += sizeof(DWORD); + + fsresult = fs->DiskRead(nUnit, fsout, nSector, nSize); + fsoutlen = 0x200; +} + +//--------------------------------------------------------------------------- +// +// $54 - 繧サ繧ッ繧ソ譖ク縺崎セシ縺ソ +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_DiskWrite(BYTE *buf) +{ + DWORD nUnit; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + fsresult = fs->DiskWrite(nUnit); +} + +//--------------------------------------------------------------------------- +// +// $55 - IOCTRL +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_Ioctrl(BYTE *buf) +{ + DWORD nUnit; + DWORD nFunction; + Human68k::ioctrl_t *pIoctrl; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + nFunction = ntohl(*dp); + i += sizeof(DWORD); + + pIoctrl = (Human68k::ioctrl_t*)&buf[i]; + i += sizeof(Human68k::ioctrl_t); + + switch (nFunction) { + case 2: + case -2: + pIoctrl->param = htonl(pIoctrl->param); + break; + } + + fsresult = fs->Ioctrl(nUnit, nFunction, pIoctrl); + + switch (nFunction) { + case 0: + pIoctrl->media = htons(pIoctrl->media); + break; + case 1: + case -3: + pIoctrl->param = htonl(pIoctrl->param); + break; + } + + i = 0; + memcpy(&fsout[i], pIoctrl, sizeof(Human68k::ioctrl_t)); + i += sizeof(Human68k::ioctrl_t); + fsoutlen = i; +} + +//--------------------------------------------------------------------------- +// +// $56 - 繝輔Λ繝繧キ繝・ +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_Flush(BYTE *buf) +{ + DWORD nUnit; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + fsresult = fs->Flush(nUnit); +} + +//--------------------------------------------------------------------------- +// +// $57 - 繝。繝繧」繧「莠、謠帙メ繧ァ繝繧ッ +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_CheckMedia(BYTE *buf) +{ + DWORD nUnit; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + fsresult = fs->CheckMedia(nUnit); +} + +//--------------------------------------------------------------------------- +// +// $58 - 謗剃サ門宛蠕。 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_Lock(BYTE *buf) +{ + DWORD nUnit; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + fsresult = fs->Lock(nUnit); +} + +//--------------------------------------------------------------------------- +// +// 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝隱ュ縺ソ霎シ縺ソ(邨先棡繧ウ繝シ繝) +// +//--------------------------------------------------------------------------- +int FASTCALL SCSIBR::ReadFsResult(BYTE *buf) +{ + DWORD *dp; + + ASSERT(this); + ASSERT(buf); + + dp = (DWORD*)buf; + *dp = htonl(fsresult); + return sizeof(DWORD); +} + +//--------------------------------------------------------------------------- +// +// 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝隱ュ縺ソ霎シ縺ソ(霑泌唆繝繝シ繧ソ) +// +//--------------------------------------------------------------------------- +int FASTCALL SCSIBR::ReadFsOut(BYTE *buf) +{ + ASSERT(this); + ASSERT(buf); + + memcpy(buf, fsout, fsoutlen); + return fsoutlen; +} + +//--------------------------------------------------------------------------- +// +// 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝隱ュ縺ソ霎シ縺ソ(霑泌唆繧ェ繝励す繝ァ繝ウ繝繝シ繧ソ) +// +//--------------------------------------------------------------------------- +int FASTCALL SCSIBR::ReadFsOpt(BYTE *buf) +{ + ASSERT(this); + ASSERT(buf); + + memcpy(buf, fsopt, fsoptlen); + return fsoptlen; +} + +//--------------------------------------------------------------------------- +// +// 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝譖ク縺崎セシ縺ソ +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::WriteFs(int func, BYTE *buf) +{ + ASSERT(this); + ASSERT(buf); + + fsresult = FS_FATAL_INVALIDCOMMAND; + fsoutlen = 0; + fsoptlen = 0; + + // 繧ウ繝槭Φ繝牙蟯 + func &= 0x1f; + switch (func) { + case 0x00: return FS_InitDevice(buf); // $40 - 繝繝舌う繧ケ襍キ蜍 + case 0x01: return FS_CheckDir(buf); // $41 - 繝繧」繝ャ繧ッ繝医Μ繝√ぉ繝繧ッ + case 0x02: return FS_MakeDir(buf); // $42 - 繝繧」繝ャ繧ッ繝医Μ菴懈 + case 0x03: return FS_RemoveDir(buf); // $43 - 繝繧」繝ャ繧ッ繝医Μ蜑企勁 + case 0x04: return FS_Rename(buf); // $44 - 繝輔ぃ繧、繝ォ蜷榊、画峩 + case 0x05: return FS_Delete(buf); // $45 - 繝輔ぃ繧、繝ォ蜑企勁 + case 0x06: return FS_Attribute(buf); // $46 - 繝輔ぃ繧、繝ォ螻樊ァ蜿門セ/險ュ螳 + case 0x07: return FS_Files(buf); // $47 - 繝輔ぃ繧、繝ォ讀懃エ「 + case 0x08: return FS_NFiles(buf); // $48 - 繝輔ぃ繧、繝ォ谺。讀懃エ「 + case 0x09: return FS_Create(buf); // $49 - 繝輔ぃ繧、繝ォ菴懈 + case 0x0A: return FS_Open(buf); // $4A - 繝輔ぃ繧、繝ォ繧ェ繝シ繝励Φ + case 0x0B: return FS_Close(buf); // $4B - 繝輔ぃ繧、繝ォ繧ッ繝ュ繝シ繧コ + case 0x0C: return FS_Read(buf); // $4C - 繝輔ぃ繧、繝ォ隱ュ縺ソ霎シ縺ソ + case 0x0D: return FS_Write(buf); // $4D - 繝輔ぃ繧、繝ォ譖ク縺崎セシ縺ソ + case 0x0E: return FS_Seek(buf); // $4E - 繝輔ぃ繧、繝ォ繧キ繝シ繧ッ + case 0x0F: return FS_TimeStamp(buf); // $4F - 繝輔ぃ繧、繝ォ譖エ譁ー譎ょ綾縺ョ蜿門セ/險ュ螳 + case 0x10: return FS_GetCapacity(buf); // $50 - 螳ケ驥丞叙蠕 + case 0x11: return FS_CtrlDrive(buf); // $51 - 繝峨Λ繧、繝門宛蠕。/迥カ諷区、懈渊 + case 0x12: return FS_GetDPB(buf); // $52 - DPB蜿門セ + case 0x13: return FS_DiskRead(buf); // $53 - 繧サ繧ッ繧ソ隱ュ縺ソ霎シ縺ソ + case 0x14: return FS_DiskWrite(buf); // $54 - 繧サ繧ッ繧ソ譖ク縺崎セシ縺ソ + case 0x15: return FS_Ioctrl(buf); // $55 - IOCTRL + case 0x16: return FS_Flush(buf); // $56 - 繝輔Λ繝繧キ繝・ + case 0x17: return FS_CheckMedia(buf); // $57 - 繝。繝繧」繧「莠、謠帙メ繧ァ繝繧ッ + case 0x18: return FS_Lock(buf); // $58 - 謗剃サ門宛蠕。 + } +} + +//--------------------------------------------------------------------------- +// +// 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝譖ク縺崎セシ縺ソ(蜈・蜉帙が繝励す繝ァ繝ウ繝繝シ繧ソ) +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::WriteFsOpt(BYTE *buf, int num) +{ + ASSERT(this); + + memcpy(fsopt, buf, num); +} + +//=========================================================================== +// +// SASI 繝繝舌う繧ケ +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +#ifdef RASCSI +SASIDEV::SASIDEV() +#else +SASIDEV::SASIDEV(Device *dev) +#endif // RASCSI +{ + int i; + +#ifndef RASCSI + // 繝帙せ繝医ョ繝舌う繧ケ繧定ィ俶カ + host = dev; +#endif // RASCSI + + // 繝ッ繝シ繧ッ蛻晄悄蛹 + ctrl.phase = BUS::busfree; + ctrl.id = -1; + ctrl.bus = NULL; + memset(ctrl.cmd, 0x00, sizeof(ctrl.cmd)); + ctrl.status = 0x00; + ctrl.message = 0x00; + ctrl.bufsize = 0x800; + ctrl.buffer = new BYTE[ctrl.bufsize]; + memset(ctrl.buffer, 0x00, ctrl.bufsize); + ctrl.blocks = 0; + ctrl.next = 0; + ctrl.offset = 0; + ctrl.length = 0; + + // 隲也炊繝ヲ繝九ャ繝亥晄悄蛹 + for (i = 0; i < UnitMax; i++) { + ctrl.unit[i] = NULL; + } +} + +//--------------------------------------------------------------------------- +// +// 繝繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +SASIDEV::~SASIDEV() +{ + // 繝舌ャ繝輔ぃ繧帝幕謾セ + if (ctrl.buffer) { + delete ctrl.buffer; + ctrl.buffer = NULL; + } +} + +//--------------------------------------------------------------------------- +// +// 繝繝舌う繧ケ繝ェ繧サ繝繝 +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::Reset() +{ + int i; + + ASSERT(this); + + // 繝ッ繝シ繧ッ蛻晄悄蛹 + memset(ctrl.cmd, 0x00, sizeof(ctrl.cmd)); + ctrl.phase = BUS::busfree; + ctrl.status = 0x00; + ctrl.message = 0x00; + memset(ctrl.buffer, 0x00, ctrl.bufsize); + ctrl.blocks = 0; + ctrl.next = 0; + ctrl.offset = 0; + ctrl.length = 0; + + // 繝ヲ繝九ャ繝亥晄悄蛹 + for (i = 0; i < UnitMax; i++) { + if (ctrl.unit[i]) { + ctrl.unit[i]->Reset(); + } + } +} + +#ifndef RASCSI +//--------------------------------------------------------------------------- +// +// 繧サ繝シ繝 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SASIDEV::Save(Fileio *fio, int /*ver*/) +{ + DWORD sz; + + ASSERT(this); + ASSERT(fio); + + // 繧オ繧、繧コ繧偵そ繝シ繝 + sz = 2120; + if (!fio->Write(&sz, sizeof(sz))) { + return FALSE; + } + + // 螳滉ス薙r繧サ繝シ繝 + PROP_EXPORT(fio, ctrl.phase); + PROP_EXPORT(fio, ctrl.id); + PROP_EXPORT(fio, ctrl.cmd); + PROP_EXPORT(fio, ctrl.status); + PROP_EXPORT(fio, ctrl.message); + if (!fio->Write(ctrl.buffer, 0x800)) { + return FALSE; + } + PROP_EXPORT(fio, ctrl.blocks); + PROP_EXPORT(fio, ctrl.next); + PROP_EXPORT(fio, ctrl.offset); + PROP_EXPORT(fio, ctrl.length); + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繝ュ繝シ繝 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SASIDEV::Load(Fileio *fio, int ver) +{ + DWORD sz; + + ASSERT(this); + ASSERT(fio); + + // version3.11繧医j蜑阪ッ繧サ繝シ繝悶@縺ヲ縺縺ェ縺 + if (ver <= 0x0311) { + return TRUE; + } + + // 繧オ繧、繧コ繧偵Ο繝シ繝峨∫ァ蜷 + if (!fio->Read(&sz, sizeof(sz))) { + return FALSE; + } + if (sz != 2120) { + return FALSE; + } + + // 螳滉ス薙r繝ュ繝シ繝 + PROP_IMPORT(fio, ctrl.phase); + PROP_IMPORT(fio, ctrl.id); + PROP_IMPORT(fio, ctrl.cmd); + PROP_IMPORT(fio, ctrl.status); + PROP_IMPORT(fio, ctrl.message); + if (!fio->Read(ctrl.buffer, 0x800)) { + return FALSE; + } + PROP_IMPORT(fio, ctrl.blocks); + PROP_IMPORT(fio, ctrl.next); + PROP_IMPORT(fio, ctrl.offset); + PROP_IMPORT(fio, ctrl.length); + + return TRUE; +} +#endif // RASCSI + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繝医Ο繝シ繝ゥ謗・邯 +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::Connect(int id, BUS *bus) +{ + ASSERT(this); + + ctrl.id = id; + ctrl.bus = bus; +} + +//--------------------------------------------------------------------------- +// +// 隲也炊繝ヲ繝九ャ繝亥叙蠕 +// +//--------------------------------------------------------------------------- +Disk* FASTCALL SASIDEV::GetUnit(int no) +{ + ASSERT(this); + ASSERT(no < UnitMax); + + return ctrl.unit[no]; +} + +//--------------------------------------------------------------------------- +// +// 隲也炊繝ヲ繝九ャ繝郁ィュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::SetUnit(int no, Disk *dev) +{ + ASSERT(this); + ASSERT(no < UnitMax); + + ctrl.unit[no] = dev; +} + +//--------------------------------------------------------------------------- +// +// 譛牙柑縺ェ隲也炊繝ヲ繝九ャ繝医r謖√▲縺ヲ縺繧九°霑斐☆ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SASIDEV::HasUnit() +{ + int i; + + ASSERT(this); + + for (i = 0; i < UnitMax; i++) { + if (ctrl.unit[i]) { + return TRUE; + } + } + + return FALSE; +} + +//--------------------------------------------------------------------------- +// +// 蜀驛ィ繝繝シ繧ソ蜿門セ +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::GetCTRL(ctrl_t *buffer) +{ + ASSERT(this); + ASSERT(buffer); + + // 蜀驛ィ繝ッ繝シ繧ッ繧偵さ繝斐シ + *buffer = ctrl; +} + +//--------------------------------------------------------------------------- +// +// 繝薙ず繝シ迥カ諷九ョ繝ヲ繝九ャ繝医r蜿門セ +// +//--------------------------------------------------------------------------- +Disk* FASTCALL SASIDEV::GetBusyUnit() +{ + DWORD lun; + + ASSERT(this); + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + return ctrl.unit[lun]; +} + +//--------------------------------------------------------------------------- +// +// 螳溯。 +// +//--------------------------------------------------------------------------- +BUS::phase_t FASTCALL SASIDEV::Process() +{ + ASSERT(this); + + // 譛ェ謗・邯壹↑繧我ス輔b縺励↑縺 + if (ctrl.id < 0 || ctrl.bus == NULL) { + return ctrl.phase; + } + + // 繝舌せ諠蝣ア縺ョ蜿悶j霎シ縺ソ + ctrl.bus->Aquire(); + + // 繝ェ繧サ繝繝 + if (ctrl.bus->GetRST()) { +#if defined(DISK_LOG) + Log(Log::Normal, "RESET菫。蜿キ蜿嶺ソ。"); +#endif // DISK_LOG + + // 繧ウ繝ウ繝医Ο繝シ繝ゥ繧偵Μ繧サ繝繝 + Reset(); + + // 繝舌せ繧ゅΜ繧サ繝繝 + ctrl.bus->Reset(); + return ctrl.phase; + } + + // 繝輔ぉ繝シ繧コ蜃ヲ逅 + switch (ctrl.phase) { + // 繝舌せ繝輔Μ繝シ + case BUS::busfree: + BusFree(); + break; + + // 繧サ繝ャ繧ッ繧キ繝ァ繝ウ + case BUS::selection: + Selection(); + break; + + // 繝繝シ繧ソ繧「繧ヲ繝(MCI=000) + case BUS::dataout: + DataOut(); + break; + + // 繝繝シ繧ソ繧、繝ウ(MCI=001) + case BUS::datain: + DataIn(); + break; + + // 繧ウ繝槭Φ繝(MCI=010) + case BUS::command: + Command(); + break; + + // 繧ケ繝繝シ繧ソ繧ケ(MCI=011) + case BUS::status: + Status(); + break; + + // 繝。繝繧サ繝シ繧ク繧、繝ウ(MCI=111) + case BUS::msgin: + MsgIn(); + break; + + // 縺昴ョ莉 + default: + ASSERT(FALSE); + break; + } + + return ctrl.phase; +} + +//--------------------------------------------------------------------------- +// +// 繝舌せ繝輔Μ繝シ繝輔ぉ繝シ繧コ +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::BusFree() +{ + ASSERT(this); + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク + if (ctrl.phase != BUS::busfree) { + +#if defined(DISK_LOG) + Log(Log::Normal, "繝舌せ繝輔Μ繝シ繝輔ぉ繝シ繧コ"); +#endif // DISK_LOG + + // 繝輔ぉ繝シ繧コ險ュ螳 + ctrl.phase = BUS::busfree; + + // 菫。蜿キ邱 + ctrl.bus->SetBSY(FALSE); + ctrl.bus->SetMSG(FALSE); + ctrl.bus->SetCD(FALSE); + ctrl.bus->SetIO(FALSE); + ctrl.bus->SetREQ(FALSE); + + // 繧ケ繝繝シ繧ソ繧ケ縺ィ繝。繝繧サ繝シ繧ク繧貞晄悄蛹 + ctrl.status = 0x00; + ctrl.message = 0x00; + + // 繝舌せ繧ッ繝ェ繧「繝繧」繝ャ繧、 + ctrl.bus->SleepNsec(Time_phase_bsy); + return; + } + + // 繧サ繝ャ繧ッ繧キ繝ァ繝ウ繝輔ぉ繝シ繧コ縺ォ遘サ陦 + if (ctrl.bus->GetSEL() && !ctrl.bus->GetBSY()) { + Selection(); + } +} + +//--------------------------------------------------------------------------- +// +// 繧サ繝ャ繧ッ繧キ繝ァ繝ウ繝輔ぉ繝シ繧コ +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::Selection() +{ + DWORD id; + + ASSERT(this); + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク + if (ctrl.phase != BUS::selection) { + // ID縺御ク閾エ縺励※縺縺ェ縺代l縺ー辟。蜉ケ + id = 1 << ctrl.id; + if ((ctrl.bus->GetDAT() & id) == 0) { + return; + } + + // 譛牙柑縺ェ繝ヲ繝九ャ繝医′辟。縺代l縺ー邨ゆコ + if (!HasUnit()) { + return; + } + +#if defined(DISK_LOG) + Log(Log::Normal, "繧サ繝ャ繧ッ繧キ繝ァ繝ウ繝輔ぉ繝シ繧コ ID=%d (繝繝舌う繧ケ縺ゅj)", ctrl.id); +#endif // DISK_LOG + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク + ctrl.phase = BUS::selection; + + // BSY繧剃ク翫£縺ヲ蠢懃ュ + ctrl.bus->SetBSY(TRUE); + return; + } + + // 繧サ繝ャ繧ッ繧キ繝ァ繝ウ螳御コ縺ァ繧ウ繝槭Φ繝峨ヵ繧ァ繝シ繧コ遘サ陦 + if (!ctrl.bus->GetSEL() && ctrl.bus->GetBSY()) { + Command(); + } +} + +//--------------------------------------------------------------------------- +// +// 繧ウ繝槭Φ繝峨ヵ繧ァ繝シ繧コ +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::Command() +{ + BYTE data; + int count; + ASSERT(this); + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク + if (ctrl.phase != BUS::command) { + +#if defined(DISK_LOG) + Log(Log::Normal, "繧ウ繝槭Φ繝峨ヵ繧ァ繝シ繧コ"); +#endif // DISK_LOG + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク蜑阪ョ繧ヲ繧ァ繧、繝 + ctrl.bus->SleepNsec(Time_phase_before); + + // 繝輔ぉ繝シ繧コ險ュ螳 + ctrl.phase = BUS::command; + + // 繧ソ繝シ繧イ繝繝医′謫堺ス懊☆繧倶ソ。蜿キ邱 + ctrl.bus->SetMSG(FALSE); + ctrl.bus->SetCD(TRUE); + ctrl.bus->SetIO(FALSE); + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク蠕後ョ莠亥相譎る俣 + ctrl.bus->SleepNsec(Time_phase_after); + + // 繝繝シ繧ソ霆「騾√ッ6繝舌う繝x1繝悶Ο繝繧ッ + ctrl.offset = 0; + ctrl.length = 6; + ctrl.blocks = 1; + + // 譛蛻昴ョ1繝舌う繝医r蜿門セ(蜻ス莉、髟キ險育ョ励ョ縺溘a) + count = ctrl.bus->ReceiveHandShake(&data, 1); + ctrl.buffer[ctrl.offset] = data; + + // 繝ェ繧カ繝ォ繝FALSE縺ェ繧峨√せ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ縺ク遘サ陦 + if (count != 1) { + Error(); + return; + } + + if (ctrl.buffer[0] >= 0x20 && ctrl.buffer[0] <= 0x7D) { + // 10繝舌う繝CDB + ctrl.length = 10; + } + + // 繧ェ繝輔そ繝繝医→繝ャ繝ウ繧ー繧ケ + ctrl.offset++; + ctrl.length--; + return; + } + + // 蜿嶺ソ。 + Receive(); +} + +//--------------------------------------------------------------------------- +// +// 螳溯。後ヵ繧ァ繝シ繧コ +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::Execute() +{ + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "螳溯。後ヵ繧ァ繝シ繧コ 繧ウ繝槭Φ繝$%02X", ctrl.cmd[0]); +#endif // DISK_LOG + + // 繝輔ぉ繝シ繧コ險ュ螳 + ctrl.phase = BUS::execute; + + // 繝繝シ繧ソ霆「騾√ョ縺溘a縺ョ蛻晄悄蛹 + ctrl.offset = 0; + ctrl.blocks = 1; + + // 繧ウ繝槭Φ繝牙挨蜃ヲ逅 + switch (ctrl.cmd[0]) { + // TEST UNIT READY + case 0x00: + CmdTestUnitReady(); + return; + + // REZERO UNIT + case 0x01: + CmdRezero(); + return; + + // REQUEST SENSE + case 0x03: + CmdRequestSense(); + return; + + // FORMAT UNIT + case 0x04: + CmdFormat(); + return; + + // FORMAT UNIT + case 0x06: + CmdFormat(); + return; + + // REASSIGN BLOCKS + case 0x07: + CmdReassign(); + return; + + // READ(6) + case 0x08: + CmdRead6(); + return; + + // WRITE(6) + case 0x0a: + CmdWrite6(); + return; + + // SEEK(6) + case 0x0b: + CmdSeek6(); + return; + + // ASSIGN(SASI縺ョ縺ソ) + case 0x0e: + CmdAssign(); + return; + + // SPECIFY(SASI縺ョ縺ソ) + case 0xc2: + CmdSpecify(); + return; + } + + // 縺昴l莉・螟悶ッ蟇セ蠢懊@縺ヲ縺縺ェ縺 + Log(Log::Warning, "譛ェ蟇セ蠢懊さ繝槭Φ繝 $%02X", ctrl.cmd[0]); + CmdInvalid(); +} + +//--------------------------------------------------------------------------- +// +// 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::Status() +{ + ASSERT(this); + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク + if (ctrl.phase != BUS::status) { + +#if defined(DISK_LOG) + Log(Log::Normal, "繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ"); +#endif // DISK_LOG + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク蜑阪ョ繧ヲ繧ァ繧、繝 + ctrl.bus->SleepNsec(Time_phase_before); + + // 繝輔ぉ繝シ繧コ險ュ螳 + ctrl.phase = BUS::status; + + // 繧ソ繝シ繧イ繝繝医′謫堺ス懊☆繧倶ソ。蜿キ邱 + ctrl.bus->SetMSG(FALSE); + ctrl.bus->SetCD(TRUE); + ctrl.bus->SetIO(TRUE); + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク蠕後ョ莠亥相譎る俣 + ctrl.bus->SleepNsec(Time_phase_after_status); + + // 繝繝シ繧ソ霆「騾√ッ1繝舌う繝x1繝悶Ο繝繧ッ + ctrl.offset = 0; + ctrl.length = 1; + ctrl.blocks = 1; + ctrl.buffer[0] = (BYTE)ctrl.status; + return; + } + + // 騾∽ソ。 + Send(); +} + +//--------------------------------------------------------------------------- +// +// 繝。繝繧サ繝シ繧ク繧、繝ウ繝輔ぉ繝シ繧コ +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::MsgIn() +{ + ASSERT(this); + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク + if (ctrl.phase != BUS::msgin) { + +#if defined(DISK_LOG) + Log(Log::Normal, "繝。繝繧サ繝シ繧ク繧、繝ウ繝輔ぉ繝シ繧コ"); +#endif // DISK_LOG + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク蜑阪ョ繧ヲ繧ァ繧、繝 + ctrl.bus->SleepNsec(Time_phase_before); + + // 繝輔ぉ繝シ繧コ險ュ螳 + ctrl.phase = BUS::msgin; + + // 繧ソ繝シ繧イ繝繝医′謫堺ス懊☆繧倶ソ。蜿キ邱 + ctrl.bus->SetMSG(TRUE); + ctrl.bus->SetCD(TRUE); + ctrl.bus->SetIO(TRUE); + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク蠕後ョ莠亥相譎る俣 + ctrl.bus->SleepNsec(Time_phase_after); + + // length, blocks縺ッ險ュ螳壽ク医∩ + ASSERT(ctrl.length > 0); + ASSERT(ctrl.blocks > 0); + ctrl.offset = 0; + return; + } + + // 騾∽ソ。 + Send(); +} + +//--------------------------------------------------------------------------- +// +// 繝繝シ繧ソ繧、繝ウ繝輔ぉ繝シ繧コ +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::DataIn() +{ + ASSERT(this); + ASSERT(ctrl.length >= 0); + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク + if (ctrl.phase != BUS::datain) { + // 繝ャ繝ウ繧ー繧ケ0縺ェ繧峨√せ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ縺ク + if (ctrl.length == 0) { + Status(); + return; + } + +#if defined(DISK_LOG) + Log(Log::Normal, "繝繝シ繧ソ繧、繝ウ繝輔ぉ繝シ繧コ"); +#endif // DISK_LOG + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク蜑阪ョ繧ヲ繧ァ繧、繝 + ctrl.bus->SleepNsec(Time_phase_before_data); + + // 繝輔ぉ繝シ繧コ險ュ螳 + ctrl.phase = BUS::datain; + + // 繧ソ繝シ繧イ繝繝医′謫堺ス懊☆繧倶ソ。蜿キ邱 + ctrl.bus->SetMSG(FALSE); + ctrl.bus->SetCD(FALSE); + ctrl.bus->SetIO(TRUE); + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク蠕後ョ莠亥相譎る俣 + ctrl.bus->SleepNsec(Time_phase_after); + + // length, blocks縺ッ險ュ螳壽ク医∩ + ASSERT(ctrl.length > 0); + ASSERT(ctrl.blocks > 0); + ctrl.offset = 0; + return; + } + + // 騾∽ソ。 + Send(); +} + +//--------------------------------------------------------------------------- +// +// 繝繝シ繧ソ繧「繧ヲ繝医ヵ繧ァ繝シ繧コ +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::DataOut() +{ + ASSERT(this); + ASSERT(ctrl.length >= 0); + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク + if (ctrl.phase != BUS::dataout) { + // 繝ャ繝ウ繧ー繧ケ0縺ェ繧峨√せ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ縺ク + if (ctrl.length == 0) { + Status(); + return; + } + +#if defined(DISK_LOG) + Log(Log::Normal, "繝繝シ繧ソ繧「繧ヲ繝医ヵ繧ァ繝シ繧コ"); +#endif // DISK_LOG + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク蜑阪ョ繧ヲ繧ァ繧、繝 + ctrl.bus->SleepNsec(Time_phase_before_data); + + // 繝輔ぉ繝シ繧コ險ュ螳 + ctrl.phase = BUS::dataout; + + // 繧ソ繝シ繧イ繝繝医′謫堺ス懊☆繧倶ソ。蜿キ邱 + ctrl.bus->SetMSG(FALSE); + ctrl.bus->SetCD(FALSE); + ctrl.bus->SetIO(FALSE); + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク蠕後ョ莠亥相譎る俣 + ctrl.bus->SleepNsec(Time_phase_after); + + // length, blocks縺ッ險ュ螳壽ク医∩ + ASSERT(ctrl.length > 0); + ASSERT(ctrl.blocks > 0); + ctrl.offset = 0; + return; + } + + // 蜿嶺ソ。 + Receive(); +} + +//--------------------------------------------------------------------------- +// +// 蜈ア騾壹お繝ゥ繝シ +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::Error() +{ + DWORD lun; + + ASSERT(this); + + // 繝舌せ諠蝣ア縺ョ蜿悶j霎シ縺ソ + ctrl.bus->Aquire(); + + // 繝ェ繧サ繝繝医メ繧ァ繝繧ッ + if (ctrl.bus->GetRST()) { + // 繧ウ繝ウ繝医Ο繝シ繝ゥ繧偵Μ繧サ繝繝 + Reset(); + + // 繝舌せ繧ゅΜ繧サ繝繝 + ctrl.bus->Reset(); + return; + } + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ縲√Γ繝繧サ繝シ繧ク繧、繝ウ繝輔ぉ繝シ繧コ縺ッ繝舌せ繝輔Μ繝シ + if (ctrl.phase == BUS::status || ctrl.phase == BUS::msgin) { + BusFree(); + return; + } + +#if defined(DISK_LOG) + Log(Log::Warning, "繧ィ繝ゥ繝シ(繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ縺ク)"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + + // 繧ケ繝繝シ繧ソ繧ケ縺ィ繝。繝繧サ繝シ繧ク繧定ィュ螳(CHECK CONDITION) + ctrl.status = (lun << 5) | 0x02; + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); +} + +//--------------------------------------------------------------------------- +// +// TEST UNIT READY +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::CmdTestUnitReady() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "TEST UNIT READY繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + status = ctrl.unit[lun]->TestUnitReady(ctrl.cmd); + if (!status) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); +} + +//--------------------------------------------------------------------------- +// +// REZERO UNIT +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::CmdRezero() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "REZERO UNIT繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + status = ctrl.unit[lun]->Rezero(ctrl.cmd); + if (!status) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); +} + +//--------------------------------------------------------------------------- +// +// REQUEST SENSE +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::CmdRequestSense() +{ + DWORD lun; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "REQUEST SENSE繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + ctrl.length = ctrl.unit[lun]->RequestSense(ctrl.cmd, ctrl.buffer); + ASSERT(ctrl.length > 0); + +#if defined(DISK_LOG) + Log(Log::Normal, "繧サ繝ウ繧ケ繧ュ繝シ $%02X", ctrl.buffer[2]); +#endif // DISK_LOG + + // 繝ェ繝シ繝峨ヵ繧ァ繝シ繧コ + DataIn(); +} + +//--------------------------------------------------------------------------- +// +// FORMAT UNIT +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::CmdFormat() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "FORMAT UNIT繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + status = ctrl.unit[lun]->Format(ctrl.cmd); + if (!status) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); +} + +//--------------------------------------------------------------------------- +// +// REASSIGN BLOCKS +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::CmdReassign() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "REASSIGN BLOCKS繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + status = ctrl.unit[lun]->Reassign(ctrl.cmd); + if (!status) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); +} + +//--------------------------------------------------------------------------- +// +// READ(6) +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::CmdRead6() +{ + DWORD lun; + DWORD record; + + ASSERT(this); + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝ャ繧ウ繝シ繝臥分蜿キ縺ィ繝悶Ο繝繧ッ謨ー繧貞叙蠕 + record = ctrl.cmd[1] & 0x1f; + record <<= 8; + record |= ctrl.cmd[2]; + record <<= 8; + record |= ctrl.cmd[3]; + ctrl.blocks = ctrl.cmd[4]; + if (ctrl.blocks == 0) { + ctrl.blocks = 0x100; + } + +#if defined(DISK_LOG) + Log(Log::Normal, "READ(6)繧ウ繝槭Φ繝 繝ャ繧ウ繝シ繝=%06X 繝悶Ο繝繧ッ=%d", record, ctrl.blocks); +#endif // DISK_LOG + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + ctrl.length = ctrl.unit[lun]->Read(ctrl.buffer, record); + if (ctrl.length <= 0) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 谺。縺ョ繝悶Ο繝繧ッ繧定ィュ螳 + ctrl.next = record + 1; + + // 繝ェ繝シ繝峨ヵ繧ァ繝シ繧コ + DataIn(); +} + +//--------------------------------------------------------------------------- +// +// WRITE(6) +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::CmdWrite6() +{ + DWORD lun; + DWORD record; + + ASSERT(this); + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝ャ繧ウ繝シ繝臥分蜿キ縺ィ繝悶Ο繝繧ッ謨ー繧貞叙蠕 + record = ctrl.cmd[1] & 0x1f; + record <<= 8; + record |= ctrl.cmd[2]; + record <<= 8; + record |= ctrl.cmd[3]; + ctrl.blocks = ctrl.cmd[4]; + if (ctrl.blocks == 0) { + ctrl.blocks = 0x100; + } + +#if defined(DISK_LOG) + Log(Log::Normal, "WRITE(6)繧ウ繝槭Φ繝 繝ャ繧ウ繝シ繝=%06X 繝悶Ο繝繧ッ=%d", record, ctrl.blocks); +#endif // DISK_LOG + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + ctrl.length = ctrl.unit[lun]->WriteCheck(record); + if (ctrl.length <= 0) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 谺。縺ョ繝悶Ο繝繧ッ繧定ィュ螳 + ctrl.next = record + 1; + + // 繝ゥ繧、繝医ヵ繧ァ繝シ繧コ + DataOut(); +} + +//--------------------------------------------------------------------------- +// +// SEEK(6) +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::CmdSeek6() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "SEEK(6)繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + status = ctrl.unit[lun]->Seek(ctrl.cmd); + if (!status) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); +} + +//--------------------------------------------------------------------------- +// +// ASSIGN +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::CmdAssign() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "ASSIGN繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + status = ctrl.unit[lun]->Assign(ctrl.cmd); + if (!status) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 4繝舌う繝医ョ繝繝シ繧ソ繧偵Μ繧ッ繧ィ繧ケ繝 + ctrl.length = 4; + + // 繝ゥ繧、繝医ヵ繧ァ繝シ繧コ + DataOut(); +} + +//--------------------------------------------------------------------------- +// +// SPECIFY +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::CmdSpecify() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "SPECIFY繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + status = ctrl.unit[lun]->Assign(ctrl.cmd); + if (!status) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 10繝舌う繝医ョ繝繝シ繧ソ繧偵Μ繧ッ繧ィ繧ケ繝 + ctrl.length = 10; + + // 繝ゥ繧、繝医ヵ繧ァ繝シ繧コ + DataOut(); +} + +//--------------------------------------------------------------------------- +// +// 繧オ繝昴シ繝医@縺ヲ縺縺ェ縺繧ウ繝槭Φ繝 +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::CmdInvalid() +{ + DWORD lun; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "繧オ繝昴シ繝医@縺ヲ縺縺ェ縺繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (ctrl.unit[lun]) { + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + ctrl.unit[lun]->InvalidCmd(); + } + + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); +} + +//=========================================================================== +// +// 繝繝シ繧ソ霆「騾 +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繝繝シ繧ソ騾∽ソ。 +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::Send() +{ + int len; + BOOL result; + + ASSERT(this); + ASSERT(!ctrl.bus->GetREQ()); + ASSERT(!ctrl.bus->GetACK()); + ASSERT(ctrl.bus->GetIO()); + + // 繝ャ繝ウ繧ー繧ケ!=0縺ェ繧蛾∽ソ。 + if (ctrl.length != 0) { + len = ctrl.bus->SendHandShake( + &ctrl.buffer[ctrl.offset], ctrl.length); + + // 蜈ィ縺ヲ騾∽ソ。縺ァ縺阪↑縺代l縺ー繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ縺ク遘サ陦 + if (len != ctrl.length) { + Error(); + return; + } + + // 繧ェ繝輔そ繝繝医→繝ャ繝ウ繧ー繧ケ + ctrl.offset += ctrl.length; + ctrl.length = 0; + return; + } + + // 繝悶Ο繝繧ッ貂帷ョ励√Μ繧カ繝ォ繝亥晄悄蛹 + ctrl.blocks--; + result = TRUE; + + // 繝繝シ繧ソ蠑輔″蜿悶j蠕後ョ蜃ヲ逅(繝ェ繝シ繝/繝繝シ繧ソ繧、繝ウ縺ョ縺ソ) + if (ctrl.phase == BUS::datain) { + if (ctrl.blocks != 0) { + // 谺。縺ョ繝舌ャ繝輔ぃ繧定ィュ螳(offset, length繧偵そ繝繝医☆繧九%縺ィ) + result = XferIn(ctrl.buffer); + } + } + + // 繝ェ繧カ繝ォ繝FALSE縺ェ繧峨√せ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ縺ク遘サ陦 + if (!result) { + Error(); + return; + } + + // 繝悶Ο繝繧ッ!=0縺ェ繧蛾∽ソ。邯咏カ + if (ctrl.blocks != 0){ + ASSERT(ctrl.length > 0); + ASSERT(ctrl.offset == 0); + return; + } + + // 谺。繝輔ぉ繝シ繧コ縺ォ遘サ蜍 + switch (ctrl.phase) { + // 繝。繝繧サ繝シ繧ク繧、繝ウ繝輔ぉ繝シ繧コ + case BUS::msgin: + // 繝舌せ繝輔Μ繝シ繝輔ぉ繝シ繧コ + BusFree(); + break; + + // 繝繝シ繧ソ繧、繝ウ繝輔ぉ繝シ繧コ + case BUS::datain: + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); + break; + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + case BUS::status: + // 繝。繝繧サ繝シ繧ク繧、繝ウ繝輔ぉ繝シ繧コ + ctrl.length = 1; + ctrl.blocks = 1; + ctrl.buffer[0] = ctrl.message; + MsgIn(); + break; + + // 縺昴ョ莉(縺ゅj縺医↑縺) + default: + ASSERT(FALSE); + break; + } +} + +//--------------------------------------------------------------------------- +// +// 繝繝シ繧ソ蜿嶺ソ。 +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::Receive() +{ + BOOL result; + int i; + int len; + + ASSERT(this); + + // REQ,ACK縺御ク九′縺」縺ヲ縺繧九%縺ィ + ASSERT(!ctrl.bus->GetREQ()); + ASSERT(!ctrl.bus->GetACK()); + ASSERT(!ctrl.bus->GetIO()); + + // 繝ャ繝ウ繧ー繧ケ!=0縺ェ繧牙女菫。 + if (ctrl.length != 0) { + // 蜿嶺ソ。 + len = ctrl.bus->ReceiveHandShake( + &ctrl.buffer[ctrl.offset], ctrl.length); + + // 蜈ィ縺ヲ蜿嶺ソ。縺ァ縺阪↑縺代l縺ー繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ縺ク遘サ陦 + if (len != ctrl.length) { + Error(); + return; + } + + // 繧ェ繝輔そ繝繝医→繝ャ繝ウ繧ー繧ケ + ctrl.offset += ctrl.length; + ctrl.length = 0; + return; + } + + // 繝悶Ο繝繧ッ貂帷ョ励√Μ繧カ繝ォ繝亥晄悄蛹 + ctrl.blocks--; + result = TRUE; + + // 繝繝シ繧ソ繧「繧ヲ繝医ヵ繧ァ繝シ繧コ縺ョ蜃ヲ逅 + if (ctrl.phase == BUS::dataout) { + if (ctrl.blocks == 0) { + // 縺薙ョ繝舌ャ繝輔ぃ縺ァ邨ゆコ + result = XferOut(FALSE); + } else { + // 谺。縺ョ繝舌ャ繝輔ぃ縺ォ邯壹¥(offset, length繧偵そ繝繝医☆繧九%縺ィ) + result = XferOut(TRUE); + } + } + + // 繝ェ繧カ繝ォ繝FALSE縺ェ繧峨√せ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ縺ク遘サ陦 + if (!result) { + Error(); + return; + } + + // 繝悶Ο繝繧ッ!=0縺ェ繧牙女菫。邯咏カ + if (ctrl.blocks != 0){ + ASSERT(ctrl.length > 0); + ASSERT(ctrl.offset == 0); + return; + } + + // 谺。繝輔ぉ繝シ繧コ縺ォ遘サ蜍 + switch (ctrl.phase) { + // 繧ウ繝槭Φ繝峨ヵ繧ァ繝シ繧コ + case BUS::command: + // 繧ウ繝槭Φ繝峨ョ繝シ繧ソ霆「騾 + len = 6; + if (ctrl.buffer[0] >= 0x20 && ctrl.buffer[0] <= 0x7D) { + // 10繝舌う繝CDB + len = 10; + } + for (i = 0; i < len; i++) { + ctrl.cmd[i] = (DWORD)ctrl.buffer[i]; +#if defined(DISK_LOG) + Log(Log::Normal, "繧ウ繝槭Φ繝 $%02X", ctrl.cmd[i]); +#endif // DISK_LOG + } + + // 螳溯。後ヵ繧ァ繝シ繧コ + Execute(); + break; + + // 繝繝シ繧ソ繧「繧ヲ繝医ヵ繧ァ繝シ繧コ + case BUS::dataout: + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); + break; + + // 縺昴ョ莉(縺ゅj縺医↑縺) + default: + ASSERT(FALSE); + break; + } +} + +//--------------------------------------------------------------------------- +// +// 繝繝シ繧ソ霆「騾!N +// 窶サoffset, length繧貞崎ィュ螳壹☆繧九%縺ィ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SASIDEV::XferIn(BYTE *buf) +{ + DWORD lun; + + ASSERT(this); + ASSERT(ctrl.phase == BUS::datain); + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + return FALSE; + } + + // READ邉サ繧ウ繝槭Φ繝峨↓髯舌k + switch (ctrl.cmd[0]) { + // READ(6) + case 0x08: + // READ(10) + case 0x28: + // 繝繧」繧ケ繧ッ縺九i隱ュ縺ソ蜿悶j繧定。後≧ + ctrl.length = ctrl.unit[lun]->Read(buf, ctrl.next); + ctrl.next++; + + // 繧ィ繝ゥ繝シ縺ェ繧峨√せ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ縺ク + if (ctrl.length <= 0) { + // 繝繝シ繧ソ繧、繝ウ荳ュ豁「 + return FALSE; + } + + // 豁」蟶ク縺ェ繧峨√Ρ繝シ繧ッ險ュ螳 + ctrl.offset = 0; + break; + + // 縺昴ョ莉(縺ゅj縺医↑縺) + default: + ASSERT(FALSE); + return FALSE; + } + + // 繝舌ャ繝輔ぃ險ュ螳壹↓謌仙粥縺励◆ + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繝繝シ繧ソ霆「騾^UT +// 窶サcont=TRUE縺ョ蝣エ蜷医{ffset, length繧貞崎ィュ螳壹☆繧九%縺ィ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SASIDEV::XferOut(BOOL cont) +{ + DWORD lun; + SCSIBR *bridge; + + ASSERT(this); + ASSERT(ctrl.phase == BUS::dataout); + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + return FALSE; + } + + // MODE SELECT縺セ縺溘ッ縲仝RITE邉サ + switch (ctrl.cmd[0]) { + // MODE SELECT + case 0x15: + // MODE SELECT(10) + case 0x55: + if (!ctrl.unit[lun]->ModeSelect(ctrl.cmd, ctrl.buffer, ctrl.offset)) { + // MODE SELECT縺ォ螟ア謨 + return FALSE; + } + break; + + // WRITE(6) + case 0x0a: + // WRITE(10) + case 0x2a: + // 繝帙せ繝医ヶ繝ェ繝繧ク縺ッSEND MESSAGE10縺ォ蟾ョ縺玲崛縺医k + if (ctrl.unit[lun]->GetID() == MAKEID('S', 'C', 'B', 'R')) { + bridge = (SCSIBR*)ctrl.unit[lun]; + if (!bridge->SendMessage10(ctrl.cmd, ctrl.buffer)) { + // 譖ク縺崎セシ縺ソ螟ア謨 + return FALSE; + } + + // 豁」蟶ク縺ェ繧峨√Ρ繝シ繧ッ險ュ螳 + ctrl.offset = 0; + break; + } + + // WRITE AND VERIFY + case 0x2e: + // 譖ク縺崎セシ縺ソ繧定。後≧ + if (!ctrl.unit[lun]->Write(ctrl.buffer, ctrl.next - 1)) { + // 譖ク縺崎セシ縺ソ螟ア謨 + return FALSE; + } + + // 谺。縺ョ繝悶Ο繝繧ッ縺悟ソ隕√↑縺縺ェ繧峨%縺薙∪縺ァ + ctrl.next++; + if (!cont) { + break; + } + + // 谺。縺ョ繝悶Ο繝繧ッ繧偵メ繧ァ繝繧ッ + ctrl.length = ctrl.unit[lun]->WriteCheck(ctrl.next); + if (ctrl.length <= 0) { + // 譖ク縺崎セシ縺ソ縺ァ縺阪↑縺 + return FALSE; + } + + // 豁」蟶ク縺ェ繧峨√Ρ繝シ繧ッ險ュ螳 + ctrl.offset = 0; + break; + + default: + ASSERT(FALSE); + break; + } + + // 繝舌ャ繝輔ぃ菫晏ュ倥↓謌仙粥縺励◆ + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繝ュ繧ー蜃コ蜉 +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::Log(Log::loglevel level, const char *format, ...) +{ + char buffer[0x200]; + va_list args; + va_start(args, format); + +#ifdef RASCSI +#ifndef DISK_LOG + if (level == Log::Warning) { + return; + } +#endif // DISK_LOG +#endif // RASCSI + + // 繝輔か繝シ繝槭ャ繝 + vsprintf(buffer, format, args); + + // 蜿ッ螟蛾聞蠑墓焚邨ゆコ + va_end(args); + + // 繝ュ繧ー蜃コ蜉 +#ifdef RASCSI + printf("%s\n", buffer); +#else + host->GetVM()->GetLog()->Format(level, host, buffer); +#endif // RASCSI +} + +//=========================================================================== +// +// SCSI 繝繝舌う繧ケ +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +#ifdef RASCSI +SCSIDEV::SCSIDEV() : SASIDEV() +#else +SCSIDEV::SCSIDEV(Device *dev) : SASIDEV(dev) +#endif +{ + // 蜷梧悄霆「騾√Ρ繝シ繧ッ蛻晄悄蛹 + scsi.syncenable = FALSE; + scsi.syncperiod = 50; + scsi.syncoffset = 0; + scsi.atnmsg = FALSE; + scsi.msc = 0; + memset(scsi.msb, 0x00, sizeof(scsi.msb)); +} + +//--------------------------------------------------------------------------- +// +// 繝繝舌う繧ケ繝ェ繧サ繝繝 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::Reset() +{ + ASSERT(this); + + // 繝ッ繝シ繧ッ蛻晄悄蛹 + scsi.atnmsg = FALSE; + scsi.msc = 0; + memset(scsi.msb, 0x00, sizeof(scsi.msb)); + + // 蝓コ蠎輔け繝ゥ繧ケ + SASIDEV::Reset(); +} + +//--------------------------------------------------------------------------- +// +// 螳溯。 +// +//--------------------------------------------------------------------------- +BUS::phase_t FASTCALL SCSIDEV::Process() +{ + ASSERT(this); + + // 譛ェ謗・邯壹↑繧我ス輔b縺励↑縺 + if (ctrl.id < 0 || ctrl.bus == NULL) { + return ctrl.phase; + } + + // 繝舌せ諠蝣ア縺ョ蜿悶j霎シ縺ソ + ctrl.bus->Aquire(); + + // 繝ェ繧サ繝繝 + if (ctrl.bus->GetRST()) { +#if defined(DISK_LOG) + Log(Log::Normal, "RESET菫。蜿キ蜿嶺ソ。"); +#endif // DISK_LOG + + // 繧ウ繝ウ繝医Ο繝シ繝ゥ繧偵Μ繧サ繝繝 + Reset(); + + // 繝舌せ繧ゅΜ繧サ繝繝 + ctrl.bus->Reset(); + return ctrl.phase; + } + + // 繝輔ぉ繝シ繧コ蜃ヲ逅 + switch (ctrl.phase) { + + // 繝舌せ繝輔Μ繝シ + case BUS::busfree: + BusFree(); + break; + + // 繧サ繝ャ繧ッ繧キ繝ァ繝ウ繝輔ぉ繝シ繧コ + case BUS::selection: + Selection(); + break; + + // 繝繝シ繧ソ繧「繧ヲ繝(MCI=000) + case BUS::dataout: + DataOut(); + break; + + // 繝繝シ繧ソ繧、繝ウ(MCI=001) + case BUS::datain: + DataIn(); + break; + + // 繧ウ繝槭Φ繝(MCI=010) + case BUS::command: + Command(); + break; + + // 繧ケ繝繝シ繧ソ繧ケ(MCI=011) + case BUS::status: + Status(); + break; + + // 繝。繝繧サ繝シ繧ク繧「繧ヲ繝(MCI=110) + case BUS::msgout: + MsgOut(); + break; + + // 繝。繝繧サ繝シ繧ク繧、繝ウ(MCI=111) + case BUS::msgin: + MsgIn(); + break; + + // 縺昴ョ莉 + default: + ASSERT(FALSE); + break; + } + + return ctrl.phase; +} + +//--------------------------------------------------------------------------- +// +// 繝輔ぉ繝シ繧コ +// +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// +// 繝舌せ繝輔Μ繝シ繝輔ぉ繝シ繧コ +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::BusFree() +{ + ASSERT(this); + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク + if (ctrl.phase != BUS::busfree) { + +#if defined(DISK_LOG) + Log(Log::Normal, "繝舌せ繝輔Μ繝シ繝輔ぉ繝シ繧コ"); +#endif // DISK_LOG + + // 繝輔ぉ繝シ繧コ險ュ螳 + ctrl.phase = BUS::busfree; + + // 菫。蜿キ邱 + ctrl.bus->SetBSY(FALSE); + ctrl.bus->SetMSG(FALSE); + ctrl.bus->SetCD(FALSE); + ctrl.bus->SetIO(FALSE); + ctrl.bus->SetREQ(FALSE); + + // 繧ケ繝繝シ繧ソ繧ケ縺ィ繝。繝繧サ繝シ繧ク繧貞晄悄蛹 + ctrl.status = 0x00; + ctrl.message = 0x00; + + // ATN繝。繝繧サ繝シ繧ク蜿嶺ソ。繧ケ繧ソ繝シ繧ソ繧ケ蛻晄悄蛹 + scsi.atnmsg = FALSE; + + // 繝舌せ繧ッ繝ェ繧「繝繧」繝ャ繧、 + ctrl.bus->SleepNsec(Time_phase_bsy); + + return; + } + + // 繧サ繝ャ繧ッ繧キ繝ァ繝ウ繝輔ぉ繝シ繧コ縺ォ遘サ陦 + if (ctrl.bus->GetSEL() && !ctrl.bus->GetBSY()) { + Selection(); + } +} + +//--------------------------------------------------------------------------- +// +// 繧サ繝ャ繧ッ繧キ繝ァ繝ウ繝輔ぉ繝シ繧コ +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::Selection() +{ + DWORD id; + + ASSERT(this); + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク + if (ctrl.phase != BUS::selection) { + // ID縺御ク閾エ縺励※縺縺ェ縺代l縺ー辟。蜉ケ + id = 1 << ctrl.id; + if ((ctrl.bus->GetDAT() & id) == 0) { + return; + } + + // 譛牙柑縺ェ繝ヲ繝九ャ繝医′辟。縺代l縺ー邨ゆコ + if (!HasUnit()) { + return; + } + +#if defined(DISK_LOG) + Log(Log::Normal, "繧サ繝ャ繧ッ繧キ繝ァ繝ウ繝輔ぉ繝シ繧コ ID=%d (繝繝舌う繧ケ縺ゅj)", ctrl.id); +#endif // DISK_LOG + + // 繝輔ぉ繝シ繧コ險ュ螳 + ctrl.phase = BUS::selection; + + // BSY繧剃ク翫£縺ヲ蠢懃ュ + ctrl.bus->SetBSY(TRUE); + return; + } + + // 繧サ繝ャ繧ッ繧キ繝ァ繝ウ螳御コ + if (!ctrl.bus->GetSEL() && ctrl.bus->GetBSY()) { + // ATN=1縺ェ繧峨Γ繝繧サ繝シ繧ク繧「繧ヲ繝医ヵ繧ァ繝シ繧コ縲√◎縺縺ァ縺ェ縺代l縺ー繧ウ繝槭Φ繝峨ヵ繧ァ繝シ繧コ + if (ctrl.bus->GetATN()) { + MsgOut(); + } else { + Command(); + } + } +} + +//--------------------------------------------------------------------------- +// +// 螳溯。後ヵ繧ァ繝シ繧コ +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::Execute() +{ + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "螳溯。後ヵ繧ァ繝シ繧コ 繧ウ繝槭Φ繝$%02X", ctrl.cmd[0]); +#endif // DISK_LOG + + // 繝輔ぉ繝シ繧コ險ュ螳 + ctrl.phase = BUS::execute; + + // 繝繝シ繧ソ霆「騾√ョ縺溘a縺ョ蛻晄悄蛹 + ctrl.offset = 0; + ctrl.blocks = 1; + + // 蜃ヲ逅譎る俣縺ョ繝繧」繝ャ繧、 + ctrl.bus->SleepNsec(100 * 1000); + + // 繧ウ繝槭Φ繝牙挨蜃ヲ逅 + switch (ctrl.cmd[0]) { + // TEST UNIT READY + case 0x00: + CmdTestUnitReady(); + return; + + // REZERO + case 0x01: + CmdRezero(); + return; + + // REQUEST SENSE + case 0x03: + CmdRequestSense(); + return; + + // FORMAT UNIT + case 0x04: + CmdFormat(); + return; + + // REASSIGN BLOCKS + case 0x07: + CmdReassign(); + return; + + // READ(6) + case 0x08: + CmdRead6(); + return; + + // WRITE(6) + case 0x0a: + CmdWrite6(); + return; + + // SEEK(6) + case 0x0b: + CmdSeek6(); + return; + + // INQUIRY + case 0x12: + CmdInquiry(); + return; + + // MODE SELECT + case 0x15: + CmdModeSelect(); + return; + + // MDOE SENSE + case 0x1a: + CmdModeSense(); + return; + + // START STOP UNIT + case 0x1b: + CmdStartStop(); + return; + + // SEND DIAGNOSTIC + case 0x1d: + CmdSendDiag(); + return; + + // PREVENT/ALLOW MEDIUM REMOVAL + case 0x1e: + CmdRemoval(); + return; + + // READ CAPACITY + case 0x25: + CmdReadCapacity(); + return; + + // READ(10) + case 0x28: + CmdRead10(); + return; + + // WRITE(10) + case 0x2a: + CmdWrite10(); + return; + + // SEEK(10) + case 0x2b: + CmdSeek10(); + return; + + // WRITE and VERIFY + case 0x2e: + CmdWrite10(); + return; + + // VERIFY + case 0x2f: + CmdVerify(); + return; + + // SYNCHRONIZE CACHE + case 0x35: + CmdSynchronizeCache(); + return; + + // READ DEFECT DATA(10) + case 0x37: + CmdReadDefectData10(); + return; + + // READ TOC + case 0x43: + CmdReadToc(); + return; + + // PLAY AUDIO(10) + case 0x45: + CmdPlayAudio10(); + return; + + // PLAY AUDIO MSF + case 0x47: + CmdPlayAudioMSF(); + return; + + // PLAY AUDIO TRACK + case 0x48: + CmdPlayAudioTrack(); + return; + + // MODE SELECT(10) + case 0x55: + CmdModeSelect10(); + return; + + // MDOE SENSE(10) + case 0x5a: + CmdModeSense10(); + return; + } + + // 縺昴l莉・螟悶ッ蟇セ蠢懊@縺ヲ縺縺ェ縺 + Log(Log::Normal, "譛ェ蟇セ蠢懊さ繝槭Φ繝 $%02X", ctrl.cmd[0]); + CmdInvalid(); +} + +//--------------------------------------------------------------------------- +// +// 繝。繝繧サ繝シ繧ク繧「繧ヲ繝医ヵ繧ァ繝シ繧コ +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::MsgOut() +{ + ASSERT(this); + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク + if (ctrl.phase != BUS::msgout) { + +#if defined(DISK_LOG) + Log(Log::Normal, "繝。繝繧サ繝シ繧ク繧「繧ヲ繝医ヵ繧ァ繝シ繧コ"); +#endif // DISK_LOG + + // 繧サ繝ャ繧ッ繧キ繝ァ繝ウ蠕後ョ繝。繝繧サ繝シ繧ク繧「繧ヲ繝医ヵ繧ァ繝シ繧コ縺ッIDENTIFY繝。繝繧サ繝シ繧ク縺ョ蜃ヲ逅 + if (ctrl.phase == BUS::selection) { + scsi.atnmsg = TRUE; + scsi.msc = 0; + memset(scsi.msb, 0x00, sizeof(scsi.msb)); + } + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク蜑阪ョ繧ヲ繧ァ繧、繝 + ctrl.bus->SleepNsec(Time_phase_before); + + // 繝輔ぉ繝シ繧コ險ュ螳 + ctrl.phase = BUS::msgout; + + // 繧ソ繝シ繧イ繝繝医′謫堺ス懊☆繧倶ソ。蜿キ邱 + ctrl.bus->SetMSG(TRUE); + ctrl.bus->SetCD(TRUE); + ctrl.bus->SetIO(FALSE); + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク蠕後ョ莠亥相譎る俣 + ctrl.bus->SleepNsec(Time_phase_after); + + // 繝繝シ繧ソ霆「騾√ッ1繝舌う繝x1繝悶Ο繝繧ッ + ctrl.offset = 0; + ctrl.length = 1; + ctrl.blocks = 1; + return; + } + + // 蜿嶺ソ。 + Receive(); +} + +//--------------------------------------------------------------------------- +// +// 蜈ア騾壹お繝ゥ繝シ蜃ヲ逅 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::Error() +{ + ASSERT(this); + + // 繝舌せ諠蝣ア縺ョ蜿悶j霎シ縺ソ + ctrl.bus->Aquire(); + + // 繝ェ繧サ繝繝医メ繧ァ繝繧ッ + if (ctrl.bus->GetRST()) { + // 繧ウ繝ウ繝医Ο繝シ繝ゥ繧偵Μ繧サ繝繝 + Reset(); + + // 繝舌せ繧ゅΜ繧サ繝繝 + ctrl.bus->Reset(); + return; + } + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ縲√Γ繝繧サ繝シ繧ク繧、繝ウ繝輔ぉ繝シ繧コ縺ッ繝舌せ繝輔Μ繝シ + if (ctrl.phase == BUS::status || ctrl.phase == BUS::msgin) { + BusFree(); + return; + } + +#if defined(DISK_LOG) + Log(Log::Normal, "繧ィ繝ゥ繝シ(繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ縺ク)"); +#endif // DISK_LOG + + // 繧ケ繝繝シ繧ソ繧ケ縺ィ繝。繝繧サ繝シ繧ク繧定ィュ螳(CHECK CONDITION) + ctrl.status = 0x02; + ctrl.message = 0x00; + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); +} + +//--------------------------------------------------------------------------- +// +// 繧ウ繝槭Φ繝 +// +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// +// INQUIRY +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdInquiry() +{ + Disk *disk; + int lun; + DWORD major; + DWORD minor; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "INQUIRY繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 譛牙柑縺ェ繝ヲ繝九ャ繝医r謗「縺 + disk = NULL; + for (lun = 0; lun < UnitMax; lun++) { + if (ctrl.unit[lun]) { + disk = ctrl.unit[lun]; + break; + } + } + + // 繝繧」繧ケ繧ッ蛛エ縺ァ蜃ヲ逅(譛ャ譚・縺ッ繧ウ繝ウ繝医Ο繝シ繝ゥ縺ァ蜃ヲ逅縺輔l繧) + if (disk) { +#ifdef RASCSI + major = (DWORD)(RASCSI >> 8); + minor = (DWORD)(RASCSI & 0xff); +#else + host->GetVM()->GetVersion(major, minor); +#endif // RASCSI + ctrl.length = ctrl.unit[lun]->Inquiry(ctrl.cmd, ctrl.buffer, major, minor); + } else { + ctrl.length = 0; + } + + if (ctrl.length <= 0) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 蜷梧悄霆「騾√し繝昴シ繝域ュ蝣ア縺ョ霑ス蜉 + if (scsi.syncenable) { + ctrl.buffer[7] |= (1 << 4); + } + + // 繝繝シ繧ソ繧、繝ウ繝輔ぉ繝シ繧コ + DataIn(); +} + +//--------------------------------------------------------------------------- +// +// MODE SELECT +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdModeSelect() +{ + DWORD lun; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "MODE SELECT繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + ctrl.length = ctrl.unit[lun]->SelectCheck(ctrl.cmd); + if (ctrl.length <= 0) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繝繝シ繧ソ繧「繧ヲ繝医ヵ繧ァ繝シ繧コ + DataOut(); +} + +//--------------------------------------------------------------------------- +// +// MODE SENSE +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdModeSense() +{ + DWORD lun; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "MODE SENSE繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + ctrl.length = ctrl.unit[lun]->ModeSense(ctrl.cmd, ctrl.buffer); + ASSERT(ctrl.length >= 0); + if (ctrl.length == 0) { + Log(Log::Warning, "繧オ繝昴シ繝医@縺ヲ縺縺ェ縺МODE SENSE繝壹シ繧ク $%02X", ctrl.cmd[2]); + + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繝繝シ繧ソ繧、繝ウ繝輔ぉ繝シ繧コ + DataIn(); +} + +//--------------------------------------------------------------------------- +// +// START STOP UNIT +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdStartStop() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "START STOP UNIT繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + status = ctrl.unit[lun]->StartStop(ctrl.cmd); + if (!status) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); +} + +//--------------------------------------------------------------------------- +// +// SEND DIAGNOSTIC +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdSendDiag() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "SEND DIAGNOSTIC繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + status = ctrl.unit[lun]->SendDiag(ctrl.cmd); + if (!status) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); +} + +//--------------------------------------------------------------------------- +// +// PREVENT/ALLOW MEDIUM REMOVAL +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdRemoval() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "PREVENT/ALLOW MEDIUM REMOVAL繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + status = ctrl.unit[lun]->Removal(ctrl.cmd); + if (!status) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); +} + +//--------------------------------------------------------------------------- +// +// READ CAPACITY +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdReadCapacity() +{ + DWORD lun; + int length; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "READ CAPACITY繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + length = ctrl.unit[lun]->ReadCapacity(ctrl.cmd, ctrl.buffer); + ASSERT(length >= 0); + if (length <= 0) { + Error(); + return; + } + + // 繝ャ繝ウ繧ー繧ケ險ュ螳 + ctrl.length = length; + + // 繝繝シ繧ソ繧、繝ウ繝輔ぉ繝シ繧コ + DataIn(); +} + +//--------------------------------------------------------------------------- +// +// READ(10) +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdRead10() +{ + DWORD lun; + DWORD record; + + ASSERT(this); + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝帙せ繝医ヶ繝ェ繝繧ク縺ェ繧峨Γ繝繧サ繝シ繧ク蜿嶺ソ。 + if (ctrl.unit[lun]->GetID() == MAKEID('S', 'C', 'B', 'R')) { + CmdGetMessage10(); + return; + } + + // 繝ャ繧ウ繝シ繝臥分蜿キ縺ィ繝悶Ο繝繧ッ謨ー繧貞叙蠕 + record = ctrl.cmd[2]; + record <<= 8; + record |= ctrl.cmd[3]; + record <<= 8; + record |= ctrl.cmd[4]; + record <<= 8; + record |= ctrl.cmd[5]; + ctrl.blocks = ctrl.cmd[7]; + ctrl.blocks <<= 8; + ctrl.blocks |= ctrl.cmd[8]; + +#if defined(DISK_LOG) + Log(Log::Normal, "READ(10)繧ウ繝槭Φ繝 繝ャ繧ウ繝シ繝=%08X 繝悶Ο繝繧ッ=%d", record, ctrl.blocks); +#endif // DISK_LOG + + // 繝悶Ο繝繧ッ謨ー0縺ッ蜃ヲ逅縺励↑縺 + if (ctrl.blocks == 0) { + Status(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + ctrl.length = ctrl.unit[lun]->Read(ctrl.buffer, record); + if (ctrl.length <= 0) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 谺。縺ョ繝悶Ο繝繧ッ繧定ィュ螳 + ctrl.next = record + 1; + + // 繝繝シ繧ソ繧、繝ウ繝輔ぉ繝シ繧コ + DataIn(); +} + +//--------------------------------------------------------------------------- +// +// WRITE(10) +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdWrite10() +{ + DWORD lun; + DWORD record; + + ASSERT(this); + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝帙せ繝医ヶ繝ェ繝繧ク縺ェ繧峨Γ繝繧サ繝シ繧ク蜿嶺ソ。 + if (ctrl.unit[lun]->GetID() == MAKEID('S', 'C', 'B', 'R')) { + CmdSendMessage10(); + return; + } + + // 繝ャ繧ウ繝シ繝臥分蜿キ縺ィ繝悶Ο繝繧ッ謨ー繧貞叙蠕 + record = ctrl.cmd[2]; + record <<= 8; + record |= ctrl.cmd[3]; + record <<= 8; + record |= ctrl.cmd[4]; + record <<= 8; + record |= ctrl.cmd[5]; + ctrl.blocks = ctrl.cmd[7]; + ctrl.blocks <<= 8; + ctrl.blocks |= ctrl.cmd[8]; + +#if defined(DISK_LOG) + Log(Log::Normal, "WRTIE(10)繧ウ繝槭Φ繝 繝ャ繧ウ繝シ繝=%08X 繝悶Ο繝繧ッ=%d", record, ctrl.blocks); +#endif // DISK_LOG + + // 繝悶Ο繝繧ッ謨ー0縺ッ蜃ヲ逅縺励↑縺 + if (ctrl.blocks == 0) { + Status(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + ctrl.length = ctrl.unit[lun]->WriteCheck(record); + if (ctrl.length <= 0) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 谺。縺ョ繝悶Ο繝繧ッ繧定ィュ螳 + ctrl.next = record + 1; + + // 繝繝シ繧ソ繧「繧ヲ繝医ヵ繧ァ繝シ繧コ + DataOut(); +} + +//--------------------------------------------------------------------------- +// +// SEEK(10) +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdSeek10() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "SEEK(10)繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + status = ctrl.unit[lun]->Seek(ctrl.cmd); + if (!status) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); +} + +//--------------------------------------------------------------------------- +// +// VERIFY +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdVerify() +{ + DWORD lun; + BOOL status; + DWORD record; + + ASSERT(this); + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝ャ繧ウ繝シ繝臥分蜿キ縺ィ繝悶Ο繝繧ッ謨ー繧貞叙蠕 + record = ctrl.cmd[2]; + record <<= 8; + record |= ctrl.cmd[3]; + record <<= 8; + record |= ctrl.cmd[4]; + record <<= 8; + record |= ctrl.cmd[5]; + ctrl.blocks = ctrl.cmd[7]; + ctrl.blocks <<= 8; + ctrl.blocks |= ctrl.cmd[8]; + +#if defined(DISK_LOG) + Log(Log::Normal, "VERIFY繧ウ繝槭Φ繝 繝ャ繧ウ繝シ繝=%08X 繝悶Ο繝繧ッ=%d", record, ctrl.blocks); +#endif // DISK_LOG + + // 繝悶Ο繝繧ッ謨ー0縺ッ蜃ヲ逅縺励↑縺 + if (ctrl.blocks == 0) { + Status(); + return; + } + + // BytChk=0縺ェ繧 + if ((ctrl.cmd[1] & 0x02) == 0) { + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + status = ctrl.unit[lun]->Seek(ctrl.cmd); + if (!status) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); + return; + } + + // 繝繧ケ繝郁ェュ縺ソ霎シ縺ソ + ctrl.length = ctrl.unit[lun]->Read(ctrl.buffer, record); + if (ctrl.length <= 0) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 谺。縺ョ繝悶Ο繝繧ッ繧定ィュ螳 + ctrl.next = record + 1; + + // 繝繝シ繧ソ繧「繧ヲ繝医ヵ繧ァ繝シ繧コ + DataOut(); +} + +//--------------------------------------------------------------------------- +// +// SYNCHRONIZE CACHE +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdSynchronizeCache() +{ + DWORD lun; + + ASSERT(this); + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 謌仙粥縺励◆縺薙→縺ォ縺吶k(譛ェ螳溯」) + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); +} + +//--------------------------------------------------------------------------- +// +// READ DEFECT DATA(10) +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdReadDefectData10() +{ + DWORD lun; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "READ DEFECT DATA(10)繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + ctrl.length = ctrl.unit[lun]->ReadDefectData10(ctrl.cmd, ctrl.buffer); + ASSERT(ctrl.length >= 0); + + if (ctrl.length <= 4) { + Error(); + return; + } + + // 繝繝シ繧ソ繧、繝ウ繝輔ぉ繝シ繧コ + DataIn(); +} + +//--------------------------------------------------------------------------- +// +// READ TOC +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdReadToc() +{ + DWORD lun; + + ASSERT(this); + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + ctrl.length = ctrl.unit[lun]->ReadToc(ctrl.cmd, ctrl.buffer); + if (ctrl.length <= 0) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繝繝シ繧ソ繧、繝ウ繝輔ぉ繝シ繧コ + DataIn(); +} + +//--------------------------------------------------------------------------- +// +// PLAY AUDIO(10) +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdPlayAudio10() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + status = ctrl.unit[lun]->PlayAudio(ctrl.cmd); + if (!status) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); +} + +//--------------------------------------------------------------------------- +// +// PLAY AUDIO MSF +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdPlayAudioMSF() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + status = ctrl.unit[lun]->PlayAudioMSF(ctrl.cmd); + if (!status) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); +} + +//--------------------------------------------------------------------------- +// +// PLAY AUDIO TRACK +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdPlayAudioTrack() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + status = ctrl.unit[lun]->PlayAudioTrack(ctrl.cmd); + if (!status) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); +} + +//--------------------------------------------------------------------------- +// +// MODE SELECT10 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdModeSelect10() +{ + DWORD lun; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "MODE SELECT10繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + ctrl.length = ctrl.unit[lun]->SelectCheck10(ctrl.cmd); + if (ctrl.length <= 0) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繝繝シ繧ソ繧「繧ヲ繝医ヵ繧ァ繝シ繧コ + DataOut(); +} + +//--------------------------------------------------------------------------- +// +// MODE SENSE(10) +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdModeSense10() +{ + DWORD lun; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "MODE SENSE(10)繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + ctrl.length = ctrl.unit[lun]->ModeSense10(ctrl.cmd, ctrl.buffer); + ASSERT(ctrl.length >= 0); + if (ctrl.length == 0) { + Log(Log::Warning, "繧オ繝昴シ繝医@縺ヲ縺縺ェ縺МODE SENSE(10)繝壹シ繧ク $%02X", ctrl.cmd[2]); + + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繝繝シ繧ソ繧、繝ウ繝輔ぉ繝シ繧コ + DataIn(); +} + +//--------------------------------------------------------------------------- +// +// GET MESSAGE(10) +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdGetMessage10() +{ + DWORD lun; + SCSIBR *bridge; + + ASSERT(this); + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝帙せ繝医ヶ繝ェ繝繧ク縺ァ縺ェ縺縺ェ繧峨お繝ゥ繝シ + if (ctrl.unit[lun]->GetID() != MAKEID('S', 'C', 'B', 'R')) { + Error(); + return; + } + + // 繝舌ャ繝輔ぃ縺ョ蜀咲「コ菫(繝悶Ο繝繧ッ豈弱ョ霆「騾√〒縺ッ縺ェ縺縺溘a) + if (ctrl.bufsize < 0x1000000) { + delete ctrl.buffer; + ctrl.bufsize = 0x1000000; + ctrl.buffer = new BYTE[ctrl.bufsize]; + } + + // 繝峨Λ繧、繝悶〒蜃ヲ逅縺吶k + bridge = (SCSIBR*)ctrl.unit[lun]; + ctrl.length = bridge->GetMessage10(ctrl.cmd, ctrl.buffer); + + if (ctrl.length <= 0) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 谺。縺ョ繝悶Ο繝繧ッ繧定ィュ螳 + ctrl.blocks = 1; + ctrl.next = 1; + + // 繝ェ繝シ繝峨ヵ繧ァ繝シ繧コ + DataIn(); +} + +//--------------------------------------------------------------------------- +// +// SEND MESSAGE(10) +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdSendMessage10() +{ + DWORD lun; + + ASSERT(this); + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝帙せ繝医ヶ繝ェ繝繧ク縺ァ縺ェ縺縺ェ繧峨お繝ゥ繝シ + if (ctrl.unit[lun]->GetID() != MAKEID('S', 'C', 'B', 'R')) { + Error(); + return; + } + + // 繝舌ャ繝輔ぃ縺ョ蜀咲「コ菫(繝悶Ο繝繧ッ豈弱ョ霆「騾√〒縺ッ縺ェ縺縺溘a) + if (ctrl.bufsize < 0x1000000) { + delete ctrl.buffer; + ctrl.bufsize = 0x1000000; + ctrl.buffer = new BYTE[ctrl.bufsize]; + } + + // 霆「騾驥上r險ュ螳 + ctrl.length = ctrl.cmd[6]; + ctrl.length <<= 8; + ctrl.length |= ctrl.cmd[7]; + ctrl.length <<= 8; + ctrl.length |= ctrl.cmd[8]; + + if (ctrl.length <= 0) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 谺。縺ョ繝悶Ο繝繧ッ繧定ィュ螳 + ctrl.blocks = 1; + ctrl.next = 1; + + // 繝ゥ繧、繝医ヵ繧ァ繝シ繧コ + DataOut(); +} + +//=========================================================================== +// +// 繝繝シ繧ソ霆「騾 +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繝繝シ繧ソ騾∽ソ。 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::Send() +{ + int len; + BOOL result; + + ASSERT(this); + ASSERT(!ctrl.bus->GetREQ()); + ASSERT(!ctrl.bus->GetACK()); + ASSERT(ctrl.bus->GetIO()); + + // 繝ャ繝ウ繧ー繧ケ!=0縺ェ繧蛾∽ソ。 + if (ctrl.length != 0) { + len = ctrl.bus->SendHandShake( + &ctrl.buffer[ctrl.offset], ctrl.length); + + // 蜈ィ縺ヲ騾∽ソ。縺ァ縺阪↑縺代l縺ー繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ縺ク遘サ陦 + if (len != ctrl.length) { + Error(); + return; + } + + // 繧ェ繝輔そ繝繝医→繝ャ繝ウ繧ー繧ケ + ctrl.offset += ctrl.length; + ctrl.length = 0; + return; + } + + // 繝悶Ο繝繧ッ貂帷ョ励√Μ繧カ繝ォ繝亥晄悄蛹 + ctrl.blocks--; + result = TRUE; + + // 繝繝シ繧ソ蠑輔″蜿悶j蠕後ョ蜃ヲ逅(繝ェ繝シ繝/繝繝シ繧ソ繧、繝ウ縺ョ縺ソ) + if (ctrl.phase == BUS::datain) { + if (ctrl.blocks != 0) { + // 谺。縺ョ繝舌ャ繝輔ぃ繧定ィュ螳(offset, length繧偵そ繝繝医☆繧九%縺ィ) + result = XferIn(ctrl.buffer); + } + } + + // 繝ェ繧カ繝ォ繝FALSE縺ェ繧峨√せ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ縺ク遘サ陦 + if (!result) { + Error(); + return; + } + + // 繝悶Ο繝繧ッ!=0縺ェ繧蛾∽ソ。邯咏カ + if (ctrl.blocks != 0){ + ASSERT(ctrl.length > 0); + ASSERT(ctrl.offset == 0); + return; + } + + // 谺。繝輔ぉ繝シ繧コ縺ォ遘サ蜍 + switch (ctrl.phase) { + // 繝。繝繧サ繝シ繧ク繧、繝ウ繝輔ぉ繝シ繧コ + case BUS::msgin: + // IDENTIFY繝。繝繧サ繝シ繧ク縺ョ諡。蠑オ繝。繝繧サ繝シ繧ク縺ォ蟇セ縺吶k蠢懃ュ秘∽ソ。螳御コ + if (scsi.atnmsg) { + // 繝輔Λ繧ー繧ェ繝 + scsi.atnmsg = FALSE; + + // 繧ウ繝槭Φ繝峨ヵ繧ァ繝シ繧コ + Command(); + } else { + // 繝舌せ繝輔Μ繝シ繝輔ぉ繝シ繧コ + BusFree(); + } + break; + + // 繝繝シ繧ソ繧、繝ウ繝輔ぉ繝シ繧コ + case BUS::datain: + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); + break; + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + case BUS::status: + // 繝。繝繧サ繝シ繧ク繧、繝ウ繝輔ぉ繝シ繧コ + ctrl.length = 1; + ctrl.blocks = 1; + ctrl.buffer[0] = ctrl.message; + MsgIn(); + break; + + // 縺昴ョ莉(縺ゅj縺医↑縺) + default: + ASSERT(FALSE); + break; + } +} + +//--------------------------------------------------------------------------- +// +// 繝繝シ繧ソ蜿嶺ソ。 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::Receive() +{ + BYTE data; + BOOL result; + int i; + int len; + + ASSERT(this); + + // REQ,ACK縺御ク九′縺」縺ヲ縺繧九%縺ィ + ASSERT(!ctrl.bus->GetREQ()); + ASSERT(!ctrl.bus->GetACK()); + ASSERT(!ctrl.bus->GetIO()); + + // 繝ャ繝ウ繧ー繧ケ!=0縺ェ繧牙女菫。 + if (ctrl.length != 0) { + // 蜿嶺ソ。 + len = ctrl.bus->ReceiveHandShake( + &ctrl.buffer[ctrl.offset], ctrl.length); + + // 蜈ィ縺ヲ蜿嶺ソ。縺ァ縺阪↑縺代l縺ー繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ縺ク遘サ陦 + if (len != ctrl.length) { + Error(); + return; + } + + // 繧ェ繝輔そ繝繝医→繝ャ繝ウ繧ー繧ケ + ctrl.offset += ctrl.length; + ctrl.length = 0;; + return; + } + + // 繝悶Ο繝繧ッ貂帷ョ励√Μ繧カ繝ォ繝亥晄悄蛹 + ctrl.blocks--; + result = TRUE; + + // 繝繝シ繧ソ蜿礼炊蠕後ョ蜃ヲ逅(繝輔ぉ繝シ繧コ蛻・) + switch (ctrl.phase) { + + // 繝繝シ繧ソ繧「繧ヲ繝医ヵ繧ァ繝シ繧コ + case BUS::dataout: + if (ctrl.blocks == 0) { + // 縺薙ョ繝舌ャ繝輔ぃ縺ァ邨ゆコ + result = XferOut(FALSE); + } else { + // 谺。縺ョ繝舌ャ繝輔ぃ縺ォ邯壹¥(offset, length繧偵そ繝繝医☆繧九%縺ィ) + result = XferOut(TRUE); + } + break; + + // 繝。繝繧サ繝シ繧ク繧「繧ヲ繝医ヵ繧ァ繝シ繧コ + case BUS::msgout: + ctrl.message = ctrl.buffer[0]; + if (!XferMsg(ctrl.message)) { + // 繝。繝繧サ繝シ繧ク繧「繧ヲ繝医↓螟ア謨励@縺溘i縲∝叉蠎ァ縺ォ繝舌せ繝輔Μ繝シ + BusFree(); + return; + } + + // 繝。繝繧サ繝シ繧ク繧、繝ウ縺ォ蛯吶∴縲√Γ繝繧サ繝シ繧ク繝繝シ繧ソ繧偵け繝ェ繧「縺励※縺翫¥ + ctrl.message = 0x00; + break; + + default: + break; + } + + // 繝ェ繧カ繝ォ繝FALSE縺ェ繧峨√せ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ縺ク遘サ陦 + if (!result) { + Error(); + return; + } + + // 繝悶Ο繝繧ッ!=0縺ェ繧牙女菫。邯咏カ + if (ctrl.blocks != 0){ + ASSERT(ctrl.length > 0); + ASSERT(ctrl.offset == 0); + return; + } + + // 谺。繝輔ぉ繝シ繧コ縺ォ遘サ蜍 + switch (ctrl.phase) { + // 繧ウ繝槭Φ繝峨ヵ繧ァ繝シ繧コ + case BUS::command: + // 繧ウ繝槭Φ繝峨ョ繝シ繧ソ霆「騾 + len = 6; + if (ctrl.buffer[0] >= 0x20 && ctrl.buffer[0] <= 0x7D) { + // 10繝舌う繝CDB + len = 10; + } + for (i = 0; i < len; i++) { + ctrl.cmd[i] = (DWORD)ctrl.buffer[i]; +#if defined(DISK_LOG) + Log(Log::Normal, "繧ウ繝槭Φ繝 $%02X", ctrl.cmd[i]); +#endif // DISK_LOG + } + + // 螳溯。後ヵ繧ァ繝シ繧コ + Execute(); + break; + + // 繝。繝繧サ繝シ繧ク繧「繧ヲ繝医ヵ繧ァ繝シ繧コ + case BUS::msgout: + // ATN縺後い繧オ繝シ繝医@邯壹¢繧矩剞繧翫Γ繝繧サ繝シ繧ク繧「繧ヲ繝医ヵ繧ァ繝シ繧コ繧堤カ咏カ + if (ctrl.bus->GetATN()) { + // 繝繝シ繧ソ霆「騾√ッ1繝舌う繝x1繝悶Ο繝繧ッ + ctrl.offset = 0; + ctrl.length = 1; + ctrl.blocks = 1; + return; + } + + // ATN縺ァ騾∽ソ。縺輔l縺溘Γ繝繧サ繝シ繧ク縺ョ隗」譫 + if (scsi.atnmsg) { + i = 0; + while (i < scsi.msc) { + // 繝。繝繧サ繝シ繧ク縺ョ遞ョ鬘 + data = scsi.msb[i]; + + // ABORT + if (data == 0x06) { +#if defined(DISK_LOG) + Log(Log::Normal, "繝。繝繧サ繝シ繧ク繧ウ繝シ繝 ABORT $%02X", data); +#endif // DISK_LOG + BusFree(); + return; + } + + // BUS DEVICE RESET + if (data == 0x0C) { +#if defined(DISK_LOG) + Log(Log::Normal, "繝。繝繧サ繝シ繧ク繧ウ繝シ繝 BUS DEVICE RESET $%02X", data); +#endif // DISK_LOG + scsi.syncoffset = 0; + BusFree(); + return; + } + + // IDENTIFY + if (data >= 0x80) { +#if defined(DISK_LOG) + Log(Log::Normal, "繝。繝繧サ繝シ繧ク繧ウ繝シ繝 IDENTIFY $%02X", data); +#endif // DISK_LOG + } + + // 諡。蠑オ繝。繝繧サ繝シ繧ク + if (data == 0x01) { +#if defined(DISK_LOG) + Log(Log::Normal, "繝。繝繧サ繝シ繧ク繧ウ繝シ繝 EXTENDED MESSAGE $%02X", data); +#endif // DISK_LOG + + // 蜷梧悄霆「騾√′蜿ッ閭ス縺ェ譎ゅ□縺代メ繧ァ繝繧ッ + if (!scsi.syncenable || scsi.msb[i + 2] != 0x01) { + ctrl.length = 1; + ctrl.blocks = 1; + ctrl.buffer[0] = 0x07; + MsgIn(); + return; + } + + // Transfer period factor(50 x 4 = 200ns縺ォ蛻カ髯) + scsi.syncperiod = scsi.msb[i + 3]; + if (scsi.syncperiod > 50) { + scsi.syncoffset = 50; + } + + // REQ/ACK offset(16縺ォ蛻カ髯) + scsi.syncoffset = scsi.msb[i + 4]; + if (scsi.syncoffset > 16) { + scsi.syncoffset = 16; + } + + // STDR蠢懃ュ斐Γ繝繧サ繝シ繧ク逕滓 + ctrl.length = 5; + ctrl.blocks = 1; + ctrl.buffer[0] = 0x01; + ctrl.buffer[1] = 0x03; + ctrl.buffer[2] = 0x01; + ctrl.buffer[3] = scsi.syncperiod; + ctrl.buffer[4] = scsi.syncoffset; + MsgIn(); + return; + } + + // 谺。縺ク + i++; + } + } + + // ATN繝。繝繧サ繝シ繧ク蜿嶺ソ。繧ケ繧ソ繝シ繧ソ繧ケ蛻晄悄蛹 + scsi.atnmsg = FALSE; + + // 繧ウ繝槭Φ繝峨ヵ繧ァ繝シ繧コ + Command(); + break; + + // 繝繝シ繧ソ繧「繧ヲ繝医ヵ繧ァ繝シ繧コ + case BUS::dataout: + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); + break; + + // 縺昴ョ莉(縺ゅj縺医↑縺) + default: + ASSERT(FALSE); + break; + } +} + +//--------------------------------------------------------------------------- +// +// 繝繝シ繧ソ霆「騾`SG +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSIDEV::XferMsg(DWORD msg) +{ + ASSERT(this); + ASSERT(ctrl.phase == BUS::msgout); + + // 繝。繝繧サ繝シ繧ク繧「繧ヲ繝医ョ繝シ繧ソ縺ョ菫晏ュ + if (scsi.atnmsg) { + scsi.msb[scsi.msc] = msg; + scsi.msc++; + scsi.msc %= 256; + } + + return TRUE; +} diff --git a/src/raspberrypi/disk.h b/src/raspberrypi/disk.h new file mode 100644 index 00000000..0d440890 --- /dev/null +++ b/src/raspberrypi/disk.h @@ -0,0 +1,1108 @@ +//--------------------------------------------------------------------------- +// +// X68000 EMULATOR "XM6" +// +// Copyright (C) 2001-2006 シーシゥシ(ytanaka@ipc-tokai.or.jp) +// Copyright (C) 2014-2018 GIMONS +// +// XM6i +// Copyright (C) 2010-2015 isaki@NetBSD.org +// +// Imported sava's Anex86/T98Next image and MO format support patch. +// +// [ 繝繧」繧ケ繧ッ ] +// +//--------------------------------------------------------------------------- + +#if !defined(disk_h) +#define disk_h + +#include "log.h" +#include "scsi.h" + +//--------------------------------------------------------------------------- +// +// 繧ィ繝ゥ繝シ螳夂セゥ(REQUEST SENSE縺ァ霑斐&繧後k繧サ繝ウ繧ケ繧ウ繝シ繝) +// +// MSB 莠育エ(0x00) +// 繧サ繝ウ繧ケ繧ュ繝シ +// 諡。蠑オ繧サ繝ウ繧ケ繧ウ繝シ繝(ASC) +// LSB 諡。蠑オ繧サ繝ウ繧ケ繧ウ繝シ繝峨け繧ゥ繝ェ繝輔ぃ繧、繧「(ASCQ) +// +//--------------------------------------------------------------------------- +#define DISK_NOERROR 0x00000000 // NO ADDITIONAL SENSE INFO. +#define DISK_DEVRESET 0x00062900 // POWER ON OR RESET OCCURED +#define DISK_NOTREADY 0x00023a00 // MEDIUM NOT PRESENT +#define DISK_ATTENTION 0x00062800 // MEDIUM MAY HAVE CHANGED +#define DISK_PREVENT 0x00045302 // MEDIUM REMOVAL PREVENTED +#define DISK_READFAULT 0x00031100 // UNRECOVERED READ ERROR +#define DISK_WRITEFAULT 0x00030300 // PERIPHERAL DEVICE WRITE FAULT +#define DISK_WRITEPROTECT 0x00042700 // WRITE PROTECTED +#define DISK_MISCOMPARE 0x000e1d00 // MISCOMPARE DURING VERIFY +#define DISK_INVALIDCMD 0x00052000 // INVALID COMMAND OPERATION CODE +#define DISK_INVALIDLBA 0x00052100 // LOGICAL BLOCK ADDR. OUT OF RANGE +#define DISK_INVALIDCDB 0x00052400 // INVALID FIELD IN CDB +#define DISK_INVALIDLUN 0x00052500 // LOGICAL UNIT NOT SUPPORTED +#define DISK_INVALIDPRM 0x00052600 // INVALID FIELD IN PARAMETER LIST +#define DISK_INVALIDMSG 0x00054900 // INVALID MESSAGE ERROR +#define DISK_PARAMLEN 0x00051a00 // PARAMETERS LIST LENGTH ERROR +#define DISK_PARAMNOT 0x00052601 // PARAMETERS NOT SUPPORTED +#define DISK_PARAMVALUE 0x00052602 // PARAMETERS VALUE INVALID +#define DISK_PARAMSAVE 0x00053900 // SAVING PARAMETERS NOT SUPPORTED +#define DISK_NODEFECT 0x00010000 // DEFECT LIST NOT FOUND + +#if 0 +#define DISK_AUDIOPROGRESS 0x00??0011 // AUDIO PLAY IN PROGRESS +#define DISK_AUDIOPAUSED 0x00??0012 // AUDIO PLAY PAUSED +#define DISK_AUDIOSTOPPED 0x00??0014 // AUDIO PLAY STOPPED DUE TO ERROR +#define DISK_AUDIOCOMPLETE 0x00??0013 // AUDIO PLAY SUCCESSFULLY COMPLETED +#endif + +//=========================================================================== +// +// 繝繧」繧ケ繧ッ繝医Λ繝繧ッ +// +//=========================================================================== +class DiskTrack +{ +public: + // 蜀驛ィ繝繝シ繧ソ螳夂セゥ + typedef struct { + int track; // 繝医Λ繝繧ッ繝翫Φ繝舌シ + int size; // 繧サ繧ッ繧ソ繧オ繧、繧コ(8 or 9) + int sectors; // 繧サ繧ッ繧ソ謨ー(<=0x100) + DWORD length; // 繝繝シ繧ソ繝舌ャ繝輔ぃ髟キ + BYTE *buffer; // 繝繝シ繧ソ繝舌ャ繝輔ぃ + BOOL init; // 繝ュ繝シ繝画ク医∩縺 + BOOL changed; // 螟画峩貂医∩繝輔Λ繧ー + DWORD maplen; // 螟画峩貂医∩繝槭ャ繝鈴聞 + BOOL *changemap; // 螟画峩貂医∩繝槭ャ繝 + BOOL raw; // RAW繝「繝シ繝 + off64_t imgoffset; // 螳溘ョ繝シ繧ソ縺セ縺ァ縺ョ繧ェ繝輔そ繝繝 + } disktrk_t; + +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + DiskTrack(); + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + virtual ~DiskTrack(); + // 繝繧ケ繝医Λ繧ッ繧ソ + void FASTCALL Init(int track, int size, int sectors, BOOL raw = FALSE, + off64_t imgoff = 0); + // 蛻晄悄蛹 + BOOL FASTCALL Load(const Filepath& path); + // 繝ュ繝シ繝 + BOOL FASTCALL Save(const Filepath& path); + // 繧サ繝シ繝 + + // 繝ェ繝シ繝峨サ繝ゥ繧、繝 + BOOL FASTCALL Read(BYTE *buf, int sec) const; + // 繧サ繧ッ繧ソ繝ェ繝シ繝 + BOOL FASTCALL Write(const BYTE *buf, int sec); + // 繧サ繧ッ繧ソ繝ゥ繧、繝 + + // 縺昴ョ莉 + int FASTCALL GetTrack() const { return dt.track; } + // 繝医Λ繝繧ッ蜿門セ + BOOL FASTCALL IsChanged() const { return dt.changed; } + // 螟画峩繝輔Λ繧ー繝√ぉ繝繧ッ + +private: + // 蜀驛ィ繝繝シ繧ソ + disktrk_t dt; + // 蜀驛ィ繝繝シ繧ソ +}; + +//=========================================================================== +// +// 繝繧」繧ケ繧ッ繧ュ繝」繝繧キ繝・ +// +//=========================================================================== +class DiskCache +{ +public: + // 蜀驛ィ繝繝シ繧ソ螳夂セゥ + typedef struct { + DiskTrack *disktrk; // 蜑イ繧雁ス薙※繝医Λ繝繧ッ + DWORD serial; // 譛邨ゅす繝ェ繧「繝ォ + } cache_t; + + // 繧ュ繝」繝繧キ繝・謨ー + enum { + CacheMax = 16 // 繧ュ繝」繝繧キ繝・縺吶k繝医Λ繝繧ッ謨ー + }; + +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + DiskCache(const Filepath& path, int size, int blocks, + off64_t imgoff = 0); + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + virtual ~DiskCache(); + // 繝繧ケ繝医Λ繧ッ繧ソ + void FASTCALL SetRawMode(BOOL raw); + // CD-ROM raw繝「繝シ繝芽ィュ螳 + + // 繧「繧ッ繧サ繧ケ + BOOL FASTCALL Save(); + // 蜈ィ繧サ繝シ繝厄シ隗」謾セ + BOOL FASTCALL Read(BYTE *buf, int block); + // 繧サ繧ッ繧ソ繝ェ繝シ繝 + BOOL FASTCALL Write(const BYTE *buf, int block); + // 繧サ繧ッ繧ソ繝ゥ繧、繝 + BOOL FASTCALL GetCache(int index, int& track, DWORD& serial) const; + // 繧ュ繝」繝繧キ繝・諠蝣ア蜿門セ + +private: + // 蜀驛ィ邂。逅 + void FASTCALL Clear(); + // 繝医Λ繝繧ッ繧偵☆縺ケ縺ヲ繧ッ繝ェ繧「 + DiskTrack* FASTCALL Assign(int track); + // 繝医Λ繝繧ッ縺ョ繝ュ繝シ繝 + BOOL FASTCALL Load(int index, int track, DiskTrack *disktrk = NULL); + // 繝医Λ繝繧ッ縺ョ繝ュ繝シ繝 + void FASTCALL Update(); + // 繧キ繝ェ繧「繝ォ逡ェ蜿キ譖エ譁ー + + // 蜀驛ィ繝繝シ繧ソ + cache_t cache[CacheMax]; + // 繧ュ繝」繝繧キ繝・邂。逅 + DWORD serial; + // 譛邨ゅい繧ッ繧サ繧ケ繧キ繝ェ繧「繝ォ繝翫Φ繝 + Filepath sec_path; + // 繝代せ + int sec_size; + // 繧サ繧ッ繧ソ繧オ繧、繧コ(8 or 9 or 11) + int sec_blocks; + // 繧サ繧ッ繧ソ繝悶Ο繝繧ッ謨ー + BOOL cd_raw; + // CD-ROM RAW繝「繝シ繝 + off64_t imgoffset; + // 螳溘ョ繝シ繧ソ縺セ縺ァ縺ョ繧ェ繝輔そ繝繝 +}; + +//=========================================================================== +// +// 繝繧」繧ケ繧ッ +// +//=========================================================================== +class Disk +{ +public: + // 蜀驛ィ繝ッ繝シ繧ッ + typedef struct { + DWORD id; // 繝。繝繧」繧「ID + BOOL ready; // 譛牙柑縺ェ繝繧」繧ケ繧ッ + BOOL writep; // 譖ク縺崎セシ縺ソ遖∵ュ「 + BOOL readonly; // 隱ュ縺ソ霎シ縺ソ蟆ら畑 + BOOL removable; // 蜿悶j螟悶@ + BOOL lock; // 繝ュ繝繧ッ + BOOL attn; // 繧「繝繝ウ繧キ繝ァ繝ウ + BOOL reset; // 繝ェ繧サ繝繝 + int size; // 繧サ繧ッ繧ソ繧オ繧、繧コ + DWORD blocks; // 邱上そ繧ッ繧ソ謨ー + DWORD lun; // LUN + DWORD code; // 繧ケ繝繝シ繧ソ繧ケ繧ウ繝シ繝 + DiskCache *dcache; // 繝繧」繧ケ繧ッ繧ュ繝」繝繧キ繝・ + off64_t imgoffset; // 螳溘ョ繝シ繧ソ縺セ縺ァ縺ョ繧ェ繝輔そ繝繝 + } disk_t; + +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + Disk(); + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + virtual ~Disk(); + // 繝繧ケ繝医Λ繧ッ繧ソ + virtual void FASTCALL Reset(); + // 繝繝舌う繧ケ繝ェ繧サ繝繝 +#ifndef RASCSI + virtual BOOL FASTCALL Save(Fileio *fio, int ver); + // 繧サ繝シ繝 + virtual BOOL FASTCALL Load(Fileio *fio, int ver); + // 繝ュ繝シ繝 +#endif // RASCSI + + // ID + DWORD FASTCALL GetID() const { return disk.id; } + // 繝。繝繧」繧「ID蜿門セ + BOOL FASTCALL IsNULL() const; + // NULL繝√ぉ繝繧ッ + BOOL FASTCALL IsSASI() const; + // SASI繝√ぉ繝繧ッ + + // 繝。繝繧」繧「謫堺ス + virtual BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE); + // 繧ェ繝シ繝励Φ + void FASTCALL GetPath(Filepath& path) const; + // 繝代せ蜿門セ + void FASTCALL Eject(BOOL force); + // 繧、繧ク繧ァ繧ッ繝 + BOOL FASTCALL IsReady() const { return disk.ready; } + // Ready繝√ぉ繝繧ッ + void FASTCALL WriteP(BOOL flag); + // 譖ク縺崎セシ縺ソ遖∵ュ「 + BOOL FASTCALL IsWriteP() const { return disk.writep; } + // 譖ク縺崎セシ縺ソ遖∵ュ「繝√ぉ繝繧ッ + BOOL FASTCALL IsReadOnly() const { return disk.readonly; } + // Read Only繝√ぉ繝繧ッ + BOOL FASTCALL IsRemovable() const { return disk.removable; } + // 繝ェ繝繝シ繝舌ヶ繝ォ繝√ぉ繝繧ッ + BOOL FASTCALL IsLocked() const { return disk.lock; } + // 繝ュ繝繧ッ繝√ぉ繝繧ッ + BOOL FASTCALL IsAttn() const { return disk.attn; } + // 莠、謠帙メ繧ァ繝繧ッ + BOOL FASTCALL Flush(); + // 繧ュ繝」繝繧キ繝・繝輔Λ繝繧キ繝・ + void FASTCALL GetDisk(disk_t *buffer) const; + // 蜀驛ィ繝ッ繝シ繧ッ蜿門セ + + // 繝励Ο繝代ユ繧」 + void FASTCALL SetLUN(DWORD lun) { disk.lun = lun; } + // LUN繧サ繝繝 + DWORD FASTCALL GetLUN() { return disk.lun; } + // LUN蜿門セ + // 繧ウ繝槭Φ繝 + virtual int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); + // INQUIRY繧ウ繝槭Φ繝 + virtual int FASTCALL RequestSense(const DWORD *cdb, BYTE *buf); + // REQUEST SENSE繧ウ繝槭Φ繝 + int FASTCALL SelectCheck(const DWORD *cdb); + // SELECT繝√ぉ繝繧ッ + int FASTCALL SelectCheck10(const DWORD *cdb); + // SELECT(10)繝√ぉ繝繧ッ + virtual BOOL FASTCALL ModeSelect(const DWORD *cdb, const BYTE *buf, int length); + // MODE SELECT繧ウ繝槭Φ繝 + virtual int FASTCALL ModeSense(const DWORD *cdb, BYTE *buf); + // MODE SENSE繧ウ繝槭Φ繝 + virtual int FASTCALL ModeSense10(const DWORD *cdb, BYTE *buf); + // MODE SENSE(10)繧ウ繝槭Φ繝 + int FASTCALL ReadDefectData10(const DWORD *cdb, BYTE *buf); + // READ DEFECT DATA(10)繧ウ繝槭Φ繝 + virtual BOOL FASTCALL TestUnitReady(const DWORD *cdb); + // TEST UNIT READY繧ウ繝槭Φ繝 + BOOL FASTCALL Rezero(const DWORD *cdb); + // REZERO繧ウ繝槭Φ繝 + BOOL FASTCALL Format(const DWORD *cdb); + // FORMAT UNIT繧ウ繝槭Φ繝 + BOOL FASTCALL Reassign(const DWORD *cdb); + // REASSIGN UNIT繧ウ繝槭Φ繝 + virtual int FASTCALL Read(BYTE *buf, DWORD block); + // READ繧ウ繝槭Φ繝 + int FASTCALL WriteCheck(DWORD block); + // WRITE繝√ぉ繝繧ッ + BOOL FASTCALL Write(const BYTE *buf, DWORD block); + // WRITE繧ウ繝槭Φ繝 + BOOL FASTCALL Seek(const DWORD *cdb); + // SEEK繧ウ繝槭Φ繝 + BOOL FASTCALL Assign(const DWORD *cdb); + // ASSIGN繧ウ繝槭Φ繝 + BOOL FASTCALL Specify(const DWORD *cdb); + // SPECIFY繧ウ繝槭Φ繝 + BOOL FASTCALL StartStop(const DWORD *cdb); + // START STOP UNIT繧ウ繝槭Φ繝 + BOOL FASTCALL SendDiag(const DWORD *cdb); + // SEND DIAGNOSTIC繧ウ繝槭Φ繝 + BOOL FASTCALL Removal(const DWORD *cdb); + // PREVENT/ALLOW MEDIUM REMOVAL繧ウ繝槭Φ繝 + int FASTCALL ReadCapacity(const DWORD *cdb, BYTE *buf); + // READ CAPACITY繧ウ繝槭Φ繝 + BOOL FASTCALL Verify(const DWORD *cdb); + // VERIFY繧ウ繝槭Φ繝 + virtual int FASTCALL ReadToc(const DWORD *cdb, BYTE *buf); + // READ TOC繧ウ繝槭Φ繝 + virtual BOOL FASTCALL PlayAudio(const DWORD *cdb); + // PLAY AUDIO繧ウ繝槭Φ繝 + virtual BOOL FASTCALL PlayAudioMSF(const DWORD *cdb); + // PLAY AUDIO MSF繧ウ繝槭Φ繝 + virtual BOOL FASTCALL PlayAudioTrack(const DWORD *cdb); + // PLAY AUDIO TRACK繧ウ繝槭Φ繝 + void FASTCALL InvalidCmd() { disk.code = DISK_INVALIDCMD; } + // 繧オ繝昴シ繝医@縺ヲ縺縺ェ縺繧ウ繝槭Φ繝 + + // 縺昴ョ莉 + void SetCacheWB(BOOL enable) { cache_wb = enable; } + // 繧ュ繝」繝繧キ繝・繝「繝シ繝芽ィュ螳 + +protected: + // 繧オ繝門ヲ逅 + virtual int FASTCALL AddError(BOOL change, BYTE *buf); + // 繧ィ繝ゥ繝シ繝壹シ繧ク霑ス蜉 + virtual int FASTCALL AddFormat(BOOL change, BYTE *buf); + // 繝輔か繝シ繝槭ャ繝医壹シ繧ク霑ス蜉 + virtual int FASTCALL AddDrive(BOOL change, BYTE *buf); + // 繝峨Λ繧、繝悶壹シ繧ク霑ス蜉 + int FASTCALL AddOpt(BOOL change, BYTE *buf); + // 繧ェ繝励ユ繧」繧ォ繝ォ繝壹シ繧ク霑ス蜉 + int FASTCALL AddCache(BOOL change, BYTE *buf); + // 繧ュ繝」繝繧キ繝・繝壹シ繧ク霑ス蜉 + int FASTCALL AddCDROM(BOOL change, BYTE *buf); + // CD-ROM繝壹シ繧ク霑ス蜉 + int FASTCALL AddCDDA(BOOL change, BYTE *buf); + // CD-DA繝壹シ繧ク霑ス蜉 + virtual int FASTCALL AddVendor(int page, BOOL change, BYTE *buf); + // 繝吶Φ繝迚ケ谿翫壹シ繧ク霑ス蜉 + BOOL FASTCALL CheckReady(); + // 繝ャ繝繧」繝√ぉ繝繧ッ + + // 蜀驛ィ繝繝シ繧ソ + disk_t disk; + // 繝繧」繧ケ繧ッ蜀驛ィ繝繝シ繧ソ + Filepath diskpath; + // 繝代せ(GetPath逕ィ) + BOOL cache_wb; + // 繧ュ繝」繝繧キ繝・繝「繝シ繝 +}; + +//=========================================================================== +// +// SASI 繝上シ繝峨ョ繧」繧ケ繧ッ +// +//=========================================================================== +class SASIHD : public Disk +{ +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + SASIHD(); + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + void FASTCALL Reset(); + // 繝ェ繧サ繝繝 + BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE); + // 繧ェ繝シ繝励Φ + // 繧ウ繝槭Φ繝 + int FASTCALL RequestSense(const DWORD *cdb, BYTE *buf); + // REQUEST SENSE繧ウ繝槭Φ繝 +}; + +//=========================================================================== +// +// SCSI 繝上シ繝峨ョ繧」繧ケ繧ッ +// +//=========================================================================== +class SCSIHD : public Disk +{ +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + SCSIHD(); + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + void FASTCALL Reset(); + // 繝ェ繧サ繝繝 + BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE); + // 繧ェ繝シ繝励Φ + + // 繧ウ繝槭Φ繝 + int FASTCALL Inquiry( + const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); + // INQUIRY繧ウ繝槭Φ繝 + BOOL FASTCALL ModeSelect(const DWORD *cdb, const BYTE *buf, int length); + // MODE SELECT(6)繧ウ繝槭Φ繝 +}; + +//=========================================================================== +// +// SCSI 繝上シ繝峨ョ繧」繧ケ繧ッ(PC-9801-55 NEC邏疲ュ」/Anex86/T98Next) +// +//=========================================================================== +class SCSIHD_NEC : public SCSIHD +{ +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + SCSIHD_NEC(); + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + + BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE); + // 繧ェ繝シ繝励Φ + + // 繧ウ繝槭Φ繝 + int FASTCALL Inquiry( + const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); + // INQUIRY繧ウ繝槭Φ繝 + + // 繧オ繝門ヲ逅 + int FASTCALL AddError(BOOL change, BYTE *buf); + // 繧ィ繝ゥ繝シ繝壹シ繧ク霑ス蜉 + int FASTCALL AddFormat(BOOL change, BYTE *buf); + // 繝輔か繝シ繝槭ャ繝医壹シ繧ク霑ス蜉 + int FASTCALL AddDrive(BOOL change, BYTE *buf); + // 繝峨Λ繧、繝悶壹シ繧ク霑ス蜉 + +private: + int cylinders; + // 繧キ繝ェ繝ウ繝謨ー + int heads; + // 繝倥ャ繝画焚 + int sectors; + // 繧サ繧ッ繧ソ謨ー + int sectorsize; + // 繧サ繧ッ繧ソ繧オ繧、繧コ + off64_t imgoffset; + // 繧、繝。繝シ繧ク繧ェ繝輔そ繝繝 + off64_t imgsize; + // 繧、繝。繝シ繧ク繧オ繧、繧コ +}; + +//=========================================================================== +// +// SCSI 繝上シ繝峨ョ繧」繧ケ繧ッ(Macintosh Apple邏疲ュ」) +// +//=========================================================================== +class SCSIHD_APPLE : public SCSIHD +{ +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + SCSIHD_APPLE(); + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + // 繧ウ繝槭Φ繝 + int FASTCALL Inquiry( + const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); + // INQUIRY繧ウ繝槭Φ繝 + + // 繧オ繝門ヲ逅 + int FASTCALL AddVendor(int page, BOOL change, BYTE *buf); + // 繝吶Φ繝迚ケ谿翫壹シ繧ク霑ス蜉 +}; + +//=========================================================================== +// +// SCSI 蜈臥」∵ー励ョ繧」繧ケ繧ッ +// +//=========================================================================== +class SCSIMO : public Disk +{ +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + SCSIMO(); + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE); + // 繧ェ繝シ繝励Φ +#ifndef RASCSI + BOOL FASTCALL Load(Fileio *fio, int ver); + // 繝ュ繝シ繝 +#endif // RASCSI + + // 繧ウ繝槭Φ繝 + int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); + // INQUIRY繧ウ繝槭Φ繝 + BOOL FASTCALL ModeSelect(const DWORD *cdb, const BYTE *buf, int length); + // MODE SELECT(6)繧ウ繝槭Φ繝 + + // 繧オ繝門ヲ逅 + int FASTCALL AddVendor(int page, BOOL change, BYTE *buf); + // 繝吶Φ繝迚ケ谿翫壹シ繧ク霑ス蜉 +}; + +//--------------------------------------------------------------------------- +// +// 繧ッ繝ゥ繧ケ蜈郁。悟ョ夂セゥ +// +//--------------------------------------------------------------------------- +class SCSICD; + +//=========================================================================== +// +// CD-ROM 繝医Λ繝繧ッ +// +//=========================================================================== +class CDTrack +{ +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + CDTrack(SCSICD *scsicd); + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + virtual ~CDTrack(); + // 繝繧ケ繝医Λ繧ッ繧ソ + BOOL FASTCALL Init(int track, DWORD first, DWORD last); + // 蛻晄悄蛹 + + // 繝励Ο繝代ユ繧」 + void FASTCALL SetPath(BOOL cdda, const Filepath& path); + // 繝代せ險ュ螳 + void FASTCALL GetPath(Filepath& path) const; + // 繝代せ蜿門セ + void FASTCALL AddIndex(int index, DWORD lba); + // 繧、繝ウ繝繝繧ッ繧ケ霑ス蜉 + DWORD FASTCALL GetFirst() const; + // 髢句ァ記BA蜿門セ + DWORD FASTCALL GetLast() const; + // 邨らォッLBA蜿門セ + DWORD FASTCALL GetBlocks() const; + // 繝悶Ο繝繧ッ謨ー蜿門セ + int FASTCALL GetTrackNo() const; + // 繝医Λ繝繧ッ逡ェ蜿キ蜿門セ + BOOL FASTCALL IsValid(DWORD lba) const; + // 譛牙柑縺ェLBA縺 + BOOL FASTCALL IsAudio() const; + // 繧ェ繝シ繝繧」繧ェ繝医Λ繝繧ッ縺 + +private: + SCSICD *cdrom; + // 隕ェ繝繝舌う繧ケ + BOOL valid; + // 譛牙柑縺ェ繝医Λ繝繧ッ + int track_no; + // 繝医Λ繝繧ッ逡ェ蜿キ + DWORD first_lba; + // 髢句ァ記BA + DWORD last_lba; + // 邨ゆコLBA + BOOL audio; + // 繧ェ繝シ繝繧」繧ェ繝医Λ繝繧ッ繝輔Λ繧ー + BOOL raw; + // RAW繝繝シ繧ソ繝輔Λ繧ー + Filepath imgpath; + // 繧、繝。繝シ繧ク繝輔ぃ繧、繝ォ繝代せ +}; + +//=========================================================================== +// +// CD-DA 繝舌ャ繝輔ぃ +// +//=========================================================================== +class CDDABuf +{ +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + CDDABuf(); + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + virtual ~CDDABuf(); + // 繝繧ケ繝医Λ繧ッ繧ソ +#if 0 + BOOL Init(); + // 蛻晄悄蛹 + BOOL FASTCALL Load(const Filepath& path); + // 繝ュ繝シ繝 + BOOL FASTCALL Save(const Filepath& path); + // 繧サ繝シ繝 + + // API + void FASTCALL Clear(); + // 繝舌ャ繝輔ぃ繧ッ繝ェ繧「 + BOOL FASTCALL Open(Filepath& path); + // 繝輔ぃ繧、繝ォ謖螳 + BOOL FASTCALL GetBuf(DWORD *buffer, int frames); + // 繝舌ャ繝輔ぃ蜿門セ + BOOL FASTCALL IsValid(); + // 譛牙柑繝√ぉ繝繧ッ + BOOL FASTCALL ReadReq(); + // 隱ュ縺ソ霎シ縺ソ隕∵ア + BOOL FASTCALL IsEnd() const; + // 邨ゆコ繝√ぉ繝繧ッ + +private: + Filepath wavepath; + // Wave繝代せ + BOOL valid; + // 繧ェ繝シ繝励Φ邨先棡 + DWORD *buf; + // 繝繝シ繧ソ繝舌ャ繝輔ぃ + DWORD read; + // Read繝昴う繝ウ繧ソ + DWORD write; + // Write繝昴う繝ウ繧ソ + DWORD num; + // 繝繝シ繧ソ譛牙柑謨ー + DWORD rest; + // 繝輔ぃ繧、繝ォ谿九j繧オ繧、繧コ +#endif +}; + +//=========================================================================== +// +// SCSI CD-ROM +// +//=========================================================================== +class SCSICD : public Disk +{ +public: + // 繝医Λ繝繧ッ謨ー + enum { + TrackMax = 96 // 繝医Λ繝繧ッ譛螟ァ謨ー + }; + +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + SCSICD(); + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + virtual ~SCSICD(); + // 繝繧ケ繝医Λ繧ッ繧ソ + BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE); + // 繧ェ繝シ繝励Φ +#ifndef RASCSI + BOOL FASTCALL Load(Fileio *fio, int ver); + // 繝ュ繝シ繝 +#endif // RASCSI + + // 繧ウ繝槭Φ繝 + int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); + // INQUIRY繧ウ繝槭Φ繝 + int FASTCALL Read(BYTE *buf, DWORD block); + // READ繧ウ繝槭Φ繝 + int FASTCALL ReadToc(const DWORD *cdb, BYTE *buf); + // READ TOC繧ウ繝槭Φ繝 + BOOL FASTCALL PlayAudio(const DWORD *cdb); + // PLAY AUDIO繧ウ繝槭Φ繝 + BOOL FASTCALL PlayAudioMSF(const DWORD *cdb); + // PLAY AUDIO MSF繧ウ繝槭Φ繝 + BOOL FASTCALL PlayAudioTrack(const DWORD *cdb); + // PLAY AUDIO TRACK繧ウ繝槭Φ繝 + + // CD-DA + BOOL FASTCALL NextFrame(); + // 繝輔Ξ繝シ繝騾夂衍 + void FASTCALL GetBuf(DWORD *buffer, int samples, DWORD rate); + // CD-DA繝舌ャ繝輔ぃ蜿門セ + + // LBA-MSF螟画鋤 + void FASTCALL LBAtoMSF(DWORD lba, BYTE *msf) const; + // LBA竊樽SF螟画鋤 + DWORD FASTCALL MSFtoLBA(const BYTE *msf) const; + // MSF竊鱈BA螟画鋤 + +private: + // 繧ェ繝シ繝励Φ + BOOL FASTCALL OpenCue(const Filepath& path); + // 繧ェ繝シ繝励Φ(CUE) + BOOL FASTCALL OpenIso(const Filepath& path); + // 繧ェ繝シ繝励Φ(ISO) + BOOL FASTCALL OpenPhysical(const Filepath& path); + // 繧ェ繝シ繝励Φ(Physical) + BOOL rawfile; + // RAW繝輔Λ繧ー + + // 繝医Λ繝繧ッ邂。逅 + void FASTCALL ClearTrack(); + // 繝医Λ繝繧ッ繧ッ繝ェ繧「 + int FASTCALL SearchTrack(DWORD lba) const; + // 繝医Λ繝繧ッ讀懃エ「 + CDTrack* track[TrackMax]; + // 繝医Λ繝繧ッ繧ェ繝悶ず繧ァ繧ッ繝 + int tracks; + // 繝医Λ繝繧ッ繧ェ繝悶ず繧ァ繧ッ繝域怏蜉ケ謨ー + int dataindex; + // 迴セ蝨ィ縺ョ繝繝シ繧ソ繝医Λ繝繧ッ + int audioindex; + // 迴セ蝨ィ縺ョ繧ェ繝シ繝繧」繧ェ繝医Λ繝繧ッ + + int frame; + // 繝輔Ξ繝シ繝逡ェ蜿キ + +#if 0 + CDDABuf da_buf; + // CD-DA繝舌ャ繝輔ぃ + int da_num; + // CD-DA繝医Λ繝繧ッ謨ー + int da_cur; + // CD-DA繧ォ繝ャ繝ウ繝医ヨ繝ゥ繝繧ッ + int da_next; + // CD-DA繝阪け繧ケ繝医ヨ繝ゥ繝繧ッ + BOOL da_req; + // CD-DA繝繝シ繧ソ隕∵ア +#endif +}; + +//=========================================================================== +// +// SCSI 繝帙せ繝医ヶ繝ェ繝繧ク +// +//=========================================================================== +class CTapDriver; +class CFileSys; +class SCSIBR : public Disk +{ +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + SCSIBR(); + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + virtual ~SCSIBR(); + // 繝繧ケ繝医Λ繧ッ繧ソ + + // 繧ウ繝槭Φ繝 + int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); + // INQUIRY繧ウ繝槭Φ繝 + BOOL FASTCALL TestUnitReady(const DWORD *cdb); + // TEST UNIT READY繧ウ繝槭Φ繝 + int FASTCALL GetMessage10(const DWORD *cdb, BYTE *buf); + // GET MESSAGE10繧ウ繝槭Φ繝 + BOOL FASTCALL SendMessage10(const DWORD *cdb, BYTE *buf); + // SEND MESSAGE10繧ウ繝槭Φ繝 + +private: + int FASTCALL GetMacAddr(BYTE *buf); + // MAC繧「繝峨Ξ繧ケ蜿門セ + void FASTCALL SetMacAddr(BYTE *buf); + // MAC繧「繝峨Ξ繧ケ險ュ螳 + void FASTCALL ReceivePacket(); + // 繝代こ繝繝亥女菫。 + void FASTCALL GetPacketBuf(BYTE *buf); + // 繝代こ繝繝亥叙蠕 + void FASTCALL SendPacket(BYTE *buf, int len); + // 繝代こ繝繝磯∽ソ。 + + CTapDriver *tap; + // TAP繝峨Λ繧、繝 + BOOL m_bTapEnable; + // TAP譛牙柑繝輔Λ繧ー + BYTE mac_addr[6]; + // MAC繧「繝峨Ξ繧ケ + int packet_len; + // 蜿嶺ソ。繝代こ繝繝医し繧、繧コ + BYTE packet_buf[0x1000]; + // 蜿嶺ソ。繝代こ繝繝医ヰ繝繝輔ぃ + BOOL packet_enable; + // 蜿嶺ソ。繝代こ繝繝域怏蜉ケ + + + int FASTCALL ReadFsResult(BYTE *buf); + // 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝隱ュ縺ソ霎シ縺ソ(邨先棡繧ウ繝シ繝) + int FASTCALL ReadFsOut(BYTE *buf); + // 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝隱ュ縺ソ霎シ縺ソ(霑泌唆繝繝シ繧ソ) + int FASTCALL ReadFsOpt(BYTE *buf); + // 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝隱ュ縺ソ霎シ縺ソ(繧ェ繝励す繝ァ繝ウ繝繝シ繧ソ) + void FASTCALL WriteFs(int func, BYTE *buf); + // 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝譖ク縺崎セシ縺ソ(螳溯。) + void FASTCALL WriteFsOpt(BYTE *buf, int len); + // 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝譖ク縺崎セシ縺ソ(繧ェ繝励す繝ァ繝ウ繝繝シ繧ソ) + + // 繧ウ繝槭Φ繝峨ワ繝ウ繝峨Λ + void FASTCALL FS_InitDevice(BYTE *buf); + // $40 - 繝繝舌う繧ケ襍キ蜍 + void FASTCALL FS_CheckDir(BYTE *buf); + // $41 - 繝繧」繝ャ繧ッ繝医Μ繝√ぉ繝繧ッ + void FASTCALL FS_MakeDir(BYTE *buf); + // $42 - 繝繧」繝ャ繧ッ繝医Μ菴懈 + void FASTCALL FS_RemoveDir(BYTE *buf); + // $43 - 繝繧」繝ャ繧ッ繝医Μ蜑企勁 + void FASTCALL FS_Rename(BYTE *buf); + // $44 - 繝輔ぃ繧、繝ォ蜷榊、画峩 + void FASTCALL FS_Delete(BYTE *buf); + // $45 - 繝輔ぃ繧、繝ォ蜑企勁 + void FASTCALL FS_Attribute(BYTE *buf); + // $46 - 繝輔ぃ繧、繝ォ螻樊ァ蜿門セ/險ュ螳 + void FASTCALL FS_Files(BYTE *buf); + // $47 - 繝輔ぃ繧、繝ォ讀懃エ「 + void FASTCALL FS_NFiles(BYTE *buf); + // $48 - 繝輔ぃ繧、繝ォ谺。讀懃エ「 + void FASTCALL FS_Create(BYTE *buf); + // $49 - 繝輔ぃ繧、繝ォ菴懈 + void FASTCALL FS_Open(BYTE *buf); + // $4A - 繝輔ぃ繧、繝ォ繧ェ繝シ繝励Φ + void FASTCALL FS_Close(BYTE *buf); + // $4B - 繝輔ぃ繧、繝ォ繧ッ繝ュ繝シ繧コ + void FASTCALL FS_Read(BYTE *buf); + // $4C - 繝輔ぃ繧、繝ォ隱ュ縺ソ霎シ縺ソ + void FASTCALL FS_Write(BYTE *buf); + // $4D - 繝輔ぃ繧、繝ォ譖ク縺崎セシ縺ソ + void FASTCALL FS_Seek(BYTE *buf); + // $4E - 繝輔ぃ繧、繝ォ繧キ繝シ繧ッ + void FASTCALL FS_TimeStamp(BYTE *buf); + // $4F - 繝輔ぃ繧、繝ォ譎ょ綾蜿門セ/險ュ螳 + void FASTCALL FS_GetCapacity(BYTE *buf); + // $50 - 螳ケ驥丞叙蠕 + void FASTCALL FS_CtrlDrive(BYTE *buf); + // $51 - 繝峨Λ繧、繝也憾諷区、懈渊/蛻カ蠕。 + void FASTCALL FS_GetDPB(BYTE *buf); + // $52 - DPB蜿門セ + void FASTCALL FS_DiskRead(BYTE *buf); + // $53 - 繧サ繧ッ繧ソ隱ュ縺ソ霎シ縺ソ + void FASTCALL FS_DiskWrite(BYTE *buf); + // $54 - 繧サ繧ッ繧ソ譖ク縺崎セシ縺ソ + void FASTCALL FS_Ioctrl(BYTE *buf); + // $55 - IOCTRL + void FASTCALL FS_Flush(BYTE *buf); + // $56 - 繝輔Λ繝繧キ繝・ + void FASTCALL FS_CheckMedia(BYTE *buf); + // $57 - 繝。繝繧」繧「莠、謠帙メ繧ァ繝繧ッ + void FASTCALL FS_Lock(BYTE *buf); + // $58 - 謗剃サ門宛蠕。 + + CFileSys *fs; + // 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝繧「繧ッ繧サ繝繧オ繝シ + DWORD fsresult; + // 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝繧「繧ッ繧サ繧ケ邨先棡繧ウ繝シ繝 + BYTE fsout[0x800]; + // 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝繧「繧ッ繧サ繧ケ邨先棡繝舌ャ繝輔ぃ + DWORD fsoutlen; + // 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝繧「繧ッ繧サ繧ケ邨先棡繝舌ャ繝輔ぃ繧オ繧、繧コ + BYTE fsopt[0x1000000]; + // 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝繧「繧ッ繧サ繧ケ繝舌ャ繝輔ぃ + DWORD fsoptlen; + // 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝繧「繧ッ繧サ繧ケ繝舌ャ繝輔ぃ繧オ繧、繧コ +}; + +//=========================================================================== +// +// SASI 繧ウ繝ウ繝医Ο繝シ繝ゥ +// +//=========================================================================== +class SASIDEV +{ +public: + // 隲也炊繝ヲ繝九ャ繝域怙螟ァ謨ー + enum { + UnitMax = 8 + }; + + // 繝輔ぉ繝シ繧コ繧ソ繧、繝溘Φ繧ー(隱ソ謨エ逕ィ) + enum { + Time_phase_bsy = 800, + Time_phase_before = 6000, // min 4000ns + Time_phase_before_data = 60000, // min 40000ns + Time_phase_after = 6000, // min 4000ns + Time_phase_after_status = 12000, // min 9000ns + }; + + // 蜀驛ィ繝繝シ繧ソ螳夂セゥ + typedef struct { + // 蜈ィ闊ャ + BUS::phase_t phase; // 驕キ遘サ繝輔ぉ繝シ繧コ + int id; // 繧ウ繝ウ繝医Ο繝シ繝ゥID(0-7) + BUS *bus; // 繝舌せ + + // 繧ウ繝槭Φ繝 + DWORD cmd[10]; // 繧ウ繝槭Φ繝峨ョ繝シ繧ソ + DWORD status; // 繧ケ繝繝シ繧ソ繧ケ繝繝シ繧ソ + DWORD message; // 繝。繝繧サ繝シ繧ク繝繝シ繧ソ + + // 霆「騾 + BYTE *buffer; // 霆「騾√ヰ繝繝輔ぃ + int bufsize; // 霆「騾√ヰ繝繝輔ぃ繧オ繧、繧コ + DWORD blocks; // 霆「騾√ヶ繝ュ繝繧ッ謨ー + DWORD next; // 谺。縺ョ繝ャ繧ウ繝シ繝 + DWORD offset; // 霆「騾√が繝輔そ繝繝 + DWORD length; // 霆「騾∵ョ九j髟キ縺 + + // 隲也炊繝ヲ繝九ャ繝 + Disk *unit[UnitMax]; + // 隲也炊繝ヲ繝九ャ繝 + } ctrl_t; + +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ +#ifdef RASCSI + SASIDEV(); +#else + SASIDEV(Device *dev); +#endif //RASCSI + + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + virtual ~SASIDEV(); + // 繝繧ケ繝医Λ繧ッ繧ソ + virtual void FASTCALL Reset(); + // 繝繝舌う繧ケ繝ェ繧サ繝繝 +#ifndef RASCSI + virtual BOOL FASTCALL Save(Fileio *fio, int ver); + // 繧サ繝シ繝 + virtual BOOL FASTCALL Load(Fileio *fio, int ver); + // 繝ュ繝シ繝 +#endif //RASCSI + + // 螟夜ΚAPI + virtual BUS::phase_t FASTCALL Process(); + // 螳溯。 + + // 謗・邯 + void FASTCALL Connect(int id, BUS *sbus); + // 繧ウ繝ウ繝医Ο繝シ繝ゥ謗・邯 + Disk* FASTCALL GetUnit(int no); + // 隲也炊繝ヲ繝九ャ繝亥叙蠕 + void FASTCALL SetUnit(int no, Disk *dev); + // 隲也炊繝ヲ繝九ャ繝郁ィュ螳 + BOOL FASTCALL HasUnit(); + // 譛牙柑縺ェ隲也炊繝ヲ繝九ャ繝医r謖√▲縺ヲ縺繧九°霑斐☆ + + // 縺昴ョ莉 + BUS::phase_t FASTCALL GetPhase() {return ctrl.phase;} + // 繝輔ぉ繝シ繧コ蜿門セ + int FASTCALL GetID() {return ctrl.id;} + // ID蜿門セ + void FASTCALL GetCTRL(ctrl_t *buffer); + // 蜀驛ィ諠蝣ア蜿門セ + ctrl_t* FASTCALL GetWorkAddr() { return &ctrl; } + // 蜀驛ィ諠蝣ア繧「繝峨Ξ繧ケ蜿門セ + virtual BOOL FASTCALL IsSASI() const {return TRUE;} + // SASI繝√ぉ繝繧ッ + Disk* FASTCALL GetBusyUnit(); + // 繝薙ず繝シ迥カ諷九ョ繝ヲ繝九ャ繝医r蜿門セ + +protected: + // 繝輔ぉ繝シ繧コ蜃ヲ逅 + virtual void FASTCALL BusFree(); + // 繝舌せ繝輔Μ繝シ繝輔ぉ繝シ繧コ + virtual void FASTCALL Selection(); + // 繧サ繝ャ繧ッ繧キ繝ァ繝ウ繝輔ぉ繝シ繧コ + virtual void FASTCALL Command(); + // 繧ウ繝槭Φ繝峨ヵ繧ァ繝シ繧コ + virtual void FASTCALL Execute(); + // 螳溯。後ヵ繧ァ繝シ繧コ + void FASTCALL Status(); + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + void FASTCALL MsgIn(); + // 繝。繝繧サ繝シ繧ク繧、繝ウ繝輔ぉ繝シ繧コ + void FASTCALL DataIn(); + // 繝繝シ繧ソ繧、繝ウ繝輔ぉ繝シ繧コ + void FASTCALL DataOut(); + // 繝繝シ繧ソ繧「繧ヲ繝医ヵ繧ァ繝シ繧コ + virtual void FASTCALL Error(); + // 蜈ア騾壹お繝ゥ繝シ蜃ヲ逅 + + // 繧ウ繝槭Φ繝 + void FASTCALL CmdTestUnitReady(); + // TEST UNIT READY繧ウ繝槭Φ繝 + void FASTCALL CmdRezero(); + // REZERO UNIT繧ウ繝槭Φ繝 + void FASTCALL CmdRequestSense(); + // REQUEST SENSE繧ウ繝槭Φ繝 + void FASTCALL CmdFormat(); + // FORMAT繧ウ繝槭Φ繝 + void FASTCALL CmdReassign(); + // REASSIGN BLOCKS繧ウ繝槭Φ繝 + void FASTCALL CmdRead6(); + // READ(6)繧ウ繝槭Φ繝 + void FASTCALL CmdWrite6(); + // WRITE(6)繧ウ繝槭Φ繝 + void FASTCALL CmdSeek6(); + // SEEK(6)繧ウ繝槭Φ繝 + void FASTCALL CmdAssign(); + // ASSIGN繧ウ繝槭Φ繝 + void FASTCALL CmdSpecify(); + // SPECIFY繧ウ繝槭Φ繝 + void FASTCALL CmdInvalid(); + // 繧オ繝昴シ繝医@縺ヲ縺縺ェ縺繧ウ繝槭Φ繝 + + // 繝繝シ繧ソ霆「騾 + virtual void FASTCALL Send(); + // 繝繝シ繧ソ騾∽ソ。 + virtual void FASTCALL Receive(); + // 繝繝シ繧ソ蜿嶺ソ。 + BOOL FASTCALL XferIn(BYTE* buf); + // 繝繝シ繧ソ霆「騾!N + BOOL FASTCALL XferOut(BOOL cont); + // 繝繝シ繧ソ霆「騾^UT + + // 繝ュ繧ー + void FASTCALL Log(Log::loglevel level, const char *format, ...); + // 繝ュ繧ー蜃コ蜉 + +protected: +#ifndef RASCSI + Device *host; + // 繝帙せ繝医ョ繝舌う繧ケ +#endif // RASCSI + + ctrl_t ctrl; + // 蜀驛ィ繝繝シ繧ソ +}; + +//=========================================================================== +// +// SCSI 繝繝舌う繧ケ(SASI 繝繝舌う繧ケ繧堤カ呎価) +// +//=========================================================================== +class SCSIDEV : public SASIDEV +{ +public: + // 蜀驛ィ繝繝シ繧ソ螳夂セゥ + typedef struct { + // 蜷梧悄霆「騾 + BOOL syncenable; // 蜷梧悄霆「騾∝庄閭ス + int syncperiod; // 蜷梧悄霆「騾√ヴ繝ェ繧ェ繝 + int syncoffset; // 蜷梧悄霆「騾√が繝輔そ繝繝 + int syncack; // 蜷梧悄霆「騾、CK謨ー + + // ATN繝。繝繧サ繝シ繧ク + BOOL atnmsg; + int msc; + BOOL msb[256]; + } scsi_t; + +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ +#ifdef RASCSI + SCSIDEV(); +#else + SCSIDEV(Device *dev); +#endif // RASCSI + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + + void FASTCALL Reset(); + // 繝繝舌う繧ケ繝ェ繧サ繝繝 + + // 螟夜ΚAPI + BUS::phase_t FASTCALL Process(); + // 螳溯。 + + void FASTCALL SyncTransfer(BOOL enable) { scsi.syncenable = enable; } + // 蜷梧悄霆「騾∝庄閭ス險ュ螳 + + // 縺昴ョ莉 + BOOL FASTCALL IsSASI() const {return FALSE;} + // SASI繝√ぉ繝繧ッ + +private: + // 繝輔ぉ繝シ繧コ + void FASTCALL BusFree(); + // 繝舌せ繝輔Μ繝シ繝輔ぉ繝シ繧コ + void FASTCALL Selection(); + // 繧サ繝ャ繧ッ繧キ繝ァ繝ウ繝輔ぉ繝シ繧コ + void FASTCALL Execute(); + // 螳溯。後ヵ繧ァ繝シ繧コ + void FASTCALL MsgOut(); + // 繝。繝繧サ繝シ繧ク繧「繧ヲ繝医ヵ繧ァ繝シ繧コ + void FASTCALL Error(); + // 蜈ア騾壹お繝ゥ繝シ蜃ヲ逅 + + // 繧ウ繝槭Φ繝 + void FASTCALL CmdInquiry(); + // INQUIRY繧ウ繝槭Φ繝 + void FASTCALL CmdModeSelect(); + // MODE SELECT繧ウ繝槭Φ繝 + void FASTCALL CmdModeSense(); + // MODE SENSE繧ウ繝槭Φ繝 + void FASTCALL CmdStartStop(); + // START STOP UNIT繧ウ繝槭Φ繝 + void FASTCALL CmdSendDiag(); + // SEND DIAGNOSTIC繧ウ繝槭Φ繝 + void FASTCALL CmdRemoval(); + // PREVENT/ALLOW MEDIUM REMOVAL繧ウ繝槭Φ繝 + void FASTCALL CmdReadCapacity(); + // READ CAPACITY繧ウ繝槭Φ繝 + void FASTCALL CmdRead10(); + // READ(10)繧ウ繝槭Φ繝 + void FASTCALL CmdWrite10(); + // WRITE(10)繧ウ繝槭Φ繝 + void FASTCALL CmdSeek10(); + // SEEK(10)繧ウ繝槭Φ繝 + void FASTCALL CmdVerify(); + // VERIFY繧ウ繝槭Φ繝 + void FASTCALL CmdSynchronizeCache(); + // SYNCHRONIZE CACHE 繧ウ繝槭Φ繝 + void FASTCALL CmdReadDefectData10(); + // READ DEFECT DATA(10) 繧ウ繝槭Φ繝 + void FASTCALL CmdReadToc(); + // READ TOC繧ウ繝槭Φ繝 + void FASTCALL CmdPlayAudio10(); + // PLAY AUDIO(10)繧ウ繝槭Φ繝 + void FASTCALL CmdPlayAudioMSF(); + // PLAY AUDIO MSF繧ウ繝槭Φ繝 + void FASTCALL CmdPlayAudioTrack(); + // PLAY AUDIO TRACK INDEX繧ウ繝槭Φ繝 + void FASTCALL CmdModeSelect10(); + // MODE SELECT(10)繧ウ繝槭Φ繝 + void FASTCALL CmdModeSense10(); + // MODE SENSE(10)繧ウ繝槭Φ繝 + void FASTCALL CmdGetMessage10(); + // GET MESSAGE(10)繧ウ繝槭Φ繝 + void FASTCALL CmdSendMessage10(); + // SEND MESSAGE(10)繧ウ繝槭Φ繝 + + // 繝繝シ繧ソ霆「騾 + void FASTCALL Send(); + // 繝繝シ繧ソ騾∽ソ。 + void FASTCALL Receive(); + // 繝繝シ繧ソ蜿嶺ソ。 + BOOL FASTCALL XferMsg(DWORD msg); + // 繝繝シ繧ソ霆「騾`SG + + scsi_t scsi; + // 蜀驛ィ繝繝シ繧ソ +}; + +#endif // disk_h diff --git a/src/raspberrypi/fileio.cpp b/src/raspberrypi/fileio.cpp new file mode 100644 index 00000000..c72c4c4c --- /dev/null +++ b/src/raspberrypi/fileio.cpp @@ -0,0 +1,367 @@ +//--------------------------------------------------------------------------- +// +// X68000 EMULATOR "XM6" +// +// Copyright (C) 2001-2006 シーシゥシ(ytanaka@ipc-tokai.or.jp) +// Copyright (C) 2010-2018 GIMONS +// [ 繝輔ぃ繧、繝ォI/O(RaSCSI逕ィ繧オ繝悶そ繝繝) ] +// +//--------------------------------------------------------------------------- + +#include "os.h" +#include "xm6.h" +#include "filepath.h" +#include "fileio.h" + +//=========================================================================== +// +// 繝輔ぃ繧、繝ォI/O +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +Fileio::Fileio() +{ + // 繝ッ繝シ繧ッ蛻晄悄蛹 + handle = -1; +} + +//--------------------------------------------------------------------------- +// +// 繝繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +Fileio::~Fileio() +{ + ASSERT(handle == -1); + + // Release縺ァ縺ョ螳牙ィ遲 + Close(); +} + +//--------------------------------------------------------------------------- +// +// 繝ュ繝シ繝 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Fileio::Load(const Filepath& path, void *buffer, int size) +{ + ASSERT(this); + ASSERT(buffer); + ASSERT(size > 0); + ASSERT(handle < 0); + + // 繧ェ繝シ繝励Φ + if (!Open(path, ReadOnly)) { + return FALSE; + } + + // 隱ュ縺ソ霎シ縺ソ + if (!Read(buffer, size)) { + Close(); + return FALSE; + } + + // 繧ッ繝ュ繝シ繧コ + Close(); + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繧サ繝シ繝 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Fileio::Save(const Filepath& path, void *buffer, int size) +{ + ASSERT(this); + ASSERT(buffer); + ASSERT(size > 0); + ASSERT(handle < 0); + + // 繧ェ繝シ繝励Φ + if (!Open(path, WriteOnly)) { + return FALSE; + } + + // 隱ュ縺ソ霎シ縺ソ + if (!Write(buffer, size)) { + Close(); + return FALSE; + } + + // 繧ッ繝ュ繝シ繧コ + Close(); + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繧ェ繝シ繝励Φ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Fileio::Open(LPCTSTR fname, OpenMode mode) +{ + ASSERT(this); + ASSERT(fname); + ASSERT(handle < 0); + + // 繝後Ν譁蟄怜励°繧峨ョ隱ュ縺ソ霎シ縺ソ縺ッ蠢縺壼、ア謨励&縺帙k + if (fname[0] == _T('\0')) { + handle = -1; + return FALSE; + } + + // 繝「繝シ繝牙挨 + switch (mode) { + // 隱ュ縺ソ霎シ縺ソ縺ョ縺ソ + case ReadOnly: + handle = open(fname, O_RDONLY); + break; + + // 譖ク縺崎セシ縺ソ縺ョ縺ソ + case WriteOnly: + handle = open(fname, O_CREAT | O_WRONLY | O_TRUNC, 0666); + break; + + // 隱ュ縺ソ譖ク縺堺ク。譁ケ + case ReadWrite: + // CD-ROM縺九i縺ョ隱ュ縺ソ霎シ縺ソ縺ッRW縺梧仙粥縺励※縺励∪縺 + if (access(fname, 0x06) != 0) { + return FALSE; + } + handle = open(fname, O_RDWR); + break; + + // 繧「繝壹Φ繝 + case Append: + handle = open(fname, O_CREAT | O_WRONLY | O_APPEND, 0666); + break; + + // 縺昴l莉・螟 + default: + ASSERT(FALSE); + break; + } + + // 邨先棡隧穂セ。 + if (handle == -1) { + return FALSE; + } + ASSERT(handle >= 0); + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繧ェ繝シ繝励Φ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Fileio::OpenDIO(LPCTSTR fname, OpenMode mode) +{ + ASSERT(this); + ASSERT(fname); + ASSERT(handle < 0); + + // 繝後Ν譁蟄怜励°繧峨ョ隱ュ縺ソ霎シ縺ソ縺ッ蠢縺壼、ア謨励&縺帙k + if (fname[0] == _T('\0')) { + handle = -1; + return FALSE; + } + + // 繝「繝シ繝牙挨 + switch (mode) { + // 隱ュ縺ソ霎シ縺ソ縺ョ縺ソ + case ReadOnly: + handle = open(fname, O_RDONLY | O_DIRECT); + break; + + // 譖ク縺崎セシ縺ソ縺ョ縺ソ + case WriteOnly: + handle = open(fname, O_CREAT | O_WRONLY | O_TRUNC | O_DIRECT, 0666); + break; + + // 隱ュ縺ソ譖ク縺堺ク。譁ケ + case ReadWrite: + // CD-ROM縺九i縺ョ隱ュ縺ソ霎シ縺ソ縺ッRW縺梧仙粥縺励※縺励∪縺 + if (access(fname, 0x06) != 0) { + return FALSE; + } + handle = open(fname, O_RDWR | O_DIRECT); + break; + + // 繧「繝壹Φ繝 + case Append: + handle = open(fname, O_CREAT | O_WRONLY | O_APPEND | O_DIRECT, 0666); + break; + + // 縺昴l莉・螟 + default: + ASSERT(FALSE); + break; + } + + // 邨先棡隧穂セ。 + if (handle == -1) { + return FALSE; + } + ASSERT(handle >= 0); + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繧ェ繝シ繝励Φ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Fileio::Open(const Filepath& path, OpenMode mode) +{ + ASSERT(this); + + return Open(path.GetPath(), mode); +} + +//--------------------------------------------------------------------------- +// +// 繧ェ繝シ繝励Φ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Fileio::OpenDIO(const Filepath& path, OpenMode mode) +{ + ASSERT(this); + + return OpenDIO(path.GetPath(), mode); +} + +//--------------------------------------------------------------------------- +// +// 隱ュ縺ソ霎シ縺ソ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Fileio::Read(void *buffer, int size) +{ + int count; + + ASSERT(this); + ASSERT(buffer); + ASSERT(size > 0); + ASSERT(handle >= 0); + + // 隱ュ縺ソ霎シ縺ソ + count = read(handle, buffer, size); + if (count != size) { + return FALSE; + } + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 譖ク縺崎セシ縺ソ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Fileio::Write(const void *buffer, int size) +{ + int count; + + ASSERT(this); + ASSERT(buffer); + ASSERT(size > 0); + ASSERT(handle >= 0); + + // 隱ュ縺ソ霎シ縺ソ + count = write(handle, buffer, size); + if (count != size) { + return FALSE; + } + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繧キ繝シ繧ッ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Fileio::Seek(off64_t offset, BOOL relative) +{ + ASSERT(this); + ASSERT(handle >= 0); + ASSERT(offset >= 0); + + // 逶ク蟇セ繧キ繝シ繧ッ縺ェ繧峨が繝輔そ繝繝医↓迴セ蝨ィ蛟、繧定ソス蜉 + if (relative) { + offset += GetFilePos(); + } + + if (lseek(handle, offset, SEEK_SET) != offset) { + return FALSE; + } + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繝輔ぃ繧、繝ォ繧オ繧、繧コ蜿門セ +// +//--------------------------------------------------------------------------- +off64_t FASTCALL Fileio::GetFileSize() +{ + off64_t cur; + off64_t end; + + ASSERT(this); + ASSERT(handle >= 0); + + // 繝輔ぃ繧、繝ォ菴咲スョ繧64bit縺ァ蜿門セ + cur = GetFilePos(); + + // 繝輔ぃ繧、繝ォ繧オ繧、繧コ繧64bit縺ァ蜿門セ + end = lseek(handle, 0, SEEK_END); + + // 菴咲スョ繧貞縺ォ謌サ縺 + Seek(cur); + + return end; +} + +//--------------------------------------------------------------------------- +// +// 繝輔ぃ繧、繝ォ菴咲スョ蜿門セ +// +//--------------------------------------------------------------------------- +off64_t FASTCALL Fileio::GetFilePos() const +{ + off64_t pos; + + ASSERT(this); + ASSERT(handle >= 0); + + // 繝輔ぃ繧、繝ォ菴咲スョ繧64bit縺ァ蜿門セ + pos = lseek(handle, 0, SEEK_CUR); + return pos; + +} + +//--------------------------------------------------------------------------- +// +// 繧ッ繝ュ繝シ繧コ +// +//--------------------------------------------------------------------------- +void FASTCALL Fileio::Close() +{ + ASSERT(this); + + if (handle != -1) { + close(handle); + handle = -1; + } +} diff --git a/src/raspberrypi/fileio.h b/src/raspberrypi/fileio.h new file mode 100644 index 00000000..22f02ac9 --- /dev/null +++ b/src/raspberrypi/fileio.h @@ -0,0 +1,83 @@ +//--------------------------------------------------------------------------- +// +// X68000 EMULATOR "XM6" +// +// Copyright (C) 2001-2005 シーシゥシ(ytanaka@ipc-tokai.or.jp) +// Copyright (C) 2013-2018 GIMONS +// [ 繝輔ぃ繧、繝ォI/O(RaSCSI逕ィ繧オ繝悶そ繝繝) ] +// +//--------------------------------------------------------------------------- + +#if !defined(fileio_h) +#define fileio_h + +//=========================================================================== +// +// 繝槭け繝ュ(Load,Save逕ィ) +// +//=========================================================================== +#define PROP_IMPORT(f, p) \ + if (!f->Read(&(p), sizeof(p))) {\ + return FALSE;\ + }\ + +#define PROP_EXPORT(f, p) \ + if (!f->Write(&(p), sizeof(p))) {\ + return FALSE;\ + }\ + +//=========================================================================== +// +// 繝輔ぃ繧、繝ォI/O +// +//=========================================================================== +class Fileio +{ +public: + enum OpenMode { + ReadOnly, // 隱ュ縺ソ霎シ縺ソ縺ョ縺ソ + WriteOnly, // 譖ク縺崎セシ縺ソ縺ョ縺ソ + ReadWrite, // 隱ュ縺ソ譖ク縺堺ク。譁ケ + Append // 繧「繝壹Φ繝 + }; + +public: + Fileio(); + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + virtual ~Fileio(); + // 繝繧ケ繝医Λ繧ッ繧ソ + BOOL FASTCALL Load(const Filepath& path, void *buffer, int size); + // ROM,RAM繝ュ繝シ繝 + BOOL FASTCALL Save(const Filepath& path, void *buffer, int size); + // RAM繧サ繝シ繝 + + BOOL FASTCALL Open(LPCTSTR fname, OpenMode mode); + // 繧ェ繝シ繝励Φ + BOOL FASTCALL OpenDIO(LPCTSTR fname, OpenMode mode); + // 繧ェ繝シ繝励Φ + BOOL FASTCALL Open(const Filepath& path, OpenMode mode); + // 繧ェ繝シ繝励Φ + BOOL FASTCALL OpenDIO(const Filepath& path, OpenMode mode); + // 繧ェ繝シ繝励Φ + BOOL FASTCALL Seek(off64_t offset, BOOL relative = FALSE); + // 繧キ繝シ繧ッ + BOOL FASTCALL Read(void *buffer, int size); + // 隱ュ縺ソ霎シ縺ソ + BOOL FASTCALL Write(const void *buffer, int size); + // 譖ク縺崎セシ縺ソ + off64_t FASTCALL GetFileSize(); + // 繝輔ぃ繧、繝ォ繧オ繧、繧コ蜿門セ + off64_t FASTCALL GetFilePos() const; + // 繝輔ぃ繧、繝ォ菴咲スョ蜿門セ + void FASTCALL Close(); + // 繧ッ繝ュ繝シ繧コ + BOOL FASTCALL IsValid() const { return (BOOL)(handle != -1); } + // 譛牙柑繝√ぉ繝繧ッ + int FASTCALL GetHandle() const { return handle; } + // 繝上Φ繝峨Ν蜿門セ + +private: + int handle; // 繝輔ぃ繧、繝ォ繝上Φ繝峨Ν +}; + +#endif // fileio_h diff --git a/src/raspberrypi/filepath.cpp b/src/raspberrypi/filepath.cpp new file mode 100644 index 00000000..43d2e410 --- /dev/null +++ b/src/raspberrypi/filepath.cpp @@ -0,0 +1,273 @@ +//--------------------------------------------------------------------------- +// +// X68000 EMULATOR "XM6" +// +// Copyright (C) 2001-2006 シーシゥシ(ytanaka@ipc-tokai.or.jp) +// Copyright (C) 2012-2018 GIMONS +// [ 繝輔ぃ繧、繝ォ繝代せ(繧オ繝悶そ繝繝) ] +// +//--------------------------------------------------------------------------- + +#include "os.h" +#include "xm6.h" +#include "filepath.h" +#include "fileio.h" + +//=========================================================================== +// +// 繝輔ぃ繧、繝ォ繝代せ +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +Filepath::Filepath() +{ + // 繧ッ繝ェ繧「 + Clear(); +} + +//--------------------------------------------------------------------------- +// +// 繝繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +Filepath::~Filepath() +{ +} + +//--------------------------------------------------------------------------- +// +// 莉」蜈・貍皮ョ怜ュ +// +//--------------------------------------------------------------------------- +Filepath& Filepath::operator=(const Filepath& path) +{ + // 繝代せ險ュ螳(蜀驛ィ縺ァSplit縺輔l繧) + SetPath(path.GetPath()); + + return *this; +} + +//--------------------------------------------------------------------------- +// +// 繧ッ繝ェ繧「 +// +//--------------------------------------------------------------------------- +void FASTCALL Filepath::Clear() +{ + ASSERT(this); + + // 繝代せ縺翫h縺ウ蜷驛ィ蛻繧偵け繝ェ繧「 + m_szPath[0] = _T('\0'); + m_szDir[0] = _T('\0'); + m_szFile[0] = _T('\0'); + m_szExt[0] = _T('\0'); +} + +//--------------------------------------------------------------------------- +// +// 繝輔ぃ繧、繝ォ險ュ螳(繝ヲ繝シ繧カ) MBCS逕ィ +// +//--------------------------------------------------------------------------- +void FASTCALL Filepath::SetPath(LPCSTR path) +{ + ASSERT(this); + ASSERT(path); + ASSERT(strlen(path) < _MAX_PATH); + + // 繝代せ蜷阪さ繝斐シ + strcpy(m_szPath, (LPTSTR)path); + + // 蛻髮「 + Split(); +} + +//--------------------------------------------------------------------------- +// +// 繝代せ蛻髮「 +// +//--------------------------------------------------------------------------- +void FASTCALL Filepath::Split() +{ + LPTSTR pDir; + LPTSTR pDirName; + LPTSTR pBase; + LPTSTR pBaseName; + LPTSTR pExtName; + + ASSERT(this); + + // 繝代シ繝繧貞晄悄蛹 + m_szDir[0] = _T('\0'); + m_szFile[0] = _T('\0'); + m_szExt[0] = _T('\0'); + + // 蛻髮「 + pDir = strdup(m_szPath); + pDirName = dirname(pDir); + pBase = strdup(m_szPath); + pBaseName = basename(pBase); + pExtName = strrchr(pBaseName, '.'); + + // 霆「騾 + if (pDirName) { + strcpy(m_szDir, pDirName); + strcat(m_szDir, "/"); + } + + if (pExtName) { + strcpy(m_szExt, pExtName); + *pExtName = 0; + } + + if (pBaseName) { + strcpy(m_szFile, pBaseName); + } + + // 隗」謾セ + free(pDir); + free(pBase); +} + +//--------------------------------------------------------------------------- +// +// 繝代せ蜷域 +// +//--------------------------------------------------------------------------- +void FASTCALL Filepath::Make() +{ + ASSERT(this); + + // 繝代せ蛻晄悄蛹 + m_szPath[0] = _T('\0'); + + // 蜷域 + strcat(m_szPath, m_szDir); + strcat(m_szPath, m_szFile); + strcat(m_szPath, m_szExt); +} + +//--------------------------------------------------------------------------- +// +// 繧ッ繝ェ繧「縺輔l縺ヲ縺繧九° +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Filepath::IsClear() const +{ + // Clear()縺ョ騾 + if ((m_szPath[0] == _T('\0')) && + (m_szDir[0] == _T('\0')) && + (m_szFile[0] == _T('\0')) && + (m_szExt[0] == _T('\0'))) { + // 遒コ縺九↓縲√け繝ェ繧「縺輔l縺ヲ縺繧 + return TRUE; + } + + // 繧ッ繝ェ繧「縺輔l縺ヲ縺縺ェ縺 + return FALSE; +} + +//--------------------------------------------------------------------------- +// +// 繧キ繝ァ繝シ繝亥錐蜿門セ +// 窶サ霑斐&繧後k繝昴う繝ウ繧ソ縺ッ荳譎ら噪縺ェ繧ゅョ縲ゅ☆縺舌さ繝斐シ縺吶k縺薙→ +// 窶サFDIDisk縺ョdisk.name縺ィ縺ョ髢「菫ゅ〒縲∵枚蟄怜励ッ譛螟ァ59譁蟄+邨らォッ縺ィ縺吶k縺薙→ +// +//--------------------------------------------------------------------------- +const char* FASTCALL Filepath::GetShort() const +{ + char szFile[_MAX_FNAME]; + char szExt[_MAX_EXT]; + + ASSERT(this); + + // TCHAR譁蟄怜励°繧営har譁蟄怜励∈螟画鋤 + strcpy(szFile, m_szFile); + strcpy(szExt, m_szExt); + + // 蝗コ螳壹ヰ繝繝輔ぃ縺ク蜷域 + strcpy(ShortName, szFile); + strcat(ShortName, szExt); + + // strlen縺ァ隱ソ縺ケ縺溘→縺阪∵怙螟ァ59縺ォ縺ェ繧九h縺縺ォ邏ー蟾・ + ShortName[59] = '\0'; + + // const char縺ィ縺励※霑斐☆ + return (const char*)ShortName; +} + +//--------------------------------------------------------------------------- +// +// 繝輔ぃ繧、繝ォ蜷搾シ区僑蠑オ蟄仙叙蠕 +// 窶サ霑斐&繧後k繝昴う繝ウ繧ソ縺ッ荳譎ら噪縺ェ繧ゅョ縲ゅ☆縺舌さ繝斐シ縺吶k縺薙→ +// +//--------------------------------------------------------------------------- +LPCTSTR FASTCALL Filepath::GetFileExt() const +{ + ASSERT(this); + + // 蝗コ螳壹ヰ繝繝輔ぃ縺ク蜷域 + strcpy(FileExt, m_szExt); + + // LPCTSTR縺ィ縺励※霑斐☆ + return (LPCTSTR)FileExt; +} + +//--------------------------------------------------------------------------- +// +// 繝代せ豈碑シ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Filepath::CmpPath(const Filepath& path) const +{ + // 繝代せ縺悟ョ悟ィ荳閾エ縺励※縺繧後ーTRUE + if (strcmp(path.GetPath(), GetPath()) == 0) { + return TRUE; + } + + return FALSE; +} + +//--------------------------------------------------------------------------- +// +// 繧サ繝シ繝 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Filepath::Save(Fileio *fio, int /*ver*/) +{ + ASSERT(this); + ASSERT(fio); + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繝ュ繝シ繝 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Filepath::Load(Fileio *fio, int /*ver*/) +{ + ASSERT(this); + ASSERT(fio); + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繧キ繝ァ繝シ繝亥錐 +// +//--------------------------------------------------------------------------- +char Filepath::ShortName[_MAX_FNAME + _MAX_DIR]; + +//--------------------------------------------------------------------------- +// +// 繝輔ぃ繧、繝ォ蜷搾シ区僑蠑オ蟄 +// +//--------------------------------------------------------------------------- +TCHAR Filepath::FileExt[_MAX_FNAME + _MAX_DIR]; \ No newline at end of file diff --git a/src/raspberrypi/filepath.h b/src/raspberrypi/filepath.h new file mode 100644 index 00000000..1817a429 --- /dev/null +++ b/src/raspberrypi/filepath.h @@ -0,0 +1,81 @@ +//--------------------------------------------------------------------------- +// +// X68000 EMULATOR "XM6" +// +// Copyright (C) 2001-2006 シーシゥシ(ytanaka@ipc-tokai.or.jp) +// Copyright (C) 2012-2018 GIMONS +// [ 繝輔ぃ繧、繝ォ繝代せ(繧オ繝悶そ繝繝) ] +// +//--------------------------------------------------------------------------- + +#if !defined(filepath_h) +#define filepath_h + +//--------------------------------------------------------------------------- +// +// 螳壽焚螳夂セゥ +// +//--------------------------------------------------------------------------- +#define FILEPATH_MAX _MAX_PATH + +//=========================================================================== +// +// 繝輔ぃ繧、繝ォ繝代せ +// 窶サ莉」蜈・貍皮ョ怜ュ舌r逕ィ諢上☆繧九%縺ィ +// +//=========================================================================== +class Filepath +{ +public: + Filepath(); + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + virtual ~Filepath(); + // 繝繧ケ繝医Λ繧ッ繧ソ + Filepath& operator=(const Filepath& path); + // 莉」蜈・ + + void FASTCALL Clear(); + // 繧ッ繝ェ繧「 + void FASTCALL SetPath(LPCSTR path); + // 繝輔ぃ繧、繝ォ險ュ螳(繝ヲ繝シ繧カ) MBCS逕ィ + BOOL FASTCALL IsClear() const; + // 繧ッ繝ェ繧「縺輔l縺ヲ縺繧九° + LPCTSTR FASTCALL GetPath() const { return m_szPath; } + // 繝代せ蜷榊叙蠕 + const char* FASTCALL GetShort() const; + // 繧キ繝ァ繝シ繝亥錐蜿門セ(const char*) + LPCTSTR FASTCALL GetFileExt() const; + // 繧キ繝ァ繝シ繝亥錐蜿門セ(LPCTSTR) + BOOL FASTCALL CmpPath(const Filepath& path) const; + // 繝代せ豈碑シ + + BOOL FASTCALL Save(Fileio *fio, int ver); + // 繧サ繝シ繝 + BOOL FASTCALL Load(Fileio *fio, int ver); + // 繝ュ繝シ繝 + +private: + void FASTCALL Split(); + // 繝代せ蛻蜑イ + void FASTCALL Make(); + // 繝代せ蜷域 + void FASTCALL SetCurDir(); + // 繧ォ繝ャ繝ウ繝医ョ繧」繝ャ繧ッ繝医Μ險ュ螳 + TCHAR m_szPath[_MAX_PATH]; + // 繝輔ぃ繧、繝ォ繝代せ + TCHAR m_szDrive[_MAX_DRIVE]; + // 繝峨Λ繧、繝 + TCHAR m_szDir[_MAX_DIR]; + // 繝繧」繝ャ繧ッ繝医Μ + TCHAR m_szFile[_MAX_FNAME]; + // 繝輔ぃ繧、繝ォ + TCHAR m_szExt[_MAX_EXT]; + // 諡。蠑オ蟄 + + static char ShortName[_MAX_FNAME + _MAX_DIR]; + // 繧キ繝ァ繝シ繝亥錐(char) + static TCHAR FileExt[_MAX_FNAME + _MAX_DIR]; + // 繧キ繝ァ繝シ繝亥錐(TCHAR) +}; + +#endif // filepath_h diff --git a/src/raspberrypi/gpiobus.cpp b/src/raspberrypi/gpiobus.cpp new file mode 100644 index 00000000..792f8070 --- /dev/null +++ b/src/raspberrypi/gpiobus.cpp @@ -0,0 +1,1192 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technology. +// Copyright (C) 2016-2018 GIMONS +// +// Imported NetBSD support and some optimisation patch by Rin Okuyama. +// +// [ GPIO-SCSI繝舌せ ] +// +//--------------------------------------------------------------------------- + +#include "os.h" +#include "xm6.h" +#include "gpiobus.h" + +#ifdef __linux__ +//--------------------------------------------------------------------------- +// +// imported from bcm_host.c +// +//--------------------------------------------------------------------------- +static DWORD get_dt_ranges(const char *filename, DWORD offset) +{ + DWORD address; + FILE *fp; + BYTE buf[4]; + + address = ~0; + fp = fopen(filename, "rb"); + if (fp) { + fseek(fp, offset, SEEK_SET); + if (fread(buf, 1, sizeof buf, fp) == sizeof buf) { + address = + buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3] << 0; + } + fclose(fp); + } + return address; +} + +DWORD bcm_host_get_peripheral_address(void) +{ + DWORD address; + + address = get_dt_ranges("/proc/device-tree/soc/ranges", 4); + return address == (DWORD)~0 ? 0x20000000 : address; +} +#endif // __linux__ + +#ifdef __NetBSD__ +// Raspberry Pi繧キ繝ェ繝シ繧コ繧剃サョ螳壹@縺ヲCPU縺九i繧「繝峨Ξ繧ケ繧呈耳螳 +DWORD bcm_host_get_peripheral_address(void) +{ + char buf[1024]; + size_t len = sizeof(buf); + DWORD address; + + if (sysctlbyname("hw.model", buf, &len, NULL, 0) || + strstr(buf, "ARM1176JZ-S") != buf) { + // CPU繝「繝繝ォ縺ョ蜿門セ励↓螟ア謨 || BCM2835縺ァ縺ッ縺ェ縺 + // BCM283[67]縺ョ繧「繝峨Ξ繧ケ繧剃スソ逕ィ + address = 0x3f000000; + } else { + // BCM2835縺ョ繧「繝峨Ξ繧ケ繧剃スソ逕ィ + address = 0x20000000; + } + printf("Peripheral address : 0x%lx\n", address); + return address; +} +#endif + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +GPIOBUS::GPIOBUS() +{ +} + +//--------------------------------------------------------------------------- +// +// 繝繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +GPIOBUS::~GPIOBUS() +{ +} + +//--------------------------------------------------------------------------- +// +// 繝斐Φ讖溯ス險ュ螳(蜈・蜃コ蜉幄ィュ螳) +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::PinConfig(int pin, int mode) +{ + int index; + DWORD mask; + + // 譛ェ菴ソ逕ィ縺ェ繧臥┌蜉ケ + if (pin < 0) { + return; + } + + index = pin / 10; + mask = ~(0x7 << ((pin % 10) * 3)); + gpio[index] = (gpio[index] & mask) | ((mode & 0x7) << ((pin % 10) * 3)); +} + +//--------------------------------------------------------------------------- +// +// 繝斐Φ讖溯ス險ュ螳(繝励Ν繧「繝繝/繝繧ヲ繝ウ) +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::PullConfig(int pin, int mode) +{ + // 譛ェ菴ソ逕ィ縺ェ繧臥┌蜉ケ + if (pin < 0) { + return; + } + + gpio[GPIO_PUD] = mode & 0x3; + usleep(1); + gpio[GPIO_CLK_0] = 0x1 << pin; + usleep(1); + gpio[GPIO_PUD] = 0; + gpio[GPIO_CLK_0] = 0; +} + +//--------------------------------------------------------------------------- +// +// Drive Strength險ュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::DrvConfig(DWORD drive) +{ + DWORD data; + + // 繧ォ繝シ繝阪Ν繝峨Λ繧、繝舌′縺ゅl縺ーIOCTL縺ァ萓晞シ縺吶k + if (drvfd >= 0) { + ioctl(drvfd, IOCTL_PADS, (DWORD)drive); + } else { + data = pads[PAD_0_27]; + pads[PAD_0_27] = (0xFFFFFFF8 & data) | drive | 0x5a000000; + } +} + +//--------------------------------------------------------------------------- +// +// 繝斐Φ蜃コ蜉幄ィュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::PinSetSignal(int pin, BOOL ast) +{ + // 譛ェ菴ソ逕ィ縺ェ繧臥┌蜉ケ + if (pin < 0) { + return; + } + + if (ast) { + gpio[GPIO_SET_0] = 0x1 << pin; + } else { + gpio[GPIO_CLR_0] = 0x1 << pin; + } +} + +//--------------------------------------------------------------------------- +// +// 繝ッ繝シ繧ッ繝繝シ繝悶Ν菴懈 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::MakeTable(void) +{ + const int pintbl[] = { + PIN_DT0, PIN_DT1, PIN_DT2, PIN_DT3, PIN_DT4, + PIN_DT5, PIN_DT6, PIN_DT7, PIN_DP + }; + + int i; + int j; + BOOL tblParity[256]; + DWORD bits; + DWORD parity; +#if SIGNAL_CONTROL_MODE == 0 + int index; + int shift; +#else + DWORD gpclr; + DWORD gpset; +#endif + + // 繝代Μ繝繧」繝繝シ繝悶Ν菴懈 + for (i = 0; i < 0x100; i++) { + bits = (DWORD)i; + parity = 0; + for (j = 0; j < 8; j++) { + parity ^= bits & 1; + bits >>= 1; + } + parity = ~parity; + tblParity[i] = parity & 1; + } + +#if SIGNAL_CONTROL_MODE == 0 + // 繝槭せ繧ッ縺ィ險ュ螳壹ョ繝シ繧ソ逕滓 + memset(tblDatMsk, 0xff, sizeof(tblDatMsk)); + memset(tblDatSet, 0x00, sizeof(tblDatSet)); + for (i = 0; i < 0x100; i++) { + // 讀懈渊逕ィ繝薙ャ繝亥 + bits = (DWORD)i; + + // 繝代Μ繝繧」蜿門セ + if (tblParity[i]) { + bits |= (1 << 8); + } + + // 繝薙ャ繝域、懈渊 + for (j = 0; j < 9; j++) { + // 繧、繝ウ繝繝繧ッ繧ケ縺ィ繧キ繝輔ヨ驥剰ィ育ョ + index = pintbl[j] / 10; + shift = (pintbl[j] % 10) * 3; + + // 繝槭せ繧ッ繝繝シ繧ソ + tblDatMsk[index][i] &= ~(0x7 << shift); + + // 險ュ螳壹ョ繝シ繧ソ + if (bits & 1) { + tblDatSet[index][i] |= (1 << shift); + } + + bits >>= 1; + } + } +#else + // 繝槭せ繧ッ縺ィ險ュ螳壹ョ繝シ繧ソ逕滓 + memset(tblDatMsk, 0x00, sizeof(tblDatMsk)); + memset(tblDatSet, 0x00, sizeof(tblDatSet)); + for (i = 0; i < 0x100; i++) { + // 讀懈渊逕ィ繝薙ャ繝亥 + bits = (DWORD)i; + + // 繝代Μ繝繧」蜿門セ + if (tblParity[i]) { + bits |= (1 << 8); + } + +#if SIGNAL_CONTROL_MODE == 1 + // 雋隲也炊縺ッ蜿崎サ「 + bits = ~bits; +#endif + + // GPIO繝ャ繧ク繧ケ繧ソ諠蝣ア縺ョ菴懈 + gpclr = 0; + gpset = 0; + for (j = 0; j < 9; j++) { + if (bits & 1) { + gpset |= (1 << pintbl[j]); + } else { + gpclr |= (1 << pintbl[j]); + } + bits >>= 1; + } + + tblDatMsk[i] = gpclr; + tblDatSet[i] = gpset; + } +#endif +} + +//--------------------------------------------------------------------------- +// +// 蛻晄悄蛹 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL GPIOBUS::Init(mode_e mode) +{ + DWORD base; + DWORD addr; + int fd; + void *map; + int i; + int j; + int pullmode; + + // 蜍穂ス懊Δ繝シ繝峨ョ菫晏ュ + actmode = mode; + + // 繝吶シ繧ケ繧「繝峨Ξ繧ケ縺ョ蜿門セ + base = (DWORD)bcm_host_get_peripheral_address(); + + // 繧ォ繝シ繝阪Ν繝峨Λ繧、繝舌が繝シ繝励Φ + drvfd = open(DRIVER_PATH, O_RDWR); + if (drvfd >= 0) { + printf("Activated RaSCSI GPIO Driver.\n"); + ioctl(drvfd, IOCTL_INIT, base); + ioctl(drvfd, IOCTL_MODE, (DWORD)actmode); + } + + // /dev/mem,/dev/gpiomem縺ョ鬆縺ォ繧ェ繝シ繝励Φ繧定ゥヲ縺ソ繧 + addr = base + GPIO_OFFSET; + fd = open("/dev/mem", O_RDWR | O_SYNC); + if (fd == -1) { + // /dev/gpiomem繧偵が繝シ繝励Φ + addr = 0; + fd = open("/dev/gpiomem", O_RDWR | O_SYNC); + if (fd == -1) { + return FALSE; + } + } + + // GPIO縺ョI/O繝昴シ繝医r繝槭ャ繝励☆繧 + map = mmap(NULL, 164, + PROT_READ | PROT_WRITE, MAP_SHARED, fd, addr); + if (map == MAP_FAILED) { + close(fd); + return FALSE; + } + + // GPIO縺ョI/O繝昴シ繝医い繝峨Ξ繧ケ遒コ菫 + gpio = (DWORD *)map; + level = &gpio[GPIO_LEV_0]; + + // PADS縺ョ蜃ヲ逅縺ッ繧ォ繝シ繝阪Ν繝峨Λ繧、繝舌′辟。縺譎ゅ□縺(sudo縺悟ソ隕√→縺ェ繧) + if (drvfd < 0) { + // /dev/mem繧偵が繝シ繝励Φ + fd = open("/dev/mem", O_RDWR | O_SYNC); + if (fd == -1) { + return FALSE; + } + + // PADS縺ョI/O繝昴シ繝医r繝槭ャ繝励☆繧 + map = mmap(NULL, 56, + PROT_READ | PROT_WRITE, MAP_SHARED, fd, base + PADS_OFFSET); + close(fd); + if (map == MAP_FAILED) { + return FALSE; + } + + // PADS縺ョI/O繝昴シ繝医い繝峨Ξ繧ケ遒コ菫 + pads = (DWORD *)map; + } + + // Drive Strength繧16mA縺ォ險ュ螳 + DrvConfig(7); + + // 繝励Ν繧「繝繝/繝励Ν繝繧ヲ繝ウ繧定ィュ螳 +#if SIGNAL_CONTROL_MODE == 0 + pullmode = GPIO_PULLNONE; +#elif SIGNAL_CONTROL_MODE == 1 + pullmode = GPIO_PULLUP; +#else + pullmode = GPIO_PULLDOWN; +#endif + + // 蜈ィ菫。蜿キ蛻晄悄蛹 + for (i = 0; SignalTable[i] >= 0; i++) { + j = SignalTable[i]; + PinSetSignal(j, FALSE); + PinConfig(j, GPIO_INPUT); + PullConfig(j, pullmode); + } + + // 蛻カ蠕。菫。蜿キ繧定ィュ螳 + PinSetSignal(PIN_ACT, FALSE); + PinSetSignal(PIN_TAD, FALSE); + PinSetSignal(PIN_IND, FALSE); + PinSetSignal(PIN_DTD, FALSE); + PinConfig(PIN_ACT, GPIO_OUTPUT); + PinConfig(PIN_TAD, GPIO_OUTPUT); + PinConfig(PIN_IND, GPIO_OUTPUT); + PinConfig(PIN_DTD, GPIO_OUTPUT); + + // 譛牙柑菫。蜿キ繧定ィュ螳 + PinSetSignal(PIN_ENB, ENB_ON); + PinConfig(PIN_ENB, GPIO_OUTPUT); + + // GPFSEL繝舌ャ繧ッ繧「繝繝 + gpfsel[0] = gpio[GPIO_FSEL_0]; + gpfsel[1] = gpio[GPIO_FSEL_1]; + gpfsel[2] = gpio[GPIO_FSEL_2]; + gpfsel[3] = gpio[GPIO_FSEL_3]; + + // 繝ッ繝シ繧ッ繝繝シ繝悶Ν菴懈 + MakeTable(); + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繧ッ繝ェ繝シ繝ウ繧「繝繝 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::Cleanup() +{ + int i; + int j; + + // 蛻カ蠕。菫。蜿キ繧定ィュ螳 + PinSetSignal(PIN_ENB, FALSE); + PinSetSignal(PIN_ACT, FALSE); + PinSetSignal(PIN_TAD, FALSE); + PinSetSignal(PIN_IND, FALSE); + PinSetSignal(PIN_DTD, FALSE); + PinConfig(PIN_ACT, GPIO_INPUT); + PinConfig(PIN_TAD, GPIO_INPUT); + PinConfig(PIN_IND, GPIO_INPUT); + PinConfig(PIN_DTD, GPIO_INPUT); + + // 蜈ィ菫。蜿キ蛻晄悄蛹 + for (i = 0; SignalTable[i] >= 0; i++) { + j = SignalTable[i]; + PinSetSignal(j, FALSE); + PinConfig(j, GPIO_INPUT); + PullConfig(j, GPIO_PULLNONE); + } + + // Drive Strength繧8mA縺ォ險ュ螳 + DrvConfig(3); + + // 繧ォ繝シ繝阪Ν繝峨Λ繧、繝 + if (drvfd >= 0) { + close(drvfd); + drvfd = -1; + } +} + +//--------------------------------------------------------------------------- +// +// 蛻カ蠕。菫。蜿キ險ュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::SetControl(int pin, BOOL ast) +{ + PinSetSignal(pin, ast); +} + +//--------------------------------------------------------------------------- +// +// 蜈・蜃コ蜉帙Δ繝シ繝芽ィュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::SetMode(int pin, int mode) +{ + int index; + int shift; + DWORD data; + +#if SIGNAL_CONTROL_MODE == 0 + if (mode == OUT) { + return; + } +#endif + + index = pin / 10; + shift = (pin % 10) * 3; + data = gpfsel[index]; + data &= ~(0x7 << shift); + if (mode == OUT) { + data |= (1 << shift); + } + gpio[index] = data; + gpfsel[index] = data; +} + +//--------------------------------------------------------------------------- +// +// 蜈・蜉帑ソ。蜿キ蛟、蜿門セ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL GPIOBUS::GetSignal(int pin) +{ + return (signals >> pin) & 1; +} + +//--------------------------------------------------------------------------- +// +// 蜃コ蜉帑ソ。蜿キ蛟、險ュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::SetSignal(int pin, BOOL ast) +{ +#if SIGNAL_CONTROL_MODE == 0 + int index; + int shift; + DWORD data; + + index = pin / 10; + shift = (pin % 10) * 3; + data = gpfsel[index]; + data &= ~(0x7 << shift); + if (ast) { + data |= (1 << shift); + } + gpio[index] = data; + gpfsel[index] = data; +#elif SIGNAL_CONTROL_MODE == 1 + if (ast) { + gpio[GPIO_CLR_0] = 0x1 << pin; + } else { + gpio[GPIO_SET_0] = 0x1 << pin; + } +#elif SIGNAL_CONTROL_MODE == 2 + if (ast) { + gpio[GPIO_SET_0] = 0x1 << pin; + } else { + gpio[GPIO_CLR_0] = 0x1 << pin; + } +#endif +} + +//--------------------------------------------------------------------------- +// +// 繝翫ヮ遘貞腰菴阪ョ繧ケ繝ェ繝シ繝 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::SleepNsec(DWORD nsec) +{ + DWORD count; + + count = (nsec + 8 - 1) / 8; + while (count--) { + gpio[GPIO_PUD] = 0; + } +} + +//--------------------------------------------------------------------------- +// +// 繝ェ繧サ繝繝 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::Reset() +{ + int i; + int j; + + // 繧「繧ッ繝繧」繝紋ソ。蜿キ繧偵が繝 + SetControl(PIN_ACT, ACT_OFF); + + // 蜈ィ菫。蜿キ繧偵ロ繧イ繝シ繝医↓險ュ螳 + for (i = 0;; i++) { + j = SignalTable[i]; + if (j < 0) { + break; + } + + SetSignal(j, OFF); + } + + if (actmode == TARGET) { + // 繧ソ繝シ繧イ繝繝医Δ繝シ繝 + + // 繧ソ繝シ繧イ繝繝井ソ。蜿キ繧貞・蜉帙↓險ュ螳 + SetControl(PIN_TAD, TAD_IN); + SetMode(PIN_BSY, IN); + SetMode(PIN_MSG, IN); + SetMode(PIN_CD, IN); + SetMode(PIN_REQ, IN); + SetMode(PIN_IO, IN); + + // 繧、繝九す繧ィ繝シ繧ソ菫。蜿キ繧貞・蜉帙↓險ュ螳 + SetControl(PIN_IND, IND_IN); + SetMode(PIN_SEL, IN); + SetMode(PIN_ATN, IN); + SetMode(PIN_ACK, IN); + SetMode(PIN_RST, IN); + + // 繝繝シ繧ソ繝舌せ菫。蜿キ繧貞・蜉帙↓險ュ螳 + SetControl(PIN_DTD, DTD_IN); + SetMode(PIN_DT0, IN); + SetMode(PIN_DT1, IN); + SetMode(PIN_DT2, IN); + SetMode(PIN_DT3, IN); + SetMode(PIN_DT4, IN); + SetMode(PIN_DT5, IN); + SetMode(PIN_DT6, IN); + SetMode(PIN_DT7, IN); + SetMode(PIN_DP, IN); + } else { + // 繧、繝九す繧ィ繝シ繧ソ繝「繝シ繝 + + // 繧ソ繝シ繧イ繝繝井ソ。蜿キ繧貞・蜉帙↓險ュ螳 + SetControl(PIN_TAD, TAD_IN); + SetMode(PIN_BSY, IN); + SetMode(PIN_MSG, IN); + SetMode(PIN_CD, IN); + SetMode(PIN_REQ, IN); + SetMode(PIN_IO, IN); + + // 繧、繝九す繧ィ繝シ繧ソ菫。蜿キ繧貞コ蜉帙↓險ュ螳 + SetControl(PIN_IND, IND_OUT); + SetMode(PIN_SEL, OUT); + SetMode(PIN_ATN, OUT); + SetMode(PIN_ACK, OUT); + SetMode(PIN_RST, OUT); + + // 繝繝シ繧ソ繝舌せ菫。蜿キ繧貞コ蜉帙↓險ュ螳 + SetControl(PIN_DTD, DTD_OUT); + SetMode(PIN_DT0, OUT); + SetMode(PIN_DT1, OUT); + SetMode(PIN_DT2, OUT); + SetMode(PIN_DT3, OUT); + SetMode(PIN_DT4, OUT); + SetMode(PIN_DT5, OUT); + SetMode(PIN_DT6, OUT); + SetMode(PIN_DT7, OUT); + SetMode(PIN_DP, OUT); + } + + // 蜈ィ菫。蜿キ蛻晄悄蛹 + signals = 0; +} + +//--------------------------------------------------------------------------- +// +// 繝舌せ菫。蜿キ蜿悶j霎シ縺ソ +// +//--------------------------------------------------------------------------- +DWORD FASTCALL GPIOBUS::Aquire() +{ + signals = *level; + +#if SIGNAL_CONTROL_MODE < 2 + // 雋隲也炊縺ェ繧牙渚霆「縺吶k(蜀驛ィ蜃ヲ逅縺ッ豁」隲也炊縺ォ邨ア荳) + signals = ~signals; +#endif + + return signals; +} + +//--------------------------------------------------------------------------- +// +// BSY繧キ繧ー繝翫Ν蜿門セ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL GPIOBUS::GetBSY() +{ + return GetSignal(PIN_BSY); +} + +//--------------------------------------------------------------------------- +// +// BSY繧キ繧ー繝翫Ν險ュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::SetBSY(BOOL ast) +{ + if (actmode == TARGET) { + if (ast) { + // 繧「繧ッ繝繧」繝紋ソ。蜿キ繧偵が繝ウ + SetControl(PIN_ACT, ACT_ON); + + // 繧ソ繝シ繧イ繝繝井ソ。蜿キ繧貞コ蜉帙↓險ュ螳 + SetControl(PIN_TAD, TAD_OUT); + SetMode(PIN_BSY, OUT); + SetMode(PIN_MSG, OUT); + SetMode(PIN_CD, OUT); + SetMode(PIN_REQ, OUT); + SetMode(PIN_IO, OUT); + } else { + // 繧ソ繝シ繧イ繝繝井ソ。蜿キ繧貞・蜉帙↓險ュ螳 + SetControl(PIN_TAD, TAD_IN); + SetMode(PIN_BSY, IN); + SetMode(PIN_MSG, IN); + SetMode(PIN_CD, IN); + SetMode(PIN_REQ, IN); + SetMode(PIN_IO, IN); + + // 繧「繧ッ繝繧」繝紋ソ。蜿キ繧偵が繝 + SetControl(PIN_ACT, ACT_OFF); + } + } + + // BSY菫。蜿キ繧定ィュ螳 + SetSignal(PIN_BSY, ast); +} + +//--------------------------------------------------------------------------- +// +// SEL繧キ繧ー繝翫Ν蜿門セ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL GPIOBUS::GetSEL() +{ + return GetSignal(PIN_SEL); +} + +//--------------------------------------------------------------------------- +// +// SEL繧キ繧ー繝翫Ν險ュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::SetSEL(BOOL ast) +{ + if (actmode == INITIATOR && ast) { + // 繧「繧ッ繝繧」繝紋ソ。蜿キ繧偵が繝ウ + SetControl(PIN_ACT, ACT_ON); + } + + // SEL菫。蜿キ繧定ィュ螳 + SetSignal(PIN_SEL, ast); +} + +//--------------------------------------------------------------------------- +// +// ATN繧キ繧ー繝翫Ν蜿門セ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL GPIOBUS::GetATN() +{ + return GetSignal(PIN_ATN); +} + +//--------------------------------------------------------------------------- +// +// ATN繧キ繧ー繝翫Ν險ュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::SetATN(BOOL ast) +{ + SetSignal(PIN_ATN, ast); +} + +//--------------------------------------------------------------------------- +// +// ACK繧キ繧ー繝翫Ν蜿門セ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL GPIOBUS::GetACK() +{ + return GetSignal(PIN_ACK); +} + +//--------------------------------------------------------------------------- +// +// ACK繧キ繧ー繝翫Ν險ュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::SetACK(BOOL ast) +{ + SetSignal(PIN_ACK, ast); +} + +//--------------------------------------------------------------------------- +// +// RST繧キ繧ー繝翫Ν蜿門セ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL GPIOBUS::GetRST() +{ + return GetSignal(PIN_RST); +} + +//--------------------------------------------------------------------------- +// +// RST繧キ繧ー繝翫Ν險ュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::SetRST(BOOL ast) +{ + SetSignal(PIN_RST, ast); +} + +//--------------------------------------------------------------------------- +// +// MSG繧キ繧ー繝翫Ν蜿門セ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL GPIOBUS::GetMSG() +{ + return GetSignal(PIN_MSG); +} + +//--------------------------------------------------------------------------- +// +// MSG繧キ繧ー繝翫Ν險ュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::SetMSG(BOOL ast) +{ + SetSignal(PIN_MSG, ast); +} + +//--------------------------------------------------------------------------- +// +// CD繧キ繧ー繝翫Ν蜿門セ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL GPIOBUS::GetCD() +{ + return GetSignal(PIN_CD); +} + +//--------------------------------------------------------------------------- +// +// CD繧キ繧ー繝翫Ν險ュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::SetCD(BOOL ast) +{ + SetSignal(PIN_CD, ast); +} + +//--------------------------------------------------------------------------- +// +// IO繧キ繧ー繝翫Ν蜿門セ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL GPIOBUS::GetIO() +{ + BOOL ast; + ast = GetSignal(PIN_IO); + + if (actmode == INITIATOR) { + // IO菫。蜿キ縺ォ繧医▲縺ヲ繝繝シ繧ソ縺ョ蜈・蜃コ蜉帶婿蜷代r螟画峩 + if (ast) { + SetControl(PIN_DTD, DTD_IN); + SetMode(PIN_DT0, IN); + SetMode(PIN_DT1, IN); + SetMode(PIN_DT2, IN); + SetMode(PIN_DT3, IN); + SetMode(PIN_DT4, IN); + SetMode(PIN_DT5, IN); + SetMode(PIN_DT6, IN); + SetMode(PIN_DT7, IN); + SetMode(PIN_DP, IN); + } else { + SetControl(PIN_DTD, DTD_OUT); + SetMode(PIN_DT0, OUT); + SetMode(PIN_DT1, OUT); + SetMode(PIN_DT2, OUT); + SetMode(PIN_DT3, OUT); + SetMode(PIN_DT4, OUT); + SetMode(PIN_DT5, OUT); + SetMode(PIN_DT6, OUT); + SetMode(PIN_DT7, OUT); + SetMode(PIN_DP, OUT); + } + } + + return ast; +} + +//--------------------------------------------------------------------------- +// +// IO繧キ繧ー繝翫Ν險ュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::SetIO(BOOL ast) +{ + SetSignal(PIN_IO, ast); + + if (actmode == TARGET) { + // IO菫。蜿キ縺ォ繧医▲縺ヲ繝繝シ繧ソ縺ョ蜈・蜃コ蜉帶婿蜷代r螟画峩 + if (ast) { + SetControl(PIN_DTD, DTD_OUT); + SetMode(PIN_DT0, OUT); + SetMode(PIN_DT1, OUT); + SetMode(PIN_DT2, OUT); + SetMode(PIN_DT3, OUT); + SetMode(PIN_DT4, OUT); + SetMode(PIN_DT5, OUT); + SetMode(PIN_DT6, OUT); + SetMode(PIN_DT7, OUT); + SetMode(PIN_DP, OUT); + } else { + SetControl(PIN_DTD, DTD_IN); + SetMode(PIN_DT0, IN); + SetMode(PIN_DT1, IN); + SetMode(PIN_DT2, IN); + SetMode(PIN_DT3, IN); + SetMode(PIN_DT4, IN); + SetMode(PIN_DT5, IN); + SetMode(PIN_DT6, IN); + SetMode(PIN_DT7, IN); + SetMode(PIN_DP, IN); + } + } +} + +//--------------------------------------------------------------------------- +// +// REQ繧キ繧ー繝翫Ν蜿門セ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL GPIOBUS::GetREQ() +{ + return GetSignal(PIN_REQ); +} + +//--------------------------------------------------------------------------- +// +// REQ繧キ繧ー繝翫Ν險ュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::SetREQ(BOOL ast) +{ + SetSignal(PIN_REQ, ast); +} + +//--------------------------------------------------------------------------- +// +// 繝繝シ繧ソ繧キ繧ー繝翫Ν蜿門セ +// +//--------------------------------------------------------------------------- +BYTE FASTCALL GPIOBUS::GetDAT() +{ + DWORD data; + + data = Aquire(); + data = + ((data >> (PIN_DT0 - 0)) & (1 << 0)) | + ((data >> (PIN_DT1 - 1)) & (1 << 1)) | + ((data >> (PIN_DT2 - 2)) & (1 << 2)) | + ((data >> (PIN_DT3 - 3)) & (1 << 3)) | + ((data >> (PIN_DT4 - 4)) & (1 << 4)) | + ((data >> (PIN_DT5 - 5)) & (1 << 5)) | + ((data >> (PIN_DT6 - 6)) & (1 << 6)) | + ((data >> (PIN_DT7 - 7)) & (1 << 7)); + + return (BYTE)data; +} + +//--------------------------------------------------------------------------- +// +// 繝繝シ繧ソ繧キ繧ー繝翫Ν險ュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::SetDAT(BYTE dat) +{ + // 繝昴シ繝医∈譖ク縺崎セシ縺ソ +#if SIGNAL_CONTROL_MODE == 0 + gpfsel[0] &= tblDatMsk[0][dat]; + gpfsel[0] |= tblDatSet[0][dat]; + gpio[GPIO_FSEL_0] = gpfsel[0]; + + gpfsel[1] &= tblDatMsk[1][dat]; + gpfsel[1] |= tblDatSet[1][dat]; + gpio[GPIO_FSEL_1] = gpfsel[1]; + + gpfsel[2] &= tblDatMsk[2][dat]; + gpfsel[2] |= tblDatSet[2][dat]; + gpio[GPIO_FSEL_2] = gpfsel[2]; +#else + gpio[GPIO_CLR_0] = tblDatMsk[dat]; + gpio[GPIO_SET_0] = tblDatSet[dat]; +#endif +} + +//--------------------------------------------------------------------------- +// +// 繝繝シ繧ソ蜿嶺ソ。繝上Φ繝峨す繧ァ繧、繧ッ +// +//--------------------------------------------------------------------------- +int FASTCALL GPIOBUS::ReceiveHandShake(BYTE *buf, int count) +{ + int i; + DWORD loop; + DWORD phase; + + if (drvfd >= 0) { + return read(drvfd, buf, count); + } else { + if (actmode == TARGET) { + for (i = 0; i < count; i++) { + // REQ繧「繧オ繝シ繝 + SetSignal(PIN_REQ, ON); + + // ACK繧「繧オ繝シ繝亥セ縺。 + loop = 30000000; + do { + Aquire(); + loop--; + } while (!(signals & (1 << PIN_ACK)) && + !(signals & (1 << PIN_RST)) && loop > 0); + + // 繝繝シ繧ソ蜿門セ + *buf = GetDAT(); + + // REQ繝阪ご繝シ繝 + SetSignal(PIN_REQ, OFF); + + // ACK繧「繧オ繝シ繝亥セ縺。縺ァ繧ソ繧、繝繧「繧ヲ繝 + if (loop == 0 || (signals & (1 << PIN_RST))) { + break; + } + + // ACK繝阪ご繝シ繝亥セ縺。 + loop = 30000000; + do { + Aquire(); + loop--; + } while ((signals & (1 << PIN_ACK)) && + !(signals & (1 << PIN_RST)) && loop > 0); + + // ACK繝阪ご繝シ繝亥セ縺。縺ァ繧ソ繧、繝繧「繧ヲ繝 + if (loop == 0 || (signals & (1 << PIN_RST))) { + break; + } + + // 谺。繝繝シ繧ソ縺ク + buf++; + } + + // 蜿嶺ソ。謨ー繧定ソ泌唆 + return i; + } else { + // 繝輔ぉ繝シ繧コ蜿門セ + phase = signals & GPIO_MCI; + + for (i = 0; i < count; i++) { + // REQ繧「繧オ繝シ繝亥セ縺。 + loop = 30000000; + do { + Aquire(); + loop--; + } while (!(signals & (1 << PIN_REQ)) && + ((signals & GPIO_MCI) == phase) && loop > 0); + + // REQ繧「繧オ繝シ繝亥セ縺。縺ァ繧ソ繧、繝繧「繧ヲ繝 + if (loop == 0 || (signals & GPIO_MCI) != phase) { + break; + } + + // 繝繝シ繧ソ蜿門セ + *buf = GetDAT(); + + // ACK繧「繧オ繝シ繝 + SetSignal(PIN_ACK, ON); + + // REQ繝阪ご繝シ繝亥セ縺。 + loop = 30000000; + do { + Aquire(); + loop--; + } while ((signals & (1 << PIN_REQ)) && + ((signals & GPIO_MCI) == phase) && loop > 0); + + // ACK繝阪ご繝シ繝 + SetSignal(PIN_ACK, OFF); + + // REQ繝阪ご繝シ繝亥セ縺。縺ァ繧ソ繧、繝繧「繧ヲ繝 + if (loop == 0 || (signals & GPIO_MCI) != phase) { + break; + } + + // 谺。繝繝シ繧ソ縺ク + buf++; + } + + // 蜿嶺ソ。謨ー繧定ソ泌唆 + return i; + } + } +} + +//--------------------------------------------------------------------------- +// +// 繝繝シ繧ソ騾∽ソ。繝上Φ繝峨す繧ァ繧、繧ッ +// +//--------------------------------------------------------------------------- +int FASTCALL GPIOBUS::SendHandShake(BYTE *buf, int count) +{ + int i; + DWORD loop; + DWORD phase; + + if (drvfd >= 0) { + return write(drvfd, buf, count); + } else { + if (actmode == TARGET) { + for (i = 0; i < count; i++) { + // 繝繝シ繧ソ險ュ螳 + SetDAT(*buf); + + // 菫。蜿キ邱壹′螳牙ョ壹☆繧九∪縺ァ繧ヲ繧ァ繧、繝 + SleepNsec(150); + + // ACK繝阪ご繝シ繝亥セ縺。 + loop = (DWORD)30000000; + do { + Aquire(); + loop--; + } while ((signals & (1 << PIN_ACK)) && + !(signals & (1 << PIN_RST)) && loop > 0); + + // ACK繝阪ご繝シ繝亥セ縺。縺ァ繧ソ繧、繝繧「繧ヲ繝 + if (loop == 0 || (signals & (1 << PIN_RST))) { + break; + } + + // REQ繧「繧オ繝シ繝 + SetSignal(PIN_REQ, ON); + + // ACK繧「繧オ繝シ繝亥セ縺。 + loop = (DWORD)30000000; + do { + Aquire(); + loop--; + } while (!(signals & (1 << PIN_ACK)) && + !(signals & (1 << PIN_RST)) && loop > 0); + + // REQ繝阪ご繝シ繝 + SetSignal(PIN_REQ, OFF); + + // ACK繧「繧オ繝シ繝亥セ縺。縺ァ繧ソ繧、繝繧「繧ヲ繝 + if (loop == 0 || (signals & (1 << PIN_RST))) { + break; + } + + // 谺。繝繝シ繧ソ縺ク + buf++; + } + + // ACK繝阪ご繝シ繝亥セ縺。 + loop = (DWORD)30000000; + do { + Aquire(); + loop--; + } while ((signals & (1 << PIN_ACK)) && + !(signals & (1 << PIN_RST)) && loop > 0); + + // 騾∽ソ。謨ー繧定ソ泌唆 + return i; + } else { + // 繝輔ぉ繝シ繧コ蜿門セ + phase = signals & GPIO_MCI; + + for (i = 0; i < count; i++) { + // REQ繧「繧オ繝シ繝亥セ縺。 + loop = (DWORD)30000000; + do { + Aquire(); + loop--; + } while (!(signals & (1 << PIN_REQ)) && + ((signals & GPIO_MCI) == phase) && loop > 0); + + // REQ繧「繧オ繝シ繝亥セ縺。縺ァ繧ソ繧、繝繧「繧ヲ繝 + if (loop == 0 || (signals & GPIO_MCI) != phase) { + break; + } + + // 繝繝シ繧ソ險ュ螳 + SetDAT(*buf); + + // 菫。蜿キ邱壹′螳牙ョ壹☆繧九∪縺ァ繧ヲ繧ァ繧、繝 + SleepNsec(150); + + // ACK繧「繧オ繝シ繝 + SetSignal(PIN_ACK, ON); + + // REQ繝阪ご繝シ繝亥セ縺。 + loop = (DWORD)30000000; + do { + Aquire(); + loop--; + } while ((signals & (1 << PIN_REQ)) && + ((signals & GPIO_MCI) == phase) && loop > 0); + + // ACK繝阪ご繝シ繝 + SetSignal(PIN_ACK, OFF); + + // REQ繝阪ご繝シ繝亥セ縺。縺ァ繧ソ繧、繝繧「繧ヲ繝 + if (loop == 0 || (signals & GPIO_MCI) != phase) { + break; + } + + // 谺。繝繝シ繧ソ縺ク + buf++; + } + + // 騾∽ソ。謨ー繧定ソ泌唆 + return i; + } + } +} + +//--------------------------------------------------------------------------- +// +// 菫。蜿キ繝繝シ繝悶Ν +// +//--------------------------------------------------------------------------- +const int GPIOBUS::SignalTable[19] = { + PIN_DT0, PIN_DT1, PIN_DT2, PIN_DT3, + PIN_DT4, PIN_DT5, PIN_DT6, PIN_DT7, PIN_DP, + PIN_SEL,PIN_ATN, PIN_RST, PIN_ACK, + PIN_BSY, PIN_MSG, PIN_CD, PIN_IO, PIN_REQ, + -1 +}; diff --git a/src/raspberrypi/gpiobus.h b/src/raspberrypi/gpiobus.h new file mode 100644 index 00000000..82f556f6 --- /dev/null +++ b/src/raspberrypi/gpiobus.h @@ -0,0 +1,479 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technology. +// Copyright (C) 2016-2018 GIMONS +// [ GPIO-SCSI繝舌せ ] +// +//--------------------------------------------------------------------------- + +#if !defined(gpiobus_h) +#define gpiobus_h + +#include "scsi.h" + +//--------------------------------------------------------------------------- +// +// 謗・邯壽婿豕募ョ夂セゥ縺ョ驕ク謚 +// +//--------------------------------------------------------------------------- +#define CONNECT_TYPE_STANDARD // 讓呎コ(SCSI隲也炊,讓呎コ悶ヴ繝ウ繧「繧オ繧、繝ウ) +//#define CONNECT_TYPE_FULLSPEC // 繝輔Ν繧ケ繝壹ャ繧ッ(SCSI隲也炊,讓呎コ悶ヴ繝ウ繧「繧オ繧、繝ウ) +//#define CONNECT_TYPE_AIBOM // AIBOM迚(豁」隲也炊,蝗コ譛峨ヴ繝ウ繧「繧オ繧、繝ウ) +//#define CONNECT_TYPE_GAMERNIUM // GAMERnium.com迚(讓呎コ冶ォ也炊,蝗コ譛峨ヴ繝ウ繧「繧オ繧、繝ウ) + +//--------------------------------------------------------------------------- +// +// 菫。蜿キ蛻カ蠕。隲也炊蜿翫ウ繝斐Φ繧「繧オ繧、繝ウ繧ォ繧ケ繧ソ繝槭う繧コ +// +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// +// SIGNAL_CONTROL_MODE:菫。蜿キ蛻カ蠕。繝「繝シ繝蛾∈謚 +// Version1.22縺九i菫。蜿キ蛻カ蠕。縺ョ隲也炊繧偵き繧ケ繧ソ繝槭う繧コ縺ァ縺阪∪縺吶 +// +// 0:SCSI隲也炊莉墓ァ +// 逶エ邨舌∪縺溘ッHP縺ォ蜈ャ髢九@縺74LS641-1遲峨r菴ソ逕ィ縺吶k螟画鋤蝓コ譚ソ +// 繧「繝シ繧オ繝シ繝:0V +// 繝阪ご繝シ繝 :繧ェ繝シ繝励Φ繧ウ繝ャ繧ッ繧ソ蜃コ蜉(繝舌せ縺九i蛻繧企屬縺) +// +// 1:雋隲也炊莉墓ァ(雋隲也炊->SCSI隲也炊縺ク縺ョ螟画鋤蝓コ譚ソ繧剃スソ逕ィ縺吶k蝣エ蜷) +// 迴セ譎らせ縺ァ縺薙ョ莉墓ァ倥↓繧医k螟画鋤蝓コ譚ソ縺ッ蟄伜惠縺励∪縺帙s +// 繧「繝シ繧オ繝シ繝:0V -> (CONVERT) -> 0V +// 繝阪ご繝シ繝 :3.3V -> (CONVERT) -> 繧ェ繝シ繝励Φ繧ウ繝ャ繧ッ繧ソ蜃コ蜉 +// +// 2:豁」隲也炊莉墓ァ(豁」隲也炊->SCSI隲也炊縺ク縺ョ螟画鋤蝓コ譚ソ繧剃スソ逕ィ縺吶k蝣エ蜷) +// RaSCSI Adapter Rev.C @132sync遲 +// +// 繧「繝シ繧オ繝シ繝:3.3V -> (CONVERT) -> 0V +// 繝阪ご繝シ繝 :0V -> (CONVERT) -> 繧ェ繝シ繝励Φ繧ウ繝ャ繧ッ繧ソ蜃コ蜉 +// +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// +// 蛻カ蠕。菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ險ュ螳 +// 蛻カ蠕。菫。蜿キ縺ォ蟇セ縺吶kGPIO繝斐Φ縺ョ繝槭ャ繝斐Φ繧ー繝繝シ繝悶Ν縺ァ縺吶 +// +// 蛻カ蠕。菫。蜿キ +// PIN_ACT +// SCSI繧ウ繝槭Φ繝峨r蜃ヲ逅荳ュ縺ョ迥カ諷九r遉コ縺吩ソ。蜿キ縺ョ繝斐Φ逡ェ蜿キ縲 +// PIN_ENB +// 襍キ蜍輔°繧臥オゆコ縺ョ髢薙ョ譛牙柑菫。蜿キ繧堤、コ縺吩ソ。蜿キ縺ョ繝斐Φ逡ェ蜿キ縲 +// PIN_TAD +// 繧ソ繝シ繧イ繝繝井ソ。蜿キ(BSY,IO,CD,MSG,REG)縺ョ蜈・蜃コ蜉帶婿蜷代r遉コ縺吩ソ。蜿キ縺ョ繝斐Φ逡ェ蜿キ縲 +// PIN_IND +// 繧、繝九す繝シ繧ィ繝シ繧ソ菫。蜿キ(SEL,ATN,RST,ACK)縺ョ蜈・蜃コ蜉帶婿蜷代r遉コ縺吩ソ。蜿キ縺ョ繝斐Φ逡ェ蜿キ縲 +// PIN_DTD +// 繝繝シ繧ソ菫。蜿キ(DT0...DT7,DP)縺ョ蜈・蜃コ蜉帶婿蜷代r遉コ縺吩ソ。蜿キ縺ョ繝斐Φ逡ェ蜿キ縲 +// +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// +// 蛻カ蠕。菫。蜿キ蜃コ蜉幄ォ也炊 +// 0V:FALSE 3.3V:TRUE縺ァ謖螳壹@縺セ縺吶 +// +// ACT_ON +// PIN_ACT菫。蜿キ縺ョ隲也炊縺ァ縺吶 +// ENB_ON +// PIN_ENB菫。蜿キ縺ョ隲也炊縺ァ縺吶 +// TAD_IN +// PIN_TAD蜈・蜉帶婿蜷第凾縺ョ隲也炊縺ァ縺吶 +// IND_IN +// PIN_ENB蜈・蜉帶婿蜷第凾縺ョ隲也炊縺ァ縺吶 +// DTD_IN +// PIN_ENB蜈・蜉帶婿蜷第凾縺ョ隲也炊縺ァ縺吶 +// +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// +// SCSI菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ險ュ螳 +// SCSI縺ョ菫。蜿キ縺ォ蟇セ縺吶kGPIO繝斐Φ縺ョ繝槭ャ繝斐Φ繧ー繝繝シ繝悶Ν縺ァ縺吶 +// PIN_DT0ス霸IN_SEL +// +//--------------------------------------------------------------------------- + +#ifdef CONNECT_TYPE_STANDARD +// +// RaSCSI 讓呎コ(SCSI隲也炊,讓呎コ悶ヴ繝ウ繧「繧オ繧、繝ウ) +// +#define CONNECT_DESC "STANDARD" // 襍キ蜍墓凾繝。繝繧サ繝シ繧ク + +// 菫。蜿キ蛻カ蠕。繝「繝シ繝蛾∈謚 +#define SIGNAL_CONTROL_MODE 0 // SCSI隲也炊莉墓ァ + +// 蛻カ蠕。菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ(-1縺ョ蝣エ蜷医ッ蛻カ蠕。辟。縺) +#define PIN_ACT 4 // ACTIVE +#define PIN_ENB 5 // ENABLE +#define PIN_IND -1 // INITIATOR CTRL DIRECTION +#define PIN_TAD -1 // TARGET CTRL DIRECTION +#define PIN_DTD -1 // DATA DIRECTION + +// 蛻カ蠕。菫。蜿キ蜃コ蜉幄ォ也炊 +#define ACT_ON TRUE // ACTIVE SIGNAL ON +#define ENB_ON TRUE // ENABLE SIGNAL ON +#define IND_IN FALSE // INITIATOR SIGNAL INPUT +#define TAD_IN FALSE // TARGET SIGNAL INPUT +#define DTD_IN TRUE // DATA SIGNAL INPUT + +// SCSI菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ +#define PIN_DT0 10 // 繝繝シ繧ソ0 +#define PIN_DT1 11 // 繝繝シ繧ソ1 +#define PIN_DT2 12 // 繝繝シ繧ソ2 +#define PIN_DT3 13 // 繝繝シ繧ソ3 +#define PIN_DT4 14 // 繝繝シ繧ソ4 +#define PIN_DT5 15 // 繝繝シ繧ソ5 +#define PIN_DT6 16 // 繝繝シ繧ソ6 +#define PIN_DT7 17 // 繝繝シ繧ソ7 +#define PIN_DP 18 // 繝代Μ繝繧」 +#define PIN_ATN 19 // ATN +#define PIN_RST 20 // RST +#define PIN_ACK 21 // ACK +#define PIN_REQ 22 // REQ +#define PIN_MSG 23 // MSG +#define PIN_CD 24 // CD +#define PIN_IO 25 // IO +#define PIN_BSY 26 // BSY +#define PIN_SEL 27 // SEL +#endif + +#ifdef CONNECT_TYPE_FULLSPEC +// +// RaSCSI 讓呎コ(SCSI隲也炊,讓呎コ悶ヴ繝ウ繧「繧オ繧、繝ウ) +// +#define CONNECT_DESC "FULLSPEC" // 襍キ蜍墓凾繝。繝繧サ繝シ繧ク + +// 菫。蜿キ蛻カ蠕。繝「繝シ繝蛾∈謚 +#define SIGNAL_CONTROL_MODE 0 // SCSI隲也炊莉墓ァ + +// 蛻カ蠕。菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ(-1縺ョ蝣エ蜷医ッ蛻カ蠕。辟。縺) +#define PIN_ACT 4 // ACTIVE +#define PIN_ENB 5 // ENABLE +#define PIN_IND 6 // INITIATOR CTRL DIRECTION +#define PIN_TAD 7 // TARGET CTRL DIRECTION +#define PIN_DTD 8 // DATA DIRECTION + +// 蛻カ蠕。菫。蜿キ蜃コ蜉幄ォ也炊 +#define ACT_ON TRUE // ACTIVE SIGNAL ON +#define ENB_ON TRUE // ENABLE SIGNAL ON +#define IND_IN FALSE // INITIATOR SIGNAL INPUT +#define TAD_IN FALSE // TARGET SIGNAL INPUT +#define DTD_IN TRUE // DATA SIGNAL INPUT + +// SCSI菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ +#define PIN_DT0 10 // 繝繝シ繧ソ0 +#define PIN_DT1 11 // 繝繝シ繧ソ1 +#define PIN_DT2 12 // 繝繝シ繧ソ2 +#define PIN_DT3 13 // 繝繝シ繧ソ3 +#define PIN_DT4 14 // 繝繝シ繧ソ4 +#define PIN_DT5 15 // 繝繝シ繧ソ5 +#define PIN_DT6 16 // 繝繝シ繧ソ6 +#define PIN_DT7 17 // 繝繝シ繧ソ7 +#define PIN_DP 18 // 繝代Μ繝繧」 +#define PIN_ATN 19 // ATN +#define PIN_RST 20 // RST +#define PIN_ACK 21 // ACK +#define PIN_REQ 22 // REQ +#define PIN_MSG 23 // MSG +#define PIN_CD 24 // CD +#define PIN_IO 25 // IO +#define PIN_BSY 26 // BSY +#define PIN_SEL 27 // SEL +#endif + +#ifdef CONNECT_TYPE_AIBOM +// +// RaSCSI Adapter 縺ゅ>縺シ繧迚 +// + +#define CONNECT_DESC "AIBOM PRODUCTS version" // 襍キ蜍墓凾繝。繝繧サ繝シ繧ク + +// 菫。蜿キ蛻カ蠕。繝「繝シ繝蛾∈謚 +#define SIGNAL_CONTROL_MODE 2 // SCSI豁」隲也炊莉墓ァ + +// 蛻カ蠕。菫。蜿キ蜃コ蜉幄ォ也炊 +#define ACT_ON TRUE // ACTIVE SIGNAL ON +#define ENB_ON TRUE // ENABLE SIGNAL ON +#define IND_IN FALSE // INITIATOR SIGNAL INPUT +#define TAD_IN FALSE // TARGET SIGNAL INPUT +#define DTD_IN FALSE // DATA SIGNAL INPUT + +// 蛻カ蠕。菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ(-1縺ョ蝣エ蜷医ッ蛻カ蠕。辟。縺) +#define PIN_ACT 4 // ACTIVE +#define PIN_ENB 17 // ENABLE +#define PIN_IND 27 // INITIATOR CTRL DIRECTION +#define PIN_TAD -1 // TARGET CTRL DIRECTION +#define PIN_DTD 18 // DATA DIRECTION + +// SCSI菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ +#define PIN_DT0 6 // 繝繝シ繧ソ0 +#define PIN_DT1 12 // 繝繝シ繧ソ1 +#define PIN_DT2 13 // 繝繝シ繧ソ2 +#define PIN_DT3 16 // 繝繝シ繧ソ3 +#define PIN_DT4 19 // 繝繝シ繧ソ4 +#define PIN_DT5 20 // 繝繝シ繧ソ5 +#define PIN_DT6 26 // 繝繝シ繧ソ6 +#define PIN_DT7 21 // 繝繝シ繧ソ7 +#define PIN_DP 5 // 繝代Μ繝繧」 +#define PIN_ATN 22 // ATN +#define PIN_RST 25 // RST +#define PIN_ACK 10 // ACK +#define PIN_REQ 7 // REQ +#define PIN_MSG 9 // MSG +#define PIN_CD 11 // CD +#define PIN_IO 23 // IO +#define PIN_BSY 24 // BSY +#define PIN_SEL 8 // SEL +#endif + +#ifdef CONNECT_TYPE_GAMERNIUM +// +// RaSCSI Adapter GAMERnium.com迚 +// + +#define CONNECT_DESC "GAMERnium.com version"// 襍キ蜍墓凾繝。繝繧サ繝シ繧ク + +// 菫。蜿キ蛻カ蠕。繝「繝シ繝蛾∈謚 +#define SIGNAL_CONTROL_MODE 0 // SCSI隲也炊莉墓ァ + +// 蛻カ蠕。菫。蜿キ蜃コ蜉幄ォ也炊 +#define ACT_ON TRUE // ACTIVE SIGNAL ON +#define ENB_ON TRUE // ENABLE SIGNAL ON +#define IND_IN FALSE // INITIATOR SIGNAL INPUT +#define TAD_IN FALSE // TARGET SIGNAL INPUT +#define DTD_IN TRUE // DATA SIGNAL INPUT + +// 蛻カ蠕。菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ(-1縺ョ蝣エ蜷医ッ蛻カ蠕。辟。縺) +#define PIN_ACT 14 // ACTIVE +#define PIN_ENB 6 // ENABLE +#define PIN_IND 7 // INITIATOR CTRL DIRECTION +#define PIN_TAD 8 // TARGET CTRL DIRECTION +#define PIN_DTD 5 // DATA DIRECTION + +// SCSI菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ +#define PIN_DT0 21 // 繝繝シ繧ソ0 +#define PIN_DT1 26 // 繝繝シ繧ソ1 +#define PIN_DT2 20 // 繝繝シ繧ソ2 +#define PIN_DT3 19 // 繝繝シ繧ソ3 +#define PIN_DT4 16 // 繝繝シ繧ソ4 +#define PIN_DT5 13 // 繝繝シ繧ソ5 +#define PIN_DT6 12 // 繝繝シ繧ソ6 +#define PIN_DT7 11 // 繝繝シ繧ソ7 +#define PIN_DP 25 // 繝代Μ繝繧」 +#define PIN_ATN 10 // ATN +#define PIN_RST 22 // RST +#define PIN_ACK 24 // ACK +#define PIN_REQ 15 // REQ +#define PIN_MSG 17 // MSG +#define PIN_CD 18 // CD +#define PIN_IO 4 // IO +#define PIN_BSY 27 // BSY +#define PIN_SEL 23 // SEL +#endif + +//--------------------------------------------------------------------------- +// +// 螳壽焚螳」險(GPIO) +// +//--------------------------------------------------------------------------- +#define GPIO_OFFSET 0x200000 +#define PADS_OFFSET 0x100000 +#define GPIO_INPUT 0 +#define GPIO_OUTPUT 1 +#define GPIO_PULLNONE 0 +#define GPIO_PULLDOWN 1 +#define GPIO_PULLUP 2 +#define GPIO_FSEL_0 0 +#define GPIO_FSEL_1 1 +#define GPIO_FSEL_2 2 +#define GPIO_FSEL_3 3 +#define GPIO_SET_0 7 +#define GPIO_CLR_0 10 +#define GPIO_LEV_0 13 +#define GPIO_EDS_0 16 +#define GPIO_REN_0 19 +#define GPIO_FEN_0 22 +#define GPIO_HEN_0 25 +#define GPIO_LEN_0 28 +#define GPIO_AREN_0 31 +#define GPIO_AFEN_0 34 +#define GPIO_PUD 37 +#define GPIO_CLK_0 38 +#define PAD_0_27 11 + +#define GPIO_INEDGE ((1 << PIN_BSY) | \ + (1 << PIN_SEL) | \ + (1 << PIN_ATN) | \ + (1 << PIN_ACK) | \ + (1 << PIN_RST)) + +#define GPIO_MCI ((1 << PIN_MSG) | \ + (1 << PIN_CD) | \ + (1 << PIN_IO)) + +//--------------------------------------------------------------------------- +// +// 螳壽焚螳」險(蛻カ蠕。菫。蜿キ) +// +//--------------------------------------------------------------------------- +#define ACT_OFF !ACT_ON +#define ENB_OFF !ENB_ON +#define TAD_OUT !TAD_IN +#define IND_OUT !IND_IN +#define DTD_OUT !DTD_IN + +//--------------------------------------------------------------------------- +// +// 螳壽焚螳」險(SCSI) +// +//--------------------------------------------------------------------------- +#define IN GPIO_INPUT +#define OUT GPIO_OUTPUT +#define ON TRUE +#define OFF FALSE + +//--------------------------------------------------------------------------- +// +// 螳壽焚螳」險(繝峨Λ繧、繝) +// +//--------------------------------------------------------------------------- +#define DEVICE_NAME "rascsidrv" +#define DRIVER_PATH "/dev/" DEVICE_NAME +#define IOCTL_INIT 0x100 +#define IOCTL_MODE 0x101 +#define IOCTL_PADS 0x102 + +//--------------------------------------------------------------------------- +// +// 繧ッ繝ゥ繧ケ螳夂セゥ +// +//--------------------------------------------------------------------------- +class GPIOBUS : public BUS +{ +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + GPIOBUS(); + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + virtual ~GPIOBUS(); + // 繝繧ケ繝医Λ繧ッ繧ソ + BOOL FASTCALL Init(mode_e mode = TARGET); + // 蛻晄悄蛹 + void FASTCALL Reset(); + // 繝ェ繧サ繝繝 + void FASTCALL Cleanup(); + // 繧ッ繝ェ繝シ繝ウ繧「繝繝 + + DWORD FASTCALL Aquire(); + // 菫。蜿キ蜿悶j霎シ縺ソ + + BOOL FASTCALL GetBSY(); + // BSY繧キ繧ー繝翫Ν蜿門セ + void FASTCALL SetBSY(BOOL ast); + // BSY繧キ繧ー繝翫Ν險ュ螳 + + BOOL FASTCALL GetSEL(); + // SEL繧キ繧ー繝翫Ν蜿門セ + void FASTCALL SetSEL(BOOL ast); + // SEL繧キ繧ー繝翫Ν險ュ螳 + + BOOL FASTCALL GetATN(); + // ATN繧キ繧ー繝翫Ν蜿門セ + void FASTCALL SetATN(BOOL ast); + // ATN繧キ繧ー繝翫Ν險ュ螳 + + BOOL FASTCALL GetACK(); + // ACK繧キ繧ー繝翫Ν蜿門セ + void FASTCALL SetACK(BOOL ast); + // ACK繧キ繧ー繝翫Ν險ュ螳 + + BOOL FASTCALL GetRST(); + // RST繧キ繧ー繝翫Ν蜿門セ + void FASTCALL SetRST(BOOL ast); + // RST繧キ繧ー繝翫Ν險ュ螳 + + BOOL FASTCALL GetMSG(); + // MSG繧キ繧ー繝翫Ν蜿門セ + void FASTCALL SetMSG(BOOL ast); + // MSG繧キ繧ー繝翫Ν險ュ螳 + + BOOL FASTCALL GetCD(); + // CD繧キ繧ー繝翫Ν蜿門セ + void FASTCALL SetCD(BOOL ast); + // CD繧キ繧ー繝翫Ν險ュ螳 + + BOOL FASTCALL GetIO(); + // IO繧キ繧ー繝翫Ν蜿門セ + void FASTCALL SetIO(BOOL ast); + // IO繧キ繧ー繝翫Ν險ュ螳 + + BOOL FASTCALL GetREQ(); + // REQ繧キ繧ー繝翫Ν蜿門セ + void FASTCALL SetREQ(BOOL ast); + // REQ繧キ繧ー繝翫Ν險ュ螳 + + BYTE FASTCALL GetDAT(); + // 繝繝シ繧ソ繧キ繧ー繝翫Ν蜿門セ + void FASTCALL SetDAT(BYTE dat); + // 繝繝シ繧ソ繧キ繧ー繝翫Ν險ュ螳 + int FASTCALL ReceiveHandShake(BYTE *buf, int count); + // 繝繝シ繧ソ蜿嶺ソ。繝上Φ繝峨す繧ァ繧、繧ッ + int FASTCALL SendHandShake(BYTE *buf, int count); + // 繝繝シ繧ソ騾∽ソ。繝上Φ繝峨す繧ァ繧、繧ッ + + // 繧ソ繧、繝樣未菫 + void FASTCALL SleepNsec(DWORD nsec); + // 繝翫ヮ遘貞腰菴阪ョ繧ケ繝ェ繝シ繝 + +private: + void FASTCALL DrvConfig(DWORD drive); + // GPIO繝峨Λ繧、繝冶ス蜉幄ィュ螳 + void FASTCALL PinConfig(int pin, int mode); + // GPIO繝斐Φ讖溯ス險ュ螳(蜈・蜃コ蜉幄ィュ螳) + void FASTCALL PullConfig(int pin, int mode); + // GPIO繝斐Φ讖溯ス險ュ螳(繝励Ν繧「繝繝/繝繧ヲ繝ウ) + void FASTCALL PinSetSignal(int pin, BOOL ast); + // GPIO繝斐Φ蜃コ蜉帑ソ。蜿キ險ュ螳 + void FASTCALL MakeTable(); + // 繝ッ繝シ繧ッ繝繝シ繝悶Ν菴懈 + void FASTCALL SetControl(int pin, BOOL ast); + // 蛻カ蠕。菫。蜿キ險ュ螳 + void FASTCALL SetMode(int pin, int mode); + // SCSI蜈・蜃コ蜉帙Δ繝シ繝芽ィュ螳 + BOOL FASTCALL GetSignal(int pin); + // SCSI蜈・蜉帑ソ。蜿キ蛟、蜿門セ + void FASTCALL SetSignal(int pin, BOOL ast); + // SCSI蜃コ蜉帑ソ。蜿キ蛟、險ュ螳 + + mode_e actmode; // 蜍穂ス懊Δ繝シ繝 + + volatile DWORD *gpio; // GPIO繝ャ繧ク繧ケ繧ソ + + volatile DWORD *pads; // PADS繝ャ繧ク繧ケ繧ソ + + volatile DWORD *level; // GPIO蜈・蜉帙Ξ繝吶Ν + + DWORD gpfsel[4]; // GPFSEL0-4繝舌ャ繧ッ繧「繝繝 + + DWORD signals; // 繝舌せ蜈ィ菫。蜿キ + +#if SIGNAL_CONTROL_MODE == 0 + DWORD tblDatMsk[3][256]; // 繝繝シ繧ソ繝槭せ繧ッ逕ィ繝繝シ繝悶Ν + + DWORD tblDatSet[3][256]; // 繝繝シ繧ソ險ュ螳夂畑繝繝シ繝悶Ν +#else + DWORD tblDatMsk[256]; // 繝繝シ繧ソ繝槭せ繧ッ逕ィ繝繝シ繝悶Ν + + DWORD tblDatSet[256]; // 繝繝シ繧ソ險ュ螳夂畑繝繝シ繝悶Ν +#endif + + int drvfd; // 繧ォ繝シ繝阪Ν繝峨Λ繧、繝舌ヵ繧。繧、繝ォ繝繧」繧ケ繧ッ繝励Μ繧ソ + + static const int SignalTable[19]; // 繧キ繧ー繝翫Ν繝繝シ繝悶Ν +}; + +#endif // gpiobus_h diff --git a/src/raspberrypi/kernelmodule/Makefile b/src/raspberrypi/kernelmodule/Makefile new file mode 100644 index 00000000..5ed61fdc --- /dev/null +++ b/src/raspberrypi/kernelmodule/Makefile @@ -0,0 +1,9 @@ +KERNEL_HEADERS=/lib/modules/$(shell uname -r)/build +obj-m := rascsidrv.o +ccflags-y := -O3 + +all: + $(MAKE) -C $(KERNEL_HEADERS) M=$(PWD) modules + +clean: + $(MAKE) -C $(KERNEL_HEADERS) M=$(PWD) clean diff --git a/src/raspberrypi/kernelmodule/rascsidrv.c b/src/raspberrypi/kernelmodule/rascsidrv.c new file mode 100644 index 00000000..9dd239f9 --- /dev/null +++ b/src/raspberrypi/kernelmodule/rascsidrv.c @@ -0,0 +1,1122 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technology. +// Copyright (C) 2016-2018 GIMONS +// [ GPIO繝峨Λ繧、繝 ] +// +//--------------------------------------------------------------------------- + +#include +#include +#include +#include +#include + +//--------------------------------------------------------------------------- +// +// 蝓コ譛ャ蝙句ョ夂セゥ +// +//--------------------------------------------------------------------------- +typedef unsigned char BYTE; +typedef unsigned short WORD; +typedef unsigned long DWORD; +typedef int BOOL; + +#if !defined(FALSE) +#define FALSE 0 +#endif + +#if !defined(TRUE) +#define TRUE 1 +#endif + +//--------------------------------------------------------------------------- +// +// 謗・邯壽婿豕募ョ夂セゥ縺ョ驕ク謚 +// +//--------------------------------------------------------------------------- +#define CONNECT_TYPE_STANDARD // 讓呎コ(SCSI隲也炊,讓呎コ悶ヴ繝ウ繧「繧オ繧、繝ウ) +//#define CONNECT_TYPE_FULLSPEC // 繝輔Ν繧ケ繝壹ャ繧ッ(SCSI隲也炊,讓呎コ悶ヴ繝ウ繧「繧オ繧、繝ウ) +//#define CONNECT_TYPE_AIBOM // AIBOM迚(豁」隲也炊,蝗コ譛峨ヴ繝ウ繧「繧オ繧、繝ウ) +//#define CONNECT_TYPE_GAMERNIUM // GAMERnium.com迚(讓呎コ冶ォ也炊,蝗コ譛峨ヴ繝ウ繧「繧オ繧、繝ウ) + +//--------------------------------------------------------------------------- +// +// 菫。蜿キ蛻カ蠕。隲也炊蜿翫ウ繝斐Φ繧「繧オ繧、繝ウ繧ォ繧ケ繧ソ繝槭う繧コ +// +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// +// SIGNAL_CONTROL_MODE:菫。蜿キ蛻カ蠕。繝「繝シ繝蛾∈謚 +// Version1.22縺九i菫。蜿キ蛻カ蠕。縺ョ隲也炊繧偵き繧ケ繧ソ繝槭う繧コ縺ァ縺阪∪縺吶 +// +// 0:SCSI隲也炊莉墓ァ +// 逶エ邨舌∪縺溘ッHP縺ォ蜈ャ髢九@縺74LS641-1遲峨r菴ソ逕ィ縺吶k螟画鋤蝓コ譚ソ +// 繧「繝シ繧オ繝シ繝:0V +// 繝阪ご繝シ繝 :繧ェ繝シ繝励Φ繧ウ繝ャ繧ッ繧ソ蜃コ蜉(繝舌せ縺九i蛻繧企屬縺) +// +// 1:雋隲也炊莉墓ァ(雋隲也炊->SCSI隲也炊縺ク縺ョ螟画鋤蝓コ譚ソ繧剃スソ逕ィ縺吶k蝣エ蜷) +// 迴セ譎らせ縺ァ縺薙ョ莉墓ァ倥↓繧医k螟画鋤蝓コ譚ソ縺ッ蟄伜惠縺励∪縺帙s +// 繧「繝シ繧オ繝シ繝:0V -> (CONVERT) -> 0V +// 繝阪ご繝シ繝 :3.3V -> (CONVERT) -> 繧ェ繝シ繝励Φ繧ウ繝ャ繧ッ繧ソ蜃コ蜉 +// +// 2:豁」隲也炊莉墓ァ(豁」隲也炊->SCSI隲也炊縺ク縺ョ螟画鋤蝓コ譚ソ繧剃スソ逕ィ縺吶k蝣エ蜷) +// RaSCSI Adapter Rev.C @132sync遲 +// +// 繧「繝シ繧オ繝シ繝:3.3V -> (CONVERT) -> 0V +// 繝阪ご繝シ繝 :0V -> (CONVERT) -> 繧ェ繝シ繝励Φ繧ウ繝ャ繧ッ繧ソ蜃コ蜉 +// +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// +// 蛻カ蠕。菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ險ュ螳 +// 蛻カ蠕。菫。蜿キ縺ォ蟇セ縺吶kGPIO繝斐Φ縺ョ繝槭ャ繝斐Φ繧ー繝繝シ繝悶Ν縺ァ縺吶 +// +// 蛻カ蠕。菫。蜿キ +// PIN_ACT +// SCSI繧ウ繝槭Φ繝峨r蜃ヲ逅荳ュ縺ョ迥カ諷九r遉コ縺吩ソ。蜿キ縺ョ繝斐Φ逡ェ蜿キ縲 +// PIN_ENB +// 襍キ蜍輔°繧臥オゆコ縺ョ髢薙ョ譛牙柑菫。蜿キ繧堤、コ縺吩ソ。蜿キ縺ョ繝斐Φ逡ェ蜿キ縲 +// PIN_TAD +// 繧ソ繝シ繧イ繝繝井ソ。蜿キ(BSY,IO,CD,MSG,REG)縺ョ蜈・蜃コ蜉帶婿蜷代r遉コ縺吩ソ。蜿キ縺ョ繝斐Φ逡ェ蜿キ縲 +// PIN_IND +// 繧、繝九す繝シ繧ィ繝シ繧ソ菫。蜿キ(SEL,ATN,RST,ACK)縺ョ蜈・蜃コ蜉帶婿蜷代r遉コ縺吩ソ。蜿キ縺ョ繝斐Φ逡ェ蜿キ縲 +// PIN_DTD +// 繝繝シ繧ソ菫。蜿キ(DT0...DT7,DP)縺ョ蜈・蜃コ蜉帶婿蜷代r遉コ縺吩ソ。蜿キ縺ョ繝斐Φ逡ェ蜿キ縲 +// +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// +// 蛻カ蠕。菫。蜿キ蜃コ蜉幄ォ也炊 +// 0V:FALSE 3.3V:TRUE縺ァ謖螳壹@縺セ縺吶 +// +// ACT_ON +// PIN_ACT菫。蜿キ縺ョ隲也炊縺ァ縺吶 +// ENB_ON +// PIN_ENB菫。蜿キ縺ョ隲也炊縺ァ縺吶 +// TAD_IN +// PIN_TAD蜈・蜉帶婿蜷第凾縺ョ隲也炊縺ァ縺吶 +// IND_IN +// PIN_ENB蜈・蜉帶婿蜷第凾縺ョ隲也炊縺ァ縺吶 +// DTD_IN +// PIN_ENB蜈・蜉帶婿蜷第凾縺ョ隲也炊縺ァ縺吶 +// +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// +// SCSI菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ險ュ螳 +// SCSI縺ョ菫。蜿キ縺ォ蟇セ縺吶kGPIO繝斐Φ縺ョ繝槭ャ繝斐Φ繧ー繝繝シ繝悶Ν縺ァ縺吶 +// PIN_DT0ス霸IN_SEL +// +//--------------------------------------------------------------------------- + +#ifdef CONNECT_TYPE_STANDARD +// +// RaSCSI 讓呎コ(SCSI隲也炊,讓呎コ悶ヴ繝ウ繧「繧オ繧、繝ウ) +// +#define CONNECT_DESC "STANDARD" // 襍キ蜍墓凾繝。繝繧サ繝シ繧ク + +// 菫。蜿キ蛻カ蠕。繝「繝シ繝蛾∈謚 +#define SIGNAL_CONTROL_MODE 0 // SCSI隲也炊莉墓ァ + +// 蛻カ蠕。菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ(-1縺ョ蝣エ蜷医ッ蛻カ蠕。辟。縺) +#define PIN_ACT 4 // ACTIVE +#define PIN_ENB 5 // ENABLE +#define PIN_IND -1 // INITIATOR CTRL DIRECTION +#define PIN_TAD -1 // TARGET CTRL DIRECTION +#define PIN_DTD -1 // DATA DIRECTION + +// 蛻カ蠕。菫。蜿キ蜃コ蜉幄ォ也炊 +#define ACT_ON TRUE // ACTIVE SIGNAL ON +#define ENB_ON TRUE // ENABLE SIGNAL ON +#define IND_IN FALSE // INITIATOR SIGNAL INPUT +#define TAD_IN FALSE // TARGET SIGNAL INPUT +#define DTD_IN TRUE // DATA SIGNAL INPUT + +// SCSI菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ +#define PIN_DT0 10 // 繝繝シ繧ソ0 +#define PIN_DT1 11 // 繝繝シ繧ソ1 +#define PIN_DT2 12 // 繝繝シ繧ソ2 +#define PIN_DT3 13 // 繝繝シ繧ソ3 +#define PIN_DT4 14 // 繝繝シ繧ソ4 +#define PIN_DT5 15 // 繝繝シ繧ソ5 +#define PIN_DT6 16 // 繝繝シ繧ソ6 +#define PIN_DT7 17 // 繝繝シ繧ソ7 +#define PIN_DP 18 // 繝代Μ繝繧」 +#define PIN_ATN 19 // ATN +#define PIN_RST 20 // RST +#define PIN_ACK 21 // ACK +#define PIN_REQ 22 // REQ +#define PIN_MSG 23 // MSG +#define PIN_CD 24 // CD +#define PIN_IO 25 // IO +#define PIN_BSY 26 // BSY +#define PIN_SEL 27 // SEL +#endif + +#ifdef CONNECT_TYPE_FULLSPEC +// +// RaSCSI 讓呎コ(SCSI隲也炊,讓呎コ悶ヴ繝ウ繧「繧オ繧、繝ウ) +// +#define CONNECT_DESC "FULLSPEC" // 襍キ蜍墓凾繝。繝繧サ繝シ繧ク + +// 菫。蜿キ蛻カ蠕。繝「繝シ繝蛾∈謚 +#define SIGNAL_CONTROL_MODE 0 // SCSI隲也炊莉墓ァ + +// 蛻カ蠕。菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ(-1縺ョ蝣エ蜷医ッ蛻カ蠕。辟。縺) +#define PIN_ACT 4 // ACTIVE +#define PIN_ENB 5 // ENABLE +#define PIN_IND 6 // INITIATOR CTRL DIRECTION +#define PIN_TAD 7 // TARGET CTRL DIRECTION +#define PIN_DTD 8 // DATA DIRECTION + +// 蛻カ蠕。菫。蜿キ蜃コ蜉幄ォ也炊 +#define ACT_ON TRUE // ACTIVE SIGNAL ON +#define ENB_ON TRUE // ENABLE SIGNAL ON +#define IND_IN FALSE // INITIATOR SIGNAL INPUT +#define TAD_IN FALSE // TARGET SIGNAL INPUT +#define DTD_IN TRUE // DATA SIGNAL INPUT + +// SCSI菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ +#define PIN_DT0 10 // 繝繝シ繧ソ0 +#define PIN_DT1 11 // 繝繝シ繧ソ1 +#define PIN_DT2 12 // 繝繝シ繧ソ2 +#define PIN_DT3 13 // 繝繝シ繧ソ3 +#define PIN_DT4 14 // 繝繝シ繧ソ4 +#define PIN_DT5 15 // 繝繝シ繧ソ5 +#define PIN_DT6 16 // 繝繝シ繧ソ6 +#define PIN_DT7 17 // 繝繝シ繧ソ7 +#define PIN_DP 18 // 繝代Μ繝繧」 +#define PIN_ATN 19 // ATN +#define PIN_RST 20 // RST +#define PIN_ACK 21 // ACK +#define PIN_REQ 22 // REQ +#define PIN_MSG 23 // MSG +#define PIN_CD 24 // CD +#define PIN_IO 25 // IO +#define PIN_BSY 26 // BSY +#define PIN_SEL 27 // SEL +#endif + +#ifdef CONNECT_TYPE_AIBOM +// +// RaSCSI Adapter 縺ゅ>縺シ繧迚 +// + +#define CONNECT_DESC "AIBOM PRODUCTS version" // 襍キ蜍墓凾繝。繝繧サ繝シ繧ク + +// 菫。蜿キ蛻カ蠕。繝「繝シ繝蛾∈謚 +#define SIGNAL_CONTROL_MODE 2 // SCSI豁」隲也炊莉墓ァ + +// 蛻カ蠕。菫。蜿キ蜃コ蜉幄ォ也炊 +#define ACT_ON TRUE // ACTIVE SIGNAL ON +#define ENB_ON TRUE // ENABLE SIGNAL ON +#define IND_IN FALSE // INITIATOR SIGNAL INPUT +#define TAD_IN FALSE // TARGET SIGNAL INPUT +#define DTD_IN FALSE // DATA SIGNAL INPUT + +// 蛻カ蠕。菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ(-1縺ョ蝣エ蜷医ッ蛻カ蠕。辟。縺) +#define PIN_ACT 4 // ACTIVE +#define PIN_ENB 17 // ENABLE +#define PIN_IND 27 // INITIATOR CTRL DIRECTION +#define PIN_TAD -1 // TARGET CTRL DIRECTION +#define PIN_DTD 18 // DATA DIRECTION + +// SCSI菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ +#define PIN_DT0 6 // 繝繝シ繧ソ0 +#define PIN_DT1 12 // 繝繝シ繧ソ1 +#define PIN_DT2 13 // 繝繝シ繧ソ2 +#define PIN_DT3 16 // 繝繝シ繧ソ3 +#define PIN_DT4 19 // 繝繝シ繧ソ4 +#define PIN_DT5 20 // 繝繝シ繧ソ5 +#define PIN_DT6 26 // 繝繝シ繧ソ6 +#define PIN_DT7 21 // 繝繝シ繧ソ7 +#define PIN_DP 5 // 繝代Μ繝繧」 +#define PIN_ATN 22 // ATN +#define PIN_RST 25 // RST +#define PIN_ACK 10 // ACK +#define PIN_REQ 7 // REQ +#define PIN_MSG 9 // MSG +#define PIN_CD 11 // CD +#define PIN_IO 23 // IO +#define PIN_BSY 24 // BSY +#define PIN_SEL 8 // SEL +#endif + +#ifdef CONNECT_TYPE_GAMERNIUM +// +// RaSCSI Adapter GAMERnium.com迚 +// + +#define CONNECT_DESC "GAMERnium.com version"// 襍キ蜍墓凾繝。繝繧サ繝シ繧ク + +// 菫。蜿キ蛻カ蠕。繝「繝シ繝蛾∈謚 +#define SIGNAL_CONTROL_MODE 0 // SCSI隲也炊莉墓ァ + +// 蛻カ蠕。菫。蜿キ蜃コ蜉幄ォ也炊 +#define ACT_ON TRUE // ACTIVE SIGNAL ON +#define ENB_ON TRUE // ENABLE SIGNAL ON +#define IND_IN FALSE // INITIATOR SIGNAL INPUT +#define TAD_IN FALSE // TARGET SIGNAL INPUT +#define DTD_IN TRUE // DATA SIGNAL INPUT + +// 蛻カ蠕。菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ(-1縺ョ蝣エ蜷医ッ蛻カ蠕。辟。縺) +#define PIN_ACT 14 // ACTIVE +#define PIN_ENB 6 // ENABLE +#define PIN_IND 7 // INITIATOR CTRL DIRECTION +#define PIN_TAD 8 // TARGET CTRL DIRECTION +#define PIN_DTD 5 // DATA DIRECTION + +// SCSI菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ +#define PIN_DT0 21 // 繝繝シ繧ソ0 +#define PIN_DT1 26 // 繝繝シ繧ソ1 +#define PIN_DT2 20 // 繝繝シ繧ソ2 +#define PIN_DT3 19 // 繝繝シ繧ソ3 +#define PIN_DT4 16 // 繝繝シ繧ソ4 +#define PIN_DT5 13 // 繝繝シ繧ソ5 +#define PIN_DT6 12 // 繝繝シ繧ソ6 +#define PIN_DT7 11 // 繝繝シ繧ソ7 +#define PIN_DP 25 // 繝代Μ繝繧」 +#define PIN_ATN 10 // ATN +#define PIN_RST 22 // RST +#define PIN_ACK 24 // ACK +#define PIN_REQ 15 // REQ +#define PIN_MSG 17 // MSG +#define PIN_CD 18 // CD +#define PIN_IO 4 // IO +#define PIN_BSY 27 // BSY +#define PIN_SEL 23 // SEL +#endif + +//--------------------------------------------------------------------------- +// +// 螳壽焚螳」險(GPIO) +// +//--------------------------------------------------------------------------- +#define GPIO_OFFSET 0x200000 +#define PADS_OFFSET 0x100000 +#define GPIO_INPUT 0 +#define GPIO_OUTPUT 1 +#define GPIO_PULLNONE 0 +#define GPIO_PULLDOWN 1 +#define GPIO_PULLUP 2 +#define GPIO_FSEL_0 0 +#define GPIO_FSEL_1 1 +#define GPIO_FSEL_2 2 +#define GPIO_FSEL_3 3 +#define GPIO_SET_0 7 +#define GPIO_CLR_0 10 +#define GPIO_LEV_0 13 +#define GPIO_EDS_0 16 +#define GPIO_REN_0 19 +#define GPIO_FEN_0 22 +#define GPIO_HEN_0 25 +#define GPIO_LEN_0 28 +#define GPIO_AREN_0 31 +#define GPIO_AFEN_0 34 +#define GPIO_PUD 37 +#define GPIO_CLK_0 38 +#define PAD_0_27 11 + +#define GPIO_INEDGE ((1 << PIN_BSY) | \ + (1 << PIN_SEL) | \ + (1 << PIN_ATN) | \ + (1 << PIN_ACK) | \ + (1 << PIN_RST)) + +#define GPIO_MCI ((1 << PIN_MSG) | \ + (1 << PIN_CD) | \ + (1 << PIN_IO)) + +//--------------------------------------------------------------------------- +// +// 螳壽焚螳」險(蛻カ蠕。菫。蜿キ) +// +//--------------------------------------------------------------------------- +#define ACT_OFF !ACT_ON +#define ENB_OFF !ENB_ON +#define TAD_OUT !TAD_IN +#define IND_OUT !IND_IN +#define DTD_OUT !DTD_IN + +//--------------------------------------------------------------------------- +// +// 螳壽焚螳」險(SCSI) +// +//--------------------------------------------------------------------------- +#define IN GPIO_INPUT +#define OUT GPIO_OUTPUT +#define ON TRUE +#define OFF FALSE + +//--------------------------------------------------------------------------- +// +// 螳壽焚螳」險(繝峨Λ繧、繝) +// +//--------------------------------------------------------------------------- +#define DEVICE_NAME "rascsidrv" +#define DRIVER_PATH "/dev/" DEVICE_NAME +#define IOCTL_INIT 0x100 +#define IOCTL_MODE 0x101 +#define IOCTL_PADS 0x102 + +//--------------------------------------------------------------------------- +// +// 蜍穂ス懊Δ繝シ繝 +// +//--------------------------------------------------------------------------- +enum mode_e { + TARGET = 0, + INITIATOR = 1, + MONITOR = 2, +}; + +//--------------------------------------------------------------------------- +// +// 繝峨Λ繧、繝宣未謨ー螳」險 +// +//--------------------------------------------------------------------------- +static int drv_init(void); +static void drv_exit(void); + +//--------------------------------------------------------------------------- +// +// 繧ィ繝ウ繝医Μ繝昴う繝ウ繝亥ョ」險 +// +//--------------------------------------------------------------------------- +int drv_open(struct inode *inode, struct file *file); +int drv_close(struct inode *inode, struct file *file); +long drv_ioctl(struct file *file, unsigned int cmd, unsigned long arg); +ssize_t drv_read( + struct file *file, char __user *buf, size_t count, loff_t *fops); +ssize_t drv_write( + struct file *file, const char __user *buf, size_t count, loff_t *fops); +struct file_operations drv_fops = { + .open = drv_open, + .release = drv_close, + .unlocked_ioctl = drv_ioctl, + .read = drv_read, + .write = drv_write, +}; + +//--------------------------------------------------------------------------- +// +// 螟画焚螳」險(繝峨Λ繧、繝千匳骭イ) +// +//--------------------------------------------------------------------------- +static dev_t drv_dev; +static dev_t drv_devno; +static struct cdev drv_cdev; +static struct class *drv_class; + +//--------------------------------------------------------------------------- +// +// 螟画焚螳」險(GPIO蛻カ蠕。) +// +//--------------------------------------------------------------------------- +static DWORD baseaddr; // BASE繧「繝峨Ξ繧ケ +static volatile DWORD *gpio; // GPIO繝ャ繧ク繧ケ繧ソ +static volatile DWORD *level; // GPIO繝ャ繧ク繧ケ繧ソ(繝ャ繝吶Ν) +static volatile DWORD *pads; // PADS繝ャ繧ク繧ケ繧ソ + +#if SIGNAL_CONTROL_MODE == 0 +static DWORD gpfsel[4]; // FSEL繝舌ャ繧ッ繧「繝繝 +#endif + +//--------------------------------------------------------------------------- +// +// 螟画焚螳」險(SCSI蛻カ蠕。) +// +//--------------------------------------------------------------------------- +static enum mode_e actmode; // 蜍穂ス懊Δ繝シ繝 +static DWORD signals; // SCSI蜈ィ菫。蜿キ + +static BOOL tblParity[256]; +#if SIGNAL_CONTROL_MODE == 0 +static DWORD tblDatMsk[3][256]; // 繝繝シ繧ソ繝槭せ繧ッ逕ィ繝繝シ繝悶Ν +static DWORD tblDatSet[3][256]; // 繝繝シ繧ソ險ュ螳夂畑繝繝シ繝悶Ν +#else +static DWORD tblDatMsk[256]; // 繝繝シ繧ソ繝槭せ繧ッ逕ィ繝繝シ繝悶Ν +static DWORD tblDatSet[256]; // 繝繝シ繧ソ險ュ螳夂畑繝繝シ繝悶Ν +#endif + +//--------------------------------------------------------------------------- +// +// 繝ッ繝シ繧ッ繝繝シ繝悶Ν菴懈 +// +//--------------------------------------------------------------------------- +void MakeTable(void) +{ + const int pintbl[] = { + PIN_DT0, PIN_DT1, PIN_DT2, PIN_DT3, PIN_DT4, + PIN_DT5, PIN_DT6, PIN_DT7, PIN_DP + }; + + int i; + int j; + DWORD bits; + DWORD parity; +#if SIGNAL_CONTROL_MODE == 0 + int index; + int shift; +#else + DWORD gpclr; + DWORD gpset; +#endif + + // 繝代Μ繝繧」繝繝シ繝悶Ν菴懈 + for (i = 0; i < 0x100; i++) { + bits = (DWORD)i; + parity = 0; + for (j = 0; j < 8; j++) { + parity ^= bits & 1; + bits >>= 1; + } + parity = ~parity; + tblParity[i] = parity & 1; + } + +#if SIGNAL_CONTROL_MODE == 0 + // 繝槭せ繧ッ縺ィ險ュ螳壹ョ繝シ繧ソ逕滓 + memset(tblDatMsk, 0xff, sizeof(tblDatMsk)); + memset(tblDatSet, 0x00, sizeof(tblDatSet)); + for (i = 0; i < 0x100; i++) { + // 讀懈渊逕ィ繝薙ャ繝亥 + bits = (DWORD)i; + + // 繝代Μ繝繧」蜿門セ + if (tblParity[i]) { + bits |= (1 << 8); + } + + // 繝薙ャ繝域、懈渊 + for (j = 0; j < 9; j++) { + // 繧、繝ウ繝繝繧ッ繧ケ縺ィ繧キ繝輔ヨ驥剰ィ育ョ + index = pintbl[j] / 10; + shift = (pintbl[j] % 10) * 3; + + // 繝槭せ繧ッ繝繝シ繧ソ + tblDatMsk[index][i] &= ~(0x7 << shift); + + // 險ュ螳壹ョ繝シ繧ソ + if (bits & 1) { + tblDatSet[index][i] |= (1 << shift); + } + + bits >>= 1; + } + } +#else + // 繝槭せ繧ッ縺ィ險ュ螳壹ョ繝シ繧ソ逕滓 + memset(tblDatMsk, 0x00, sizeof(tblDatMsk)); + memset(tblDatSet, 0x00, sizeof(tblDatSet)); + for (i = 0; i < 0x100; i++) { + // 讀懈渊逕ィ繝薙ャ繝亥 + bits = (DWORD)i; + + // 繝代Μ繝繧」蜿門セ + if (tblParity[i]) { + bits |= (1 << 8); + } + +#if SIGNAL_CONTROL_MODE == 1 + // 雋隲也炊縺ッ蜿崎サ「 + bits = ~bits; +#endif + + // GPIO繝ャ繧ク繧ケ繧ソ諠蝣ア縺ョ菴懈 + gpclr = 0; + gpset = 0; + for (j = 0; j < 9; j++) { + if (bits & 1) { + gpset |= (1 << pintbl[j]); + } else { + gpclr |= (1 << pintbl[j]); + } + bits >>= 1; + } + + tblDatMsk[i] = gpclr; + tblDatSet[i] = gpset; + } +#endif +} + +//--------------------------------------------------------------------------- +// +// 繝峨Λ繧、繝仙晄悄蛹 +// +//--------------------------------------------------------------------------- +static int drv_init(void) +{ + printk(KERN_INFO "RaSCSI GPIO Driver Loaded(%s)\n", CONNECT_DESC); + + // 繝繝舌う繧ケ逡ェ蜿キ蜿門セ + if (alloc_chrdev_region( + &drv_dev, + 0, + 1, + DEVICE_NAME) < 0) { + printk(KERN_DEBUG "Failed to allocate region\n"); + goto init_error; + } + + // 繧ッ繝ゥ繧ケ逋サ骭イ + if ((drv_class = class_create( + THIS_MODULE, + DEVICE_NAME)) == NULL) { + printk(KERN_DEBUG "Failed to create class\n"); + goto init_error; + } + + // 繝繝舌う繧ケ蛻晄悄蛹 + cdev_init(&drv_cdev, &drv_fops); + drv_cdev.owner = THIS_MODULE; + if (cdev_add(&drv_cdev, drv_dev, 1) < 0) { + printk(KERN_ALERT "Failed to add device\n"); + goto init_error; + } + + // 繝繝舌う繧ケ菴懈 + drv_devno = MKDEV(MAJOR(drv_dev), MINOR(drv_dev)); + if (device_create( + drv_class, + NULL, + drv_devno, + NULL, + DEVICE_NAME) == NULL) { + printk(KERN_DEBUG "Failed to create device\n"); + goto init_error; + } + + // 繝ッ繝シ繧ッ繝繝シ繝悶Ν逕滓 + MakeTable(); + + // 繝ッ繝シ繧ッ繧ッ繝ェ繧「 + baseaddr = ~0; + gpio = NULL; + level = NULL; + pads = NULL; + + return 0; + +init_error: + drv_exit(); + return -1; +} + +//--------------------------------------------------------------------------- +// +// 繝峨Λ繧、繝占ァ」謾セ +// +//--------------------------------------------------------------------------- +static void drv_exit(void) +{ + // 繧ッ繝ゥ繧ケ逋サ骭イ隗」髯、 + if (drv_class) { + device_destroy(drv_class, drv_devno); + class_destroy(drv_class); + drv_class = NULL; + } + + // 繝繝舌う繧ケ逋サ骭イ隗」髯、 + if (drv_dev){ + unregister_chrdev_region(drv_dev, 1); + drv_dev = 0; + } + + printk(KERN_INFO "RaSCSI GPIO Driver Unloaded\n"); +} + +//--------------------------------------------------------------------------- +// +// 繧ェ繝シ繝励Φ +// +//--------------------------------------------------------------------------- +int drv_open(struct inode *inode, struct file *file) +{ + // 蜍穂ス懊Δ繝シ繝牙晄悄蛹 + actmode = TARGET; + + return 0; +} + +//--------------------------------------------------------------------------- +// +// 繧ッ繝ュ繝シ繧コ +// +//--------------------------------------------------------------------------- +int drv_close(struct inode *inode, struct file *file) +{ + // 繧「繝ウ繝槭ャ繝 + if (gpio) { + iounmap(gpio); + gpio = NULL; + } + + if (pads) { + iounmap(pads); + pads = NULL; + } + + // 繝吶シ繧ケ繧「繝峨Ξ繧ケ繧ッ繝ェ繧「 + baseaddr = ~0; + + return 0; +} + +//--------------------------------------------------------------------------- +// +// 繝峨Λ繧、繝 IOCTL +// +//--------------------------------------------------------------------------- +long drv_ioctl( + struct file *file, unsigned int cmd, unsigned long arg) +{ + DWORD data; + DWORD drive; + + switch (cmd) { + case IOCTL_INIT: + // 蛻晄悄蛹悶ッ繧ェ繝シ繝励Φ蠕後↓1蝗樣剞繧 + if (baseaddr != ~0) { + break; + } + + // 繝吶シ繧ケ繧「繝峨Ξ繧ケ + baseaddr = arg; + + // GPIO繝ャ繧ク繧ケ繧ソ繧偵槭ャ繝 + gpio = (DWORD *)ioremap_nocache(baseaddr + GPIO_OFFSET, 164); + level = &gpio[GPIO_LEV_0]; + + // PADS繝ャ繧ク繧ケ繧ソ繧偵槭ャ繝 + pads = (DWORD *)ioremap_nocache(baseaddr + PADS_OFFSET, 56); + break; + + case IOCTL_MODE: + // 蜍穂ス懊Δ繝シ繝牙、画峩 + actmode = (enum mode_e)arg; + break; + + case IOCTL_PADS: + // DriveStrength螟画峩 + if (!pads) { + return -1; + } + + data = pads[PAD_0_27]; + drive = arg; + pads[PAD_0_27] = (0xFFFFFFF8 & data) | drive | 0x5a000000; + break; + + default: + break; + } + + return 0; +} + +//--------------------------------------------------------------------------- +// +// 繝舌せ菫。蜿キ蜿悶j霎シ縺ソ +// +//--------------------------------------------------------------------------- +static inline DWORD Aquire(void) +{ + signals = *level; + +#if SIGNAL_CONTROL_MODE < 2 + // 雋隲也炊縺ェ繧牙渚霆「縺吶k(蜀驛ィ蜃ヲ逅縺ッ豁」隲也炊縺ォ邨ア荳) + signals = ~signals; +#endif + + return signals; +} + +//--------------------------------------------------------------------------- +// +// 繝翫ヮ遘貞腰菴阪ョ繧ケ繝ェ繝シ繝 +// +// GPIO髢「菫ゅョ繝ャ繧ク繧ケ繧ソ縺ッ繧ウ繧「繧ッ繝ュ繝繧ッ縺400縺ョ譎ゅ↓險域クャ縺励◆騾溷コヲ繧貞盾閠縺ォ縺励◆縲 +// 繝ェ繝シ繝:48ns +// 繝ゥ繧、繝: 8ns +// +//--------------------------------------------------------------------------- +static inline void SleepNsec(DWORD nsec) +{ + DWORD count; + + count = (nsec + 8 - 1) / 8; + while (count--) { + gpio[GPIO_PUD] = 0; + } +} + +//--------------------------------------------------------------------------- +// +// 繧キ繧ー繝翫Ν險ュ螳 +// +//--------------------------------------------------------------------------- +static inline void SetSignal(int pin, BOOL ast) +{ +#if SIGNAL_CONTROL_MODE == 0 + int index; + int shift; + DWORD data; + + index = pin / 10; + shift = (pin % 10) * 3; + data = gpfsel[index]; + data &= ~(0x7 << shift); + if (ast) { + data |= (1 << shift); + } + gpio[GPIO_FSEL_0 + index] = data; + gpfsel[index] = data; +#elif SIGNAL_CONTROL_MODE == 1 + if (ast) { + gpio[GPIO_CLR_0] = 0x1 << pin; + } else { + gpio[GPIO_SET_0] = 0x1 << pin; + } +#elif SIGNAL_CONTROL_MODE == 2 + if (ast) { + gpio[GPIO_SET_0] = 0x1 << pin; + } else { + gpio[GPIO_CLR_0] = 0x1 << pin; + } +#endif +} + +//--------------------------------------------------------------------------- +// +// 繝繝シ繧ソ蜿門セ +// +//--------------------------------------------------------------------------- +static inline BYTE GetDAT(void) +{ + DWORD data; + + data = Aquire(); + data = + ((data >> (PIN_DT0 - 0)) & (1 << 0)) | + ((data >> (PIN_DT1 - 1)) & (1 << 1)) | + ((data >> (PIN_DT2 - 2)) & (1 << 2)) | + ((data >> (PIN_DT3 - 3)) & (1 << 3)) | + ((data >> (PIN_DT4 - 4)) & (1 << 4)) | + ((data >> (PIN_DT5 - 5)) & (1 << 5)) | + ((data >> (PIN_DT6 - 6)) & (1 << 6)) | + ((data >> (PIN_DT7 - 7)) & (1 << 7)); + + return (BYTE)data; +} + +//--------------------------------------------------------------------------- +// +// 繝繝シ繧ソ險ュ螳 +// +//--------------------------------------------------------------------------- +static inline void SetDAT(BYTE dat) +{ + // 繝昴シ繝医∈譖ク縺崎セシ縺ソ +#if SIGNAL_CONTROL_MODE == 0 + gpfsel[0] &= tblDatMsk[0][dat]; + gpfsel[0] |= tblDatSet[0][dat]; + gpio[GPIO_FSEL_0] = gpfsel[0]; + + gpfsel[1] &= tblDatMsk[1][dat]; + gpfsel[1] |= tblDatSet[1][dat]; + gpio[GPIO_FSEL_1] = gpfsel[1]; + + gpfsel[2] &= tblDatMsk[2][dat]; + gpfsel[2] |= tblDatSet[2][dat]; + gpio[GPIO_FSEL_2] = gpfsel[2]; +#else + gpio[GPIO_CLR_0] = tblDatMsk[dat]; + gpio[GPIO_SET_0] = tblDatSet[dat]; +#endif +} + +//--------------------------------------------------------------------------- +// +// 繝ェ繝シ繝 +// +//--------------------------------------------------------------------------- +ssize_t drv_read( + struct file *file, char __user *buf, size_t count, loff_t *fops) +{ + ssize_t i; + BYTE data; + DWORD loop; + DWORD phase; + +#if SIGNAL_CONTROL_MODE == 0 + // FSEL莠句燕蜿門セ + gpfsel[0] = gpio[GPIO_FSEL_0]; + gpfsel[1] = gpio[GPIO_FSEL_1]; + gpfsel[2] = gpio[GPIO_FSEL_2]; +#endif + + // 蜑イ繧願セシ縺ソ遖∵ュ「 + local_irq_disable(); + local_fiq_disable(); + + if (actmode == TARGET) { + for (i = 0; i < count; i++) { + // REQ繧「繧オ繝シ繝 + SetSignal(PIN_REQ, TRUE); + + // ACK繧「繧オ繝シ繝亥セ縺。 + loop = (DWORD)30000000; + do { + Aquire(); + loop--; + } while (!(signals & (1 << PIN_ACK)) && + !(signals & (1 << PIN_RST)) && loop > 0); + + // 繝繝シ繧ソ蜿門セ + data = GetDAT(); + + // REQ繝阪ご繝シ繝 + SetSignal(PIN_REQ, FALSE); + + // ACK繧「繧オ繝シ繝亥セ縺。縺ァ繧ソ繧、繝繧「繧ヲ繝 + if (loop == 0 || (signals & (1 << PIN_RST))) { + break; + } + + // ACK繝阪ご繝シ繝亥セ縺。 + loop = (DWORD)30000000; + do { + Aquire(); + loop--; + } while ((signals & (1 << PIN_ACK)) && + !(signals & (1 << PIN_RST)) && loop > 0); + + // ACK繝阪ご繝シ繝亥セ縺。縺ァ繧ソ繧、繝繧「繧ヲ繝 + if (loop == 0 || (signals & (1 << PIN_RST))) { + break; + } + + // 繝繝シ繧ソ霑泌唆 + if (copy_to_user(buf, (unsigned char *)&data, 1)) { + break; + } + + // 谺。繝繝シ繧ソ縺ク + buf++; + } + } else { + // 繝輔ぉ繝シ繧コ蜿門セ + Aquire(); + phase = signals & GPIO_MCI; + + for (i = 0; i < count; i++) { + // REQ繧「繧オ繝シ繝亥セ縺。 + loop = 30000000; + do { + Aquire(); + loop--; + } while (!(signals & (1 << PIN_REQ)) && + ((signals & GPIO_MCI) == phase) && loop > 0); + + // REQ繧「繧オ繝シ繝亥セ縺。縺ァ繧ソ繧、繝繧「繧ヲ繝 + if (loop == 0 || (signals & GPIO_MCI) != phase) { + break; + } + + // 繝繝シ繧ソ蜿門セ + data = GetDAT(); + + // ACK繧「繧オ繝シ繝 + SetSignal(PIN_ACK, TRUE); + + // REQ繝阪ご繝シ繝亥セ縺。 + loop = 30000000; + do { + Aquire(); + loop--; + } while ((signals & (1 << PIN_REQ)) && + ((signals & GPIO_MCI) == phase) && loop > 0); + + // ACK繝阪ご繝シ繝 + SetSignal(PIN_ACK, FALSE); + + // REQ繝阪ご繝シ繝亥セ縺。縺ァ繧ソ繧、繝繧「繧ヲ繝 + if (loop == 0 || (signals & GPIO_MCI) != phase) { + break; + } + + // 繝繝シ繧ソ霑泌唆 + if (copy_to_user(buf, (unsigned char *)&data, 1)) { + break; + } + + // 谺。繝繝シ繧ソ縺ク + buf++; + } + } + + // 蜑イ繧願セシ縺ソ遖∵ュ「隗」髯、 + local_fiq_enable(); + local_irq_enable(); + + return i; +} + +//--------------------------------------------------------------------------- +// +// 繝ゥ繧、繝 +// +//--------------------------------------------------------------------------- +ssize_t drv_write( + struct file *file, const char __user *buf, size_t count, loff_t *fops) +{ + size_t i; + BYTE data; + DWORD loop; + DWORD phase; + + // 蜑イ繧願セシ縺ソ遖∵ュ「 + local_irq_disable(); + local_fiq_disable(); + +#if SIGNAL_CONTROL_MODE == 0 + // FSEL莠句燕蜿門セ + gpfsel[0] = gpio[GPIO_FSEL_0]; + gpfsel[1] = gpio[GPIO_FSEL_1]; + gpfsel[2] = gpio[GPIO_FSEL_2]; +#endif + + if (actmode == TARGET) { + for (i = 0; i < count; i++) { + // 繝繝シ繧ソ蜿悶j霎シ縺ソ + if (copy_from_user((unsigned char *)&data, buf, 1)) { + break; + } + + // 繝繝シ繧ソ險ュ螳 + SetDAT(data); + + // 菫。蜿キ邱壹′螳牙ョ壹☆繧九∪縺ァ繧ヲ繧ァ繧、繝 + SleepNsec(150); + + // ACK繝阪ご繝シ繝亥セ縺。 + loop = (DWORD)30000000; + do { + Aquire(); + loop--; + } while ((signals & (1 << PIN_ACK)) && + !(signals & (1 << PIN_RST)) && loop > 0); + + // ACK繝阪ご繝シ繝亥セ縺。縺ァ繧ソ繧、繝繧「繧ヲ繝 + if (loop == 0 || (signals & (1 << PIN_RST))) { + break; + } + + // REQ繧「繧オ繝シ繝 + SetSignal(PIN_REQ, TRUE); + + // ACK繧「繧オ繝シ繝亥セ縺。 + loop = (DWORD)30000000; + do { + Aquire(); + loop--; + } while (!(signals & (1 << PIN_ACK)) && + !(signals & (1 << PIN_RST)) && loop > 0); + + // REQ繝阪ご繝シ繝 + SetSignal(PIN_REQ, FALSE); + + // ACK繧「繧オ繝シ繝亥セ縺。縺ァ繧ソ繧、繝繧「繧ヲ繝 + if (loop == 0 || (signals & (1 << PIN_RST))) { + break; + } + + // 谺。繝繝シ繧ソ + buf++; + }; + + // ACK繝阪ご繝シ繝亥セ縺。 + loop = (DWORD)30000000; + do { + Aquire(); + loop--; + } while ((signals & (1 << PIN_ACK)) && + !(signals & (1 << PIN_RST)) && loop > 0); + } else { + // 繝輔ぉ繝シ繧コ蜿門セ + Aquire(); + phase = signals & GPIO_MCI; + + for (i = 0; i < count; i++) { + // 繝繝シ繧ソ蜿悶j霎シ縺ソ + if (copy_from_user((unsigned char *)&data, buf, 1)) { + break; + } + + // REQ繧「繧オ繝シ繝亥セ縺。 + loop = (DWORD)30000000; + do { + Aquire(); + loop--; + } while (!(signals & (1 << PIN_REQ)) && + ((signals & GPIO_MCI) == phase) && loop > 0); + + // REQ繧「繧オ繝シ繝亥セ縺。縺ァ繧ソ繧、繝繧「繧ヲ繝 + if (loop == 0 || (signals & GPIO_MCI) != phase) { + break; + } + + // 繝繝シ繧ソ險ュ螳 + SetDAT(data); + + // 菫。蜿キ邱壹′螳牙ョ壹☆繧九∪縺ァ繧ヲ繧ァ繧、繝 + SleepNsec(150); + + // ACK繧「繧オ繝シ繝 + SetSignal(PIN_ACK, TRUE); + + // REQ繝阪ご繝シ繝亥セ縺。 + loop = (DWORD)30000000; + do { + Aquire(); + loop--; + } while ((signals & (1 << PIN_REQ)) && + ((signals & GPIO_MCI) == phase) && loop > 0); + + // ACK繝阪ご繝シ繝 + SetSignal(PIN_ACK, FALSE); + + // REQ繝阪ご繝シ繝亥セ縺。縺ァ繧ソ繧、繝繧「繧ヲ繝 + if (loop == 0 || (signals & GPIO_MCI) != phase) { + break; + } + + // 谺。繝繝シ繧ソ縺ク + buf++; + } + } + + // 蜑イ繧願セシ縺ソ遖∵ュ「隗」髯、 + local_fiq_enable(); + local_irq_enable(); + + return i; +} + +module_init(drv_init); +module_exit(drv_exit); + +MODULE_DESCRIPTION("RASCSI GPIO Driver"); +MODULE_VERSION("1.0"); +MODULE_AUTHOR("GIMONS"); +MODULE_LICENSE("GPL"); diff --git a/src/raspberrypi/log.h b/src/raspberrypi/log.h new file mode 100644 index 00000000..4448418f --- /dev/null +++ b/src/raspberrypi/log.h @@ -0,0 +1,31 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technology. +// Copyright (C) 2016-2018 GIMONS +// [ 繝ュ繧ー ] +// +//--------------------------------------------------------------------------- + +#if !defined(log_h) +#define log_h + +//=========================================================================== +// +// 繝ュ繧ー +// +//=========================================================================== +class Log +{ +public: + enum loglevel { + Detail, // 隧ウ邏ー繝ャ繝吶Ν + Normal, // 騾壼クク繝ャ繝吶Ν + Warning, // 隴ヲ蜻翫Ξ繝吶Ν + Debug // 繝繝舌ャ繧ー繝ャ繝吶Ν + }; +}; + +#endif // log_h diff --git a/src/raspberrypi/os.h b/src/raspberrypi/os.h new file mode 100644 index 00000000..d2d043e9 --- /dev/null +++ b/src/raspberrypi/os.h @@ -0,0 +1,145 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technology. +// Copyright (C) 2016-2018 GIMONS +// +// Imported NetBSD support and some optimisation patch by Rin Okuyama. +// +// [ OS蝗コ譛 ] +// +//--------------------------------------------------------------------------- + +#if !defined(os_h) +#define os_h + +//--------------------------------------------------------------------------- +// +// #define +// +//--------------------------------------------------------------------------- +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif + +#ifndef _FILE_OFFSET_BITS +#define _FILE_OFFSET_BITS 64 +#endif + +//--------------------------------------------------------------------------- +// +// #include +// +//--------------------------------------------------------------------------- + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(__linux__) +#include +#include +#elif defined(__NetBSD__) +#include +#include +#include +#include +#include +#include +#else +#error unsupported platform +#endif + +//--------------------------------------------------------------------------- +// +// 蝓コ譛ャ繝槭け繝ュ +// +//--------------------------------------------------------------------------- +#undef FASTCALL +#define FASTCALL + +#undef CDECL +#define CDECL + +#undef INLINE +#define INLINE + +#if !defined(ASSERT) +#if !defined(NDEBUG) +#define ASSERT(cond) assert(cond) +#else +#define ASSERT(cond) ((void)0) +#endif // NDEBUG +#endif // ASSERT + +#if !defined(ASSERT_DIAG) +#if !defined(NDEBUG) +#define ASSERT_DIAG() AssertDiag() +#else +#define ASSERT_DIAG() ((void)0) +#endif // NDEBUG +#endif // ASSERT_DIAG + +//--------------------------------------------------------------------------- +// +// 蝓コ譛ャ蝙句ョ夂セゥ +// +//--------------------------------------------------------------------------- +typedef unsigned char BYTE; +typedef unsigned short WORD; +typedef unsigned long DWORD; +typedef int BOOL; +typedef char TCHAR; +typedef char *LPTSTR; +typedef const char *LPCTSTR; +typedef const char *LPCSTR; + +#if !defined(FALSE) +#define FALSE 0 +#endif + +#if !defined(TRUE) +#define TRUE 1 +#endif + +#if !defined(_T) +#define _T(x) x +#endif + +#define _MAX_PATH 260 +#define _MAX_DRIVE 3 +#define _MAX_DIR 256 +#define _MAX_FNAME 256 +#define _MAX_EXT 256 + +#define off64_t off_t + +#define xstrcasecmp strcasecmp +#define xstrncasecmp strncasecmp + +#endif // os_h diff --git a/src/raspberrypi/rascsi.cpp b/src/raspberrypi/rascsi.cpp new file mode 100644 index 00000000..a697f101 --- /dev/null +++ b/src/raspberrypi/rascsi.cpp @@ -0,0 +1,758 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technology. +// Copyright (C) 2016-2018 GIMONS +// [ 繝。繧、繝ウ ] +// +//--------------------------------------------------------------------------- + +#include "os.h" +#include "xm6.h" +#include "fileio.h" +#include "filepath.h" +#include "disk.h" +#include "gpiobus.h" + +//--------------------------------------------------------------------------- +// +// 螟画焚螳」險 +// +//--------------------------------------------------------------------------- +enum { + CtrlMax = 8, // 譛螟ァSCSI繧ウ繝ウ繝医Ο繝シ繝ゥ謨ー +}; + +SASIDEV *ctrl[CtrlMax]; // 繧ウ繝ウ繝医Ο繝シ繝ゥ +Disk *disk[CtrlMax]; // 繝繧」繧ケ繧ッ +Filepath image[CtrlMax]; // 繧、繝。繝シ繧ク繝輔ぃ繧、繝ォ繝代せ +GPIOBUS bus; // 繝舌せ +BUS::phase_t phase; // 繝輔ぉ繝シ繧コ +int actid; // 繧「繧ッ繝繧」繝悶↑繧ウ繝ウ繝医Ο繝シ繝ゥID +volatile BOOL bRun; // 螳溯。御クュ繝輔Λ繧ー + +BOOL bServer; // 繧オ繝シ繝舌シ繝「繝シ繝峨ヵ繝ゥ繧ー +int monfd; // 繝「繝九ち繝シ逕ィ繧ス繧ア繝繝FD +pthread_t monthread; // 繝「繝九ち繝シ繧ケ繝ャ繝繝 +static void *MonThread(void *param); + +//--------------------------------------------------------------------------- +// +// 繧キ繧ー繝翫Ν蜃ヲ逅 +// +//--------------------------------------------------------------------------- +void KillHandler(int sig) +{ + // 蛛懈ュ「謖遉コ + bRun = FALSE; +} + +//--------------------------------------------------------------------------- +// +// 繝舌リ繝シ蜃コ蜉 +// +//--------------------------------------------------------------------------- +BOOL Banner(int argc, char* argv[]) +{ + printf("SCSI Target Emulator RaSCSI(*^..^*) "); + printf("version %01d.%01d%01d\n", + (int)((VERSION >> 8) & 0xf), + (int)((VERSION >> 4) & 0xf), + (int)((VERSION ) & 0xf)); + printf("Powered by XM6 TypeG Technology / "); + printf("Copyright (C) 2016-2018 GIMONS\n"); + printf("Connect type : %s\n", CONNECT_DESC); + + if (argc > 1 && strcmp(argv[1], "-h") == 0) { + printf("\n"); + printf("Usage: %s [-ID{0|1|2|3|4|5|6|7} FILE] ...\n\n", argv[0]); + printf(" IDn is SCSI identification number.\n"); + printf(" FILE is disk image file.\n\n"); + printf(" Detected images type based on file extension.\n"); + printf(" hdf : SASI HD image(XM6 SASI HD image)\n"); + printf(" hds : SCSI HD image(XM6 SCSI HD image)\n"); + printf(" hdn : SCSI HD image(NEC GENUINE)\n"); + printf(" hdi : SCSI HD image(Anex86 HD image)\n"); + printf(" nhd : SCSI HD image(T98Next HD image)\n"); + printf(" hda : SCSI HD image(APPLE GENUINE)\n"); + printf(" mos : SCSI MO image(XM6 SCSI MO image)\n"); + printf(" iso : SCSI CD image(ISO 9660 image)\n"); + return FALSE; + } + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 蛻晄悄蛹 +// +//--------------------------------------------------------------------------- +BOOL Init() +{ + int i; + struct sockaddr_in server; + + // 繝「繝九ち繝シ逕ィ繧ス繧ア繝繝育函謌 + monfd = socket(PF_INET, SOCK_STREAM, 0); + memset(&server, 0, sizeof(server)); + server.sin_family = PF_INET; + server.sin_port = htons(6868); + server.sin_addr.s_addr = htonl(INADDR_ANY); + if (bind(monfd, (struct sockaddr *)&server, + sizeof(struct sockaddr_in)) < 0) { + if (errno != EADDRINUSE) { + return FALSE; + } + bServer = FALSE; + return TRUE; + } else { + bServer = TRUE; + } + + // 蜑イ繧願セシ縺ソ繝上Φ繝峨Λ險ュ螳 + if (signal(SIGINT, KillHandler) == SIG_ERR) { + return FALSE; + } + if (signal(SIGHUP, KillHandler) == SIG_ERR) { + return FALSE; + } + if (signal(SIGTERM, KillHandler) == SIG_ERR) { + return FALSE; + } + + // GPIO蛻晄悄蛹 + if (!bus.Init()) { + return FALSE; + } + + // 繧ウ繝ウ繝医Ο繝シ繝ゥ蛻晄悄蛹 + for (i = 0; i < CtrlMax; i++) { + ctrl[i] = NULL; + } + + // 繝繧」繧ケ繧ッ蛻晄悄蛹 + for (i = 0; i < CtrlMax; i++) { + disk[i] = NULL; + } + + // 繧、繝。繝シ繧ク繝代せ蛻晄悄蛹 + for (i = 0; i < CtrlMax; i++) { + image[i].Clear(); + } + + // 繧「繧ッ繝繧」繝蜂D蛻晄悄蛹 + actid = -1; + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繧ッ繝ェ繝シ繝ウ繧「繝繝 +// +//--------------------------------------------------------------------------- +void Cleanup() +{ + int i; + + // 繝繧」繧ケ繧ッ蜑企勁 + for (i = 0; i < CtrlMax; i++) { + if (disk[i]) { + delete disk[i]; + disk[i] = NULL; + } + } + + // 繧ウ繝ウ繝医Ο繝シ繝ゥ蜑企勁 + for (i = 0; i < CtrlMax; i++) { + if (ctrl[i]) { + delete ctrl[i]; + ctrl[i] = NULL; + } + } + + // 繝舌せ繧偵け繝ェ繝シ繝ウ繧「繝繝 + bus.Cleanup(); + + // 繝「繝九ち繝シ逕ィ繧ス繧ア繝繝医け繝ュ繝シ繧コ + if (monfd >= 0) { + close(monfd); + } +} + +//--------------------------------------------------------------------------- +// +// 繝ェ繧サ繝繝 +// +//--------------------------------------------------------------------------- +void Reset() +{ + int i; + + // 繧「繧ッ繝繧」繝蜂D蛻晄悄蛹 + actid = -1; + + // 繧ウ繝ウ繝医Ο繝シ繝ゥ繝ェ繧サ繝繝 + for (i = 0; i < CtrlMax; i++) { + if (ctrl[i]) { + ctrl[i]->Reset(); + } + } + + // 繝舌せ菫。蜿キ邱壹r繝ェ繧サ繝繝 + bus.Reset(); +} + +//--------------------------------------------------------------------------- +// +// 繝繝舌う繧ケ荳隕ァ陦ィ遉コ +// +//--------------------------------------------------------------------------- +void ListDevice(FILE *fp) +{ + int i; + Filepath filepath; + BOOL find; + char type[5]; + + find = FALSE; + type[4] = 0; + for (i = 0; i < 8; i++) { + if (disk[i] == NULL) { + continue; + } + + // 繝倥ャ繝繝シ蜃コ蜉 + if (!find) { + fprintf(fp, "\n"); + fprintf(fp, "---+------+---------------------------------------\n"); + fprintf(fp, "ID | TYPE | DEVICE STATUS\n"); + fprintf(fp, "---+------+---------------------------------------\n"); + find = TRUE; + } + + // ID,繧ソ繧、繝怜コ蜉 + type[0] = (char)(disk[i]->GetID() >> 24); + type[1] = (char)(disk[i]->GetID() >> 16); + type[2] = (char)(disk[i]->GetID() >> 8); + type[3] = (char)(disk[i]->GetID()); + fprintf(fp, " %d | %s | ", i, type); + + // 繝槭え繝ウ繝育憾諷句コ蜉 + if (disk[i]->GetID() == MAKEID('S', 'C', 'B', 'R')) { + fprintf(fp, "%s", "RaSCSI BRIDGE"); + } else { + disk[i]->GetPath(filepath); + fprintf(fp, "%s", + (disk[i]->IsRemovable() && !disk[i]->IsReady()) ? + "NO MEDIA" : filepath.GetPath()); + } + + // 繝ゥ繧、繝医励Ο繝繧ッ繝育憾諷句コ蜉 + if (disk[i]->IsRemovable() && disk[i]->IsReady() && disk[i]->IsWriteP()) { + fprintf(fp, "(WRITEPROTECT)"); + } + + // 谺。縺ョ陦後∈ + fprintf(fp, "\n"); + } + + // 繧ウ繝ウ繝医Ο繝シ繝ゥ縺檎┌縺蝣エ蜷 + if (!find) { + fprintf(fp, "No device is installed.\n"); + return; + } + + fprintf(fp, "---+------+---------------------------------------\n"); +} + +//--------------------------------------------------------------------------- +// +// 繧ウ繝槭Φ繝牙ヲ逅 +// +//--------------------------------------------------------------------------- +BOOL ProcessCmd(FILE *fp, int id, int cmd, int type, char *file) +{ + int len; + char *ext; + Filepath filepath; + + // ID繝√ぉ繝繧ッ + if (id < 0 || id > 7) { + fprintf(fp, "Error : Invalid ID\n"); + return FALSE; + } + + // 謗・邯壹さ繝槭Φ繝 + if (cmd == 0) { // ATTACH + // 繧ウ繝ウ繝医Ο繝シ繝ゥ繧定ァ」謾セ + if (ctrl[id]) { + ctrl[id]->SetUnit(0, NULL); + delete ctrl[id]; + ctrl[id] = NULL; + } + + // 繝繧」繧ケ繧ッ繧定ァ」謾セ + if (disk[id]) { + delete disk[id]; + disk[id] = NULL; + } + + // SASI縺ィSCSI繧定ヲ句縺代k + if (type == 0) { + // 繝代せ繝√ぉ繝繧ッ + if (!file) { + return FALSE; + } + + // 譛菴5譁蟄 + len = strlen(file); + if (len < 5) { + return FALSE; + } + + // 諡。蠑オ蟄舌メ繧ァ繝繧ッ + if (file[len - 4] != '.') { + return FALSE; + } + + // 諡。蠑オ蟄舌′SASI繧ソ繧、繝励〒辟。縺代l縺ーSCSI縺ォ蟾ョ縺玲崛縺 + ext = &file[len - 3]; + if (xstrcasecmp(ext, "hdf") != 0) { + type = 1; + } + } + + // 繧ソ繧、繝怜挨縺ョ繧、繝ウ繧ケ繧ソ繝ウ繧ケ繧堤函謌 + switch (type) { + case 0: // HDF + disk[id] = new SASIHD(); + break; + case 1: // HDS/HDN/HDI/NHD/HDA + if (xstrcasecmp(ext, "hdn") == 0 || + xstrcasecmp(ext, "hdi") == 0 || xstrcasecmp(ext, "nhd") == 0) { + disk[id] = new SCSIHD_NEC(); + } else if (xstrcasecmp(ext, "hda") == 0) { + disk[id] = new SCSIHD_APPLE(); + } else { + disk[id] = new SCSIHD(); + } + break; + case 2: // MO + disk[id] = new SCSIMO(); + break; + case 3: // CD + disk[id] = new SCSICD(); + break; + case 4: // BRIDGE + disk[id] = new SCSIBR(); + break; + default: + fprintf(fp, "Error : Invalid device type\n"); + return FALSE; + } + + // 繧ソ繧、繝励↓蜷医o縺帙※繧ウ繝ウ繝医Ο繝シ繝ゥ繧剃ス懊k + if (type == 0) { + ctrl[id] = new SASIDEV(); + } else { + ctrl[id] = new SCSIDEV(); + } + + // 繝峨Λ繧、繝悶ッ繝輔ぃ繧、繝ォ縺ョ遒コ隱阪r陦後≧ + if (type <= 1 || (type <= 3 && xstrcasecmp(file, "-") != 0)) { + // 繝代せ繧定ィュ螳 + filepath.SetPath(file); + + // 繧ェ繝シ繝励Φ + if (!disk[id]->Open(filepath)) { + fprintf(fp, "Error : File open error [%s]\n", file); + delete disk[id]; + disk[id] = NULL; + delete ctrl[id]; + ctrl[id] = NULL; + return FALSE; + } + } + + // 繝ゥ繧、繝医せ繝ォ繝シ縺ォ險ュ螳 + disk[id]->SetCacheWB(FALSE); + + // 譁ー縺溘↑繝繧」繧ケ繧ッ繧呈磁邯 + ctrl[id]->Connect(id, &bus); + ctrl[id]->SetUnit(0, disk[id]); + return TRUE; + } + + // 譛牙柑縺ェ繧ウ繝槭Φ繝峨° + if (cmd > 4) { + fprintf(fp, "Error : Invalid command\n"); + return FALSE; + } + + // 繧ウ繝ウ繝医Ο繝シ繝ゥ縺悟ュ伜惠縺吶k縺 + if (ctrl[id] == NULL) { + fprintf(fp, "Error : No such device\n"); + return FALSE; + } + + // 繝繧」繧ケ繧ッ縺悟ュ伜惠縺吶k縺 + if (disk[id] == NULL) { + fprintf(fp, "Error : No such device\n"); + return FALSE; + } + + // 蛻譁ュ繧ウ繝槭Φ繝 + if (cmd == 1) { // DETACH + ctrl[id]->SetUnit(0, NULL); + delete disk[id]; + disk[id] = NULL; + delete ctrl[id]; + ctrl[id] = NULL; + return TRUE; + } + + // MO縺気D縺ョ蝣エ蜷医□縺第怏蜉ケ + if (disk[id]->GetID() != MAKEID('S', 'C', 'M', 'O') && + disk[id]->GetID() != MAKEID('S', 'C', 'C', 'D')) { + fprintf(fp, "Error : Operation denied(Deveice isn't MO or CD)\n"); + return FALSE; + } + + switch (cmd) { + case 2: // INSERT + // 繝代せ繧定ィュ螳 + filepath.SetPath(file); + + // 繧ェ繝シ繝励Φ + if (!disk[id]->Open(filepath)) { + fprintf(fp, "Error : File open error [%s]\n", file); + return FALSE; + } + break; + + case 3: // EJECT + disk[id]->Eject(TRUE); + break; + + case 4: // PROTECT + if (disk[id]->GetID() != MAKEID('S', 'C', 'M', 'O')) { + fprintf(fp, "Error : Operation denied(Deveice isn't MO)\n"); + return FALSE; + } + disk[id]->WriteP(!disk[id]->IsWriteP()); + break; + default: + ASSERT(FALSE); + return FALSE; + } + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 蠑墓焚蜃ヲ逅 +// +//--------------------------------------------------------------------------- +BOOL ParseArgument(int argc, char* argv[]) +{ + int i; + int id; + int type; + char *argID; + char *argPath; + int len; + char *ext; + + // ID縺ィ繝代せ謖螳壹′縺ェ縺代l縺ー蜃ヲ逅繧剃クュ譁ュ + if (argc < 3) { + return TRUE; + } + + // 蠑墓焚縺ョ隗」隱ュ髢句ァ + i = 1; + argc--; + + // ID縺ィ繝代せ繧貞叙蠕 + while (argc >= 2) { + argc -= 2; + argID = argv[i++]; + argPath = argv[i++]; + + // -ID or -id縺ョ蠖「蠑上r繝√ぉ繝繧ッ + if (strlen(argID) != 4 || xstrncasecmp(argID, "-id", 3) != 0) { + fprintf(stderr, + "Error : Invalid argument(-IDn) [%s]\n", argID); + return FALSE; + } + + // ID逡ェ蜿キ繧偵メ繧ァ繝繧ッ(0-7) + if (argID[3] < '0' || argID[3] > '7') { + fprintf(stderr, + "Error : Invalid argument(-IDn n=0-7) [%c]\n", argID[3]); + return FALSE; + } + + // ID遒コ螳 + id = argID[3] - '0'; + + // 縺吶〒縺ォ繧「繧ッ繝繧」繝悶↑繝繝舌う繧ケ縺後≠繧九↑繧峨せ繧ュ繝繝 + if (disk[id]) { + continue; + } + + // 繝繝舌う繧ケ繧ソ繧、繝励r蛻晄悄蛹 + type = -1; + + // 繧、繝シ繧オ繝阪ャ繝医→繝帙せ繝医ヶ繝ェ繝繧ク縺ョ繝√ぉ繝繧ッ + if (xstrcasecmp(argPath, "bridge") == 0) { + type = 4; + } else { + // 繝代せ縺ョ髟キ縺輔r繝√ぉ繝繧ッ + len = strlen(argPath); + if (len < 5) { + fprintf(stderr, + "Error : Invalid argument(File path is short) [%s]\n", + argPath); + return FALSE; + } + + // 諡。蠑オ蟄舌r謖√▲縺ヲ縺繧九°シ + if (argPath[len - 4] != '.') { + fprintf(stderr, + "Error : Invalid argument(No extension) [%s]\n", argPath); + return FALSE; + } + + // 繧ソ繧、繝励r豎コ繧√k + ext = &argPath[len - 3]; + if (xstrcasecmp(ext, "hdf") == 0 || + xstrcasecmp(ext, "hds") == 0 || + xstrcasecmp(ext, "hdn") == 0 || + xstrcasecmp(ext, "hdi") == 0 || xstrcasecmp(ext, "nhd") == 0 || + xstrcasecmp(ext, "hda") == 0) { + // HD(SASI/SCSI) + type = 0; + } else if (strcasecmp(ext, "mos") == 0) { + // MO + type = 2; + } else if (strcasecmp(ext, "iso") == 0) { + // CD + type = 3; + } else { + // 繧ソ繧、繝励′蛻、蛻・縺ァ縺阪↑縺 + fprintf(stderr, + "Error : Invalid argument(file type) [%s]\n", ext); + return FALSE; + } + } + + // 繧ウ繝槭Φ繝牙ョ溯。 + if (!ProcessCmd(stderr, id, 0, type, argPath)) { + return FALSE; + } + } + + // 繝繝舌う繧ケ繝ェ繧ケ繝郁。ィ遉コ + ListDevice(stdout); + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繝「繝九ち繝シ繧ケ繝ャ繝繝 +// +//--------------------------------------------------------------------------- +static void *MonThread(void *param) +{ + struct sockaddr_in client; + socklen_t len; + int fd; + FILE *fp; + BYTE buf[BUFSIZ]; + int id; + int cmd; + int type; + char *file; + BOOL list; + + // 逶」隕匁コ門y + listen(monfd, 1); + + while (1) { + // 謗・邯壼セ縺。 + memset(&client, 0, sizeof(client)); + len = sizeof(client); + fd = accept(monfd, (struct sockaddr*)&client, &len); + if (fd < 0) { + break; + } + + // 繧ウ繝槭Φ繝牙叙蠕 + fp = fdopen(fd, "r+"); + fgets((char *)buf, BUFSIZ, fp); + buf[strlen((const char*)buf) - 1] = 0; + + // 繝繝舌う繧ケ繝ェ繧ケ繝郁。ィ遉コ縺ェ縺ョ縺句宛蠕。繧ウ繝槭Φ繝峨°繧貞愛譁ュ + if (strncasecmp((char*)buf, "list", 4) == 0) { + list = TRUE; + } else { + list = FALSE; + id = (int)(buf[0] - '0'); + cmd = (int)(buf[2] - '0'); + type = (int)(buf[4] - '0'); + file = (char*)&buf[6]; + } + + // 繝舌せ繝輔Μ繝シ縺ョ繧ソ繧、繝溘Φ繧ー縺セ縺ァ蠕縺、 + while (phase != BUS::busfree) { + usleep(500 * 1000); + } + + if (list) { + // 繝ェ繧ケ繝郁。ィ遉コ + ListDevice(fp); + } else { + // 繧ウ繝槭Φ繝牙ョ溯。 + ProcessCmd(fp, id, cmd, type, file); + } + + // 謗・邯夊ァ」謾セ + fclose(fp); + close(fd); + } + + return NULL; +} + +//--------------------------------------------------------------------------- +// +// 荳サ蜃ヲ逅 +// +//--------------------------------------------------------------------------- +int main(int argc, char* argv[]) +{ + int i; + DWORD dwBusBak; + DWORD dwBusIn; + struct sched_param schparam; + + // 繝舌リ繝シ蜃コ蜉 + if (!Banner(argc, argv)) { + exit(0); + } + + // 蛻晄悄蛹 + if (!Init()) { + fprintf(stderr, "Error : Initializing\n"); + + // 諱舌i縺俊oot縺ァ縺ッ辟。縺シ + exit(EPERM); + } + + // 譌「縺ォ襍キ蜍輔@縺ヲ縺繧具シ + if (!bServer) { + fprintf(stderr, "Error : Already running RaSCSI\n"); + exit(0); + } + + // 讒狗ッ + if (!ParseArgument(argc, argv)) { + // 繧ッ繝ェ繝シ繝ウ繧「繝繝 + Cleanup(); + + // 蠑墓焚繧ィ繝ゥ繝シ縺ァ邨ゆコ + exit(EINVAL); + } + + // 繝「繝九ち繝シ繧ケ繝ャ繝繝臥函謌 + bRun = TRUE; + pthread_create(&monthread, NULL, MonThread, NULL); + + // 繝ェ繧サ繝繝 + Reset(); + + // 繝。繧、繝ウ繝ォ繝シ繝玲コ門y + phase = BUS::busfree; + dwBusBak = bus.Aquire(); + + // 繝。繧、繝ウ繝ォ繝シ繝 + while(bRun) { + // 繝舌せ縺ョ蜈・蜉帑ソ。蜿キ螟牙喧讀懷コ + dwBusIn = bus.Aquire(); + + // 蜈・蜉帑ソ。蜿キ螟牙喧讀懷コ + if ((dwBusIn & GPIO_INEDGE) == (dwBusBak & GPIO_INEDGE)) { + usleep(0); + continue; + } + + // 繝舌せ縺ョ蜈・蜉帑ソ。蜿キ繧剃ソ晏ュ + dwBusBak = dwBusIn; + + // 縺昴b縺昴b繧サ繝ャ繧ッ繧キ繝ァ繝ウ菫。蜿キ縺檎┌縺代l縺ー辟。隕 + if (!bus.GetSEL() || bus.GetBSY()) { + continue; + } + + // 蜈ィ繧ウ繝ウ繝医Ο繝シ繝ゥ縺ォ騾夂衍 + for (i = 0; i < CtrlMax; i++) { + if (!ctrl[i]) { + continue; + } + + // 繧サ繝ャ繧ッ繧キ繝ァ繝ウ繝輔ぉ繝シ繧コ縺ォ遘サ陦後@縺溘ち繝シ繧イ繝繝医r謗「縺 + if (ctrl[i]->Process() == BUS::selection) { + // 繧ソ繝シ繧イ繝繝医ョID繧貞叙蠕 + actid = i; + + // 繧サ繝ャ繧ッ繧キ繝ァ繝ウ繝輔ぉ繝シ繧コ + phase = BUS::selection; + break; + } + } + + // 繧サ繝ャ繧ッ繧キ繝ァ繝ウ繝輔ぉ繝シ繧コ縺碁幕蟋九&繧後※縺縺ェ縺代l縺ー繝舌せ縺ョ逶」隕悶∈謌サ繧 + if (phase != BUS::selection) { + continue; + } + + // 繧ソ繝シ繧イ繝繝郁オー陦碁幕蟋 + + // 繧ケ繧ア繧ク繝・繝シ繝ェ繝ウ繧ー繝昴Μ繧キ繝シ險ュ螳(譛蜆ェ蜈) + schparam.sched_priority = sched_get_priority_max(SCHED_FIFO); + sched_setscheduler(0, SCHED_FIFO, &schparam); + + // 繝舌せ繝輔Μ繝シ縺ォ縺ェ繧九∪縺ァ繝ォ繝シ繝 + while (bRun) { + // 繧ソ繝シ繧イ繝繝磯ァ蜍 + phase = ctrl[actid]->Process(); + + // 繝舌せ繝輔Μ繝シ縺ォ縺ェ縺」縺溘i邨ゆコ + if (phase == BUS::busfree) { + break; + } + } + + // 繝舌せ繝輔Μ繝シ縺ァ繧サ繝繧キ繝ァ繝ウ邨ゆコ + actid = -1; + phase = BUS::busfree; + bus.Reset(); + dwBusBak = bus.Aquire(); + + // 繧ケ繧ア繧ク繝・繝シ繝ェ繝ウ繧ー繝昴Μ繧キ繝シ險ュ螳(繝弱シ繝槭Ν) + schparam.sched_priority = 0; + sched_setscheduler(0, SCHED_OTHER, &schparam); + } + + // 繧ッ繝ェ繝シ繝ウ繧「繝繝 + Cleanup(); + + // 邨ゆコ + exit(0); +} diff --git a/src/raspberrypi/rasctl.cpp b/src/raspberrypi/rasctl.cpp new file mode 100644 index 00000000..3759ce8d --- /dev/null +++ b/src/raspberrypi/rasctl.cpp @@ -0,0 +1,247 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technology. +// Copyright (C) 2016-2018 GIMONS +// [ 蛻カ蠕。繧ウ繝槭Φ繝蛾∽ソ。 ] +// +//--------------------------------------------------------------------------- + +#include "os.h" + +//--------------------------------------------------------------------------- +// +// 繧ウ繝槭Φ繝蛾∽ソ。 +// +//--------------------------------------------------------------------------- +BOOL SendCommand(char *buf) +{ + int fd; + struct sockaddr_in server; + FILE *fp; + + // 繧ウ繝槭Φ繝臥畑繧ス繧ア繝繝育函謌 + fd = socket(PF_INET, SOCK_STREAM, 0); + memset(&server, 0, sizeof(server)); + server.sin_family = PF_INET; + server.sin_port = htons(6868); + server.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + + // 謗・邯 + if (connect(fd, (struct sockaddr *)&server, + sizeof(struct sockaddr_in)) < 0) { + fprintf(stderr, "Error : Can't connect to rascsi process\n"); + return FALSE; + } + + // 騾∽ソ。 + fp = fdopen(fd, "r+"); + setvbuf(fp, NULL, _IONBF, 0); + fprintf(fp, buf); + + // 繝。繝繧サ繝シ繧ク蜿嶺ソ。 + while (1) { + if (fgets((char *)buf, BUFSIZ, fp) == NULL) { + break; + } + printf("%s", buf); + } + + // 繧ス繧ア繝繝医r髢峨§繧 + fclose(fp); + close(fd); + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 荳サ蜃ヲ逅 +// +//--------------------------------------------------------------------------- +int main(int argc, char* argv[]) +{ + int opt; + int id; + int cmd; + int type; + char *file; + BOOL list; + int len; + char *ext; + char buf[BUFSIZ]; + + id = -1; + cmd = -1; + type = -1; + file = NULL; + list = FALSE; + + // 繝倥Ν繝励ョ陦ィ遉コ + if (argc < 2) { + fprintf(stderr, "SCSI Target Emulator RaSCSI Controller\n"); + fprintf(stderr, + "Usage: %s -i ID [-c CMD] [-t TYPE] [-f FILE]\n", + argv[0]); + fprintf(stderr, " where ID := {0|1|2|3|4|5|6|7}\n"); + fprintf(stderr, " CMD := {attach|detatch|insert|eject|protect}\n"); + fprintf(stderr, " TYPE := {hd|mo|cd|bridge}\n"); + fprintf(stderr, " FILE := image file path\n"); + fprintf(stderr, " CMD is 'attach' or 'insert' and FILE parameter is required.\n"); + fprintf(stderr, "Usage: %s -l\n", argv[0]); + fprintf(stderr, " Print device list.\n"); + exit(0); + } + + // 蠑墓焚隗」譫 + opterr = 0; + while ((opt = getopt(argc, argv, "i:c:t:f:l")) != -1) { + switch (opt) { + case 'i': + id = optarg[0] - '0'; + break; + + case 'c': + switch (optarg[0]) { + case 'a': // ATTACH + case 'A': + cmd = 0; + break; + case 'd': // DETACH + case 'D': + cmd = 1; + break; + case 'i': // INSERT + case 'I': + cmd = 2; + break; + case 'e': // EJECT + case 'E': + cmd = 3; + break; + case 'p': // PROTECT + case 'P': + cmd = 4; + break; + } + break; + + case 't': + switch (optarg[0]) { + case 's': // HD(SASI) + case 'S': + case 'h': // HD(SCSI) + case 'H': + type = 0; + break; + case 'm': // MO + case 'M': + type = 2; + break; + case 'c': // CD + case 'C': + type = 3; + break; + case 'b': // BRIDGE + case 'B': + type = 4; + break; + } + break; + + case 'f': + file = optarg; + break; + + case 'l': + list = TRUE; + break; + } + } + + // 繝ェ繧ケ繝郁。ィ遉コ縺ョ縺ソ + if (id < 0 && cmd < 0 && type < 0 && file == NULL && list) { + sprintf(buf, "list\n"); + SendCommand(buf); + exit(0); + } + + // ID繝√ぉ繝繧ッ + if (id < 0 || id > 7) { + fprintf(stderr, "Error : Invalid ID\n"); + exit(EINVAL); + } + + // 繧ウ繝槭Φ繝峨メ繧ァ繝繧ッ + if (cmd < 0) { + cmd = 0; // 繝繝輔か繝ォ繝医ッATTATCH縺ィ縺吶k + } + + // 繧ソ繧、繝励メ繧ァ繝繧ッ + if (cmd == 0 && type < 0) { + + // 諡。蠑オ蟄舌°繧峨ち繧、繝怜愛蛻・繧定ゥヲ縺ソ繧 + len = file ? strlen(file) : 0; + if (len > 4 && file[len - 4] == '.') { + ext = &file[len - 3]; + if (xstrcasecmp(ext, "hdf") == 0 || + xstrcasecmp(ext, "hds") == 0 || + xstrcasecmp(ext, "hdn") == 0 || + xstrcasecmp(ext, "hdi") == 0 || + xstrcasecmp(ext, "nhd") == 0 || + xstrcasecmp(ext, "hda") == 0) { + // HD(SASI/SCSI) + type = 0; + } else if (xstrcasecmp(ext, "mos") == 0) { + // MO + type = 2; + } else if (xstrcasecmp(ext, "iso") == 0) { + // CD + type = 3; + } + } + + if (type < 0) { + fprintf(stderr, "Error : Invalid type\n"); + exit(EINVAL); + } + } + + // 繝輔ぃ繧、繝ォ繝√ぉ繝繧ッ(繧ウ繝槭Φ繝峨ッATTACH縺ァ繧ソ繧、繝励ッHD) + if (cmd == 0 && type >= 0 && type <= 1) { + if (!file) { + fprintf(stderr, "Error : Invalid file path\n"); + exit(EINVAL); + } + } + + // 繝輔ぃ繧、繝ォ繝√ぉ繝繧ッ(繧ウ繝槭Φ繝峨ッINSERT) + if (cmd == 2) { + if (!file) { + fprintf(stderr, "Error : Invalid file path\n"); + exit(EINVAL); + } + } + + // 蠢隕√〒縺ェ縺дype縺ッ0縺ィ縺励※縺翫¥ + if (type < 0) { + type = 0; + } + + // 騾∽ソ。繧ウ繝槭Φ繝臥函謌 + sprintf(buf, "%d %d %d %s\n", id, cmd, type, file ? file : "-"); + if (!SendCommand(buf)) { + exit(ENOTCONN); + } + + // 繝ェ繧ケ繝郁。ィ遉コ + if (list) { + sprintf(buf, "list\n"); + SendCommand(buf); + } + + // 邨ゆコ + exit(0); +} diff --git a/src/raspberrypi/rasdump.cpp b/src/raspberrypi/rasdump.cpp new file mode 100644 index 00000000..c1ceef53 --- /dev/null +++ b/src/raspberrypi/rasdump.cpp @@ -0,0 +1,1006 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technology. +// Copyright (C) 2016-2018 GIMONS +// [ HDD繝繝ウ繝励Θ繝シ繝繧」繝ェ繝繧」(繧、繝九す繝シ繧ィ繧ソ繝「繝シ繝) ] +// +//--------------------------------------------------------------------------- + +#include "os.h" +#include "xm6.h" +#include "fileio.h" +#include "filepath.h" +#include "gpiobus.h" + +//--------------------------------------------------------------------------- +// +// 螳壽焚螳」險 +// +//--------------------------------------------------------------------------- +#define BUFSIZE 1024 * 64 // 64KB縺舌i縺縺九↑縺 + +//--------------------------------------------------------------------------- +// +// 螟画焚螳」險 +// +//--------------------------------------------------------------------------- +GPIOBUS bus; // 繝舌せ +int targetid; // 繧ソ繝シ繧イ繝繝医ョ繝舌う繧ケID +int boardid; // 繝懊シ繝迂D(閾ェ霄ォ縺ョID) +Filepath hdsfile; // HDS繝輔ぃ繧、繝ォ +BOOL restore; // 繝ェ繧ケ繝医い繝輔Λ繧ー +BYTE buffer[BUFSIZE]; // 繝ッ繝シ繧ッ繝舌ャ繝輔ぃ +int result; // 邨先棡繧ウ繝シ繝 + +//--------------------------------------------------------------------------- +// +// 髢「謨ー螳」險 +// +//--------------------------------------------------------------------------- +void Cleanup(); + +//--------------------------------------------------------------------------- +// +// 繧キ繧ー繝翫Ν蜃ヲ逅 +// +//--------------------------------------------------------------------------- +void KillHandler(int sig) +{ + // 蛛懈ュ「謖遉コ + Cleanup(); + exit(0); +} + +//--------------------------------------------------------------------------- +// +// 繝舌リ繝シ蜃コ蜉 +// +//--------------------------------------------------------------------------- +BOOL Banner(int argc, char* argv[]) +{ + printf("RaSCSI hard disk dump utility "); + printf("version %01d.%01d%01d\n", + (int)((VERSION >> 8) & 0xf), + (int)((VERSION >> 4) & 0xf), + (int)((VERSION ) & 0xf)); + + if (argc < 2 || strcmp(argv[1], "-h") == 0) { + printf("Usage: %s -i ID [-b BID] -f FILE [-r]\n", argv[0]); + printf(" ID is target device SCSI ID {0|1|2|3|4|5|6|7}.\n"); + printf(" BID is rascsi board SCSI ID {0|1|2|3|4|5|6|7}. Default is 7.\n"); + printf(" FILE is HDS file path.\n"); + printf(" -r is restore operation.\n"); + return FALSE; + } + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 蛻晄悄蛹 +// +//--------------------------------------------------------------------------- +BOOL Init() +{ + // 蜑イ繧願セシ縺ソ繝上Φ繝峨Λ險ュ螳 + if (signal(SIGINT, KillHandler) == SIG_ERR) { + return FALSE; + } + if (signal(SIGHUP, KillHandler) == SIG_ERR) { + return FALSE; + } + if (signal(SIGTERM, KillHandler) == SIG_ERR) { + return FALSE; + } + + // GPIO蛻晄悄蛹 + if (!bus.Init(BUS::INITIATOR)) { + return FALSE; + } + + // 繝ッ繝シ繧ッ蛻晄悄蛹 + targetid = -1; + boardid = 7; + restore = FALSE; + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繧ッ繝ェ繝シ繝ウ繧「繝繝 +// +//--------------------------------------------------------------------------- +void Cleanup() +{ + // 繝舌せ繧偵け繝ェ繝シ繝ウ繧「繝繝 + bus.Cleanup(); +} + +//--------------------------------------------------------------------------- +// +// 繝ェ繧サ繝繝 +// +//--------------------------------------------------------------------------- +void Reset() +{ + // 繝舌せ菫。蜿キ邱壹r繝ェ繧サ繝繝 + bus.Reset(); +} + +//--------------------------------------------------------------------------- +// +// 蠑墓焚蜃ヲ逅 +// +//--------------------------------------------------------------------------- +BOOL ParseArgument(int argc, char* argv[]) +{ + int opt; + char *file; + + // 蛻晄悄蛹 + file = NULL; + + // 蠑墓焚隗」譫 + opterr = 0; + while ((opt = getopt(argc, argv, "i:b:f:r")) != -1) { + switch (opt) { + case 'i': + targetid = optarg[0] - '0'; + break; + + case 'b': + boardid = optarg[0] - '0'; + break; + + case 'f': + file = optarg; + break; + + case 'r': + restore = TRUE; + break; + } + } + + // TARGET ID繝√ぉ繝繧ッ + if (targetid < 0 || targetid > 7) { + fprintf(stderr, + "Error : Invalid target id range\n"); + return FALSE; + } + + // BOARD ID繝√ぉ繝繧ッ + if (boardid < 0 || boardid > 7) { + fprintf(stderr, + "Error : Invalid board id range\n"); + return FALSE; + } + + // TARGET縺ィBOARD縺ョID驥崎、繝√ぉ繝繧ッ + if (targetid == boardid) { + fprintf(stderr, + "Error : Invalid target or board id\n"); + return FALSE; + } + + // 繝輔ぃ繧、繝ォ繝√ぉ繝繧ッ + if (!file) { + fprintf(stderr, + "Error : Invalid file path\n"); + return FALSE; + } + + hdsfile.SetPath(file); + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繝輔ぉ繝シ繧コ蠕縺。 +// +//--------------------------------------------------------------------------- +BOOL WaitPhase(BUS::phase_t phase) +{ + int count; + + // REQ繧貞セ縺、(6遘) + count = 30000; + do { + usleep(200); + bus.Aquire(); + if (bus.GetREQ()) { + break; + } + } while (count--); + + // 繝輔ぉ繝シ繧コ縺御ク閾エ縺吶l縺ーOK + bus.Aquire(); + if (bus.GetPhase() == phase) { + return TRUE; + } + + // 繝輔ぉ繝シ繧コ縺御ク閾エ縺吶l縺ーOK(繝ェ繝医Λ繧、) + usleep(1000 * 1000); + bus.Aquire(); + if (bus.GetPhase() == phase) { + return TRUE; + } + + return FALSE; +} + +//--------------------------------------------------------------------------- +// +// 繝舌せ繝輔Μ繝シ繝輔ぉ繝シ繧コ螳溯。 +// +//--------------------------------------------------------------------------- +void BusFree() +{ + bus.Reset(); +} + +//--------------------------------------------------------------------------- +// +// 繧サ繝ャ繧ッ繧キ繝ァ繝ウ繝輔ぉ繝シ繧コ螳溯。 +// +//--------------------------------------------------------------------------- +BOOL Selection(int id) +{ + BYTE data; + int count; + + // ID險ュ螳壹→SEL繧「繧オ繝シ繝 + data = 0; + data |= (1 << boardid); + data |= (1 << id); + bus.SetDAT(data); + bus.SetSEL(TRUE); + + // BSY繧貞セ縺、 + count = 10000; + do { + usleep(20); + bus.Aquire(); + if (bus.GetBSY()) { + break; + } + } while (count--); + + // SEL繝阪ご繝シ繝 + bus.SetSEL(FALSE); + + // 繧ソ繝シ繧イ繝繝医′繝薙ず繝シ迥カ諷九↑繧画仙粥 + return bus.GetBSY(); +} + +//--------------------------------------------------------------------------- +// +// 繧ウ繝槭Φ繝峨ヵ繧ァ繝シ繧コ螳溯。 +// +//--------------------------------------------------------------------------- +BOOL Command(BYTE *buf, int length) +{ + int count; + + // 繝輔ぉ繝シ繧コ蠕縺。 + if (!WaitPhase(BUS::command)) { + return FALSE; + } + + // 繧ウ繝槭Φ繝蛾∽ソ。 + count = bus.SendHandShake(buf, length); + + // 騾∽ソ。邨先棡縺御セ晞シ謨ー縺ィ蜷後§縺ェ繧画仙粥 + if (count == length) { + return TRUE; + } + + // 騾∽ソ。繧ィ繝ゥ繝シ + return FALSE; +} + +//--------------------------------------------------------------------------- +// +// 繝繝シ繧ソ繧、繝ウ繝輔ぉ繝シ繧コ螳溯。 +// +//--------------------------------------------------------------------------- +int DataIn(BYTE *buf, int length) +{ + int count; + + // 繝輔ぉ繝シ繧コ蠕縺。 + if (!WaitPhase(BUS::datain)) { + return -1; + } + + // 繝繝シ繧ソ蜿嶺ソ。 + return bus.ReceiveHandShake(buf, length); +} + +//--------------------------------------------------------------------------- +// +// 繝繝シ繧ソ繧「繧ヲ繝医ヵ繧ァ繝シ繧コ螳溯。 +// +//--------------------------------------------------------------------------- +int DataOut(BYTE *buf, int length) +{ + int count; + + // 繝輔ぉ繝シ繧コ蠕縺。 + if (!WaitPhase(BUS::dataout)) { + return -1; + } + + // 繝繝シ繧ソ蜿嶺ソ。 + return bus.SendHandShake(buf, length); +} + +//--------------------------------------------------------------------------- +// +// 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ螳溯。 +// +//--------------------------------------------------------------------------- +int Status() +{ + BYTE buf[256]; + + // 繝輔ぉ繝シ繧コ蠕縺。 + if (!WaitPhase(BUS::status)) { + return -2; + } + + // 繝繝シ繧ソ蜿嶺ソ。 + if (bus.ReceiveHandShake(buf, 1) == 1) { + return (int)buf[0]; + } + + // 蜿嶺ソ。繧ィ繝ゥ繝シ + return -1; +} + +//--------------------------------------------------------------------------- +// +// 繝。繝繧サ繝シ繧ク繧、繝ウ繝輔ぉ繝シ繧コ螳溯。 +// +//--------------------------------------------------------------------------- +int MessageIn() +{ + BYTE buf[256]; + + // 繝輔ぉ繝シ繧コ蠕縺。 + if (!WaitPhase(BUS::msgin)) { + return -2; + } + + // 繝繝シ繧ソ蜿嶺ソ。 + if (bus.ReceiveHandShake(buf, 1) == 1) { + return (int)buf[0]; + } + + // 蜿嶺ソ。繧ィ繝ゥ繝シ + return -1; +} + +//--------------------------------------------------------------------------- +// +// TEST UNIT READY螳溯。 +// +//--------------------------------------------------------------------------- +int TestUnitReady(int id) +{ + BYTE cmd[256]; + + // 邨先棡繧ウ繝シ繝牙晄悄蛹 + result = 0; + + // SELECTION + if (!Selection(id)) { + result = -1; + goto exit; + } + + // COMMAND + memset(cmd, 0x00, 6); + cmd[0] = 0x00; + if (!Command(cmd, 6)) { + result = -2; + goto exit; + } + + // STATUS + if (Status() < 0) { + result = -4; + goto exit; + } + + // MESSAGE IN + if (MessageIn() < 0) { + result = -5; + goto exit; + } + +exit: + // 繝舌せ繝輔Μ繝シ + BusFree(); + + return result; +} + +//--------------------------------------------------------------------------- +// +// REQUEST SENSE螳溯。 +// +//--------------------------------------------------------------------------- +int RequestSense(int id, BYTE *buf) +{ + BYTE cmd[256]; + int count; + + // 邨先棡繧ウ繝シ繝牙晄悄蛹 + result = 0; + + // SELECTION + if (!Selection(id)) { + result = -1; + goto exit; + } + + // COMMAND + memset(cmd, 0x00, 6); + cmd[0] = 0x03; + cmd[4] = 0xff; + if (!Command(cmd, 6)) { + result = -2; + goto exit; + } + + // DATAIN + memset(buf, 0x00, sizeof(buf)); + count = DataIn(buf, 256); + if (count <= 0) { + result = -3; + goto exit; + } + + // STATUS + if (Status() < 0) { + result = -4; + goto exit; + } + + // MESSAGE IN + if (MessageIn() < 0) { + result = -5; + goto exit; + } + +exit: + // 繝舌せ繝輔Μ繝シ + BusFree(); + + // 謌仙粥縺ァ縺ゅl縺ー霆「騾∵焚繧定ソ斐☆ + if (result == 0) { + return count; + } + + return result; +} + +//--------------------------------------------------------------------------- +// +// MODE SENSE螳溯。 +// +//--------------------------------------------------------------------------- +int ModeSense(int id, BYTE *buf) +{ + BYTE cmd[256]; + int count; + + // 邨先棡繧ウ繝シ繝牙晄悄蛹 + result = 0; + + // SELECTION + if (!Selection(id)) { + result = -1; + goto exit; + } + + // COMMAND + memset(cmd, 0x00, 6); + cmd[0] = 0x1a; + cmd[2] = 0x3f; + cmd[4] = 0xff; + if (!Command(cmd, 6)) { + result = -2; + goto exit; + } + + // DATAIN + memset(buf, 0x00, sizeof(buf)); + count = DataIn(buf, 256); + if (count <= 0) { + result = -3; + goto exit; + } + + // STATUS + if (Status() < 0) { + result = -4; + goto exit; + } + + // MESSAGE IN + if (MessageIn() < 0) { + result = -5; + goto exit; + } + +exit: + // 繝舌せ繝輔Μ繝シ + BusFree(); + + // 謌仙粥縺ァ縺ゅl縺ー霆「騾∵焚繧定ソ斐☆ + if (result == 0) { + return count; + } + + return result; +} + +//--------------------------------------------------------------------------- +// +// INQUIRY螳溯。 +// +//--------------------------------------------------------------------------- +int Inquiry(int id, BYTE *buf) +{ + BYTE cmd[256]; + int count; + + // 邨先棡繧ウ繝シ繝牙晄悄蛹 + result = 0; + + // SELECTION + if (!Selection(id)) { + result = -1; + goto exit; + } + + // COMMAND + memset(cmd, 0x00, 6); + cmd[0] = 0x12; + cmd[4] = 0xff; + if (!Command(cmd, 6)) { + result = -2; + goto exit; + } + + // DATAIN + memset(buf, 0x00, sizeof(buf)); + count = DataIn(buf, 255); + if (count <= 0) { + result = -3; + goto exit; + } + + // STATUS + if (Status() < 0) { + result = -4; + goto exit; + } + + // MESSAGE IN + if (MessageIn() < 0) { + result = -5; + goto exit; + } + +exit: + // 繝舌せ繝輔Μ繝シ + BusFree(); + + // 謌仙粥縺ァ縺ゅl縺ー霆「騾∵焚繧定ソ斐☆ + if (result == 0) { + return count; + } + + return result; +} + +//--------------------------------------------------------------------------- +// +// READ CAPACITY螳溯。 +// +//--------------------------------------------------------------------------- +int ReadCapacity(int id, BYTE *buf) +{ + BYTE cmd[256]; + int count; + + // 邨先棡繧ウ繝シ繝牙晄悄蛹 + result = 0; + + // SELECTION + if (!Selection(id)) { + result = -1; + goto exit; + } + + // COMMAND + memset(cmd, 0x00, 10); + cmd[0] = 0x25; + if (!Command(cmd, 10)) { + result = -2; + goto exit; + } + + // DATAIN + memset(buf, 0x00, sizeof(buf)); + count = DataIn(buf, 8); + if (count <= 0) { + result = -3; + goto exit; + } + + // STATUS + if (Status() < 0) { + result = -4; + goto exit; + } + + // MESSAGE IN + if (MessageIn() < 0) { + result = -5; + goto exit; + } + +exit: + // 繝舌せ繝輔Μ繝シ + BusFree(); + + // 謌仙粥縺ァ縺ゅl縺ー霆「騾∵焚繧定ソ斐☆ + if (result == 0) { + return count; + } + + return result; +} + +//--------------------------------------------------------------------------- +// +// READ10螳溯。 +// +//--------------------------------------------------------------------------- +int Read10(int id, DWORD bstart, DWORD blength, DWORD length, BYTE *buf) +{ + BYTE cmd[256]; + int count; + + // 邨先棡繧ウ繝シ繝牙晄悄蛹 + result = 0; + + // SELECTION + if (!Selection(id)) { + result = -1; + goto exit; + } + + // COMMAND + memset(cmd, 0x00, 10); + cmd[0] = 0x28; + cmd[2] = (BYTE)(bstart >> 24); + cmd[3] = (BYTE)(bstart >> 16); + cmd[4] = (BYTE)(bstart >> 8); + cmd[5] = (BYTE)bstart; + cmd[7] = (BYTE)(blength >> 8); + cmd[8] = (BYTE)blength; + if (!Command(cmd, 10)) { + result = -2; + goto exit; + } + + // DATAIN + count = DataIn(buf, length); + if (count <= 0) { + result = -3; + goto exit; + } + + // STATUS + if (Status() < 0) { + result = -4; + goto exit; + } + + // MESSAGE IN + if (MessageIn() < 0) { + result = -5; + goto exit; + } + +exit: + // 繝舌せ繝輔Μ繝シ + BusFree(); + + // 謌仙粥縺ァ縺ゅl縺ー霆「騾∵焚繧定ソ斐☆ + if (result == 0) { + return count; + } + + return result; +} + +//--------------------------------------------------------------------------- +// +// WRITE10螳溯。 +// +//--------------------------------------------------------------------------- +int Write10(int id, DWORD bstart, DWORD blength, DWORD length, BYTE *buf) +{ + BYTE cmd[256]; + int count; + + // 邨先棡繧ウ繝シ繝牙晄悄蛹 + result = 0; + + // SELECTION + if (!Selection(id)) { + result = -1; + goto exit; + } + + // COMMAND + memset(cmd, 0x00, 10); + cmd[0] = 0x2a; + cmd[2] = (BYTE)(bstart >> 24); + cmd[3] = (BYTE)(bstart >> 16); + cmd[4] = (BYTE)(bstart >> 8); + cmd[5] = (BYTE)bstart; + cmd[7] = (BYTE)(blength >> 8); + cmd[8] = (BYTE)blength; + if (!Command(cmd, 10)) { + result = -2; + goto exit; + } + + // DATAOUT + count = DataOut(buf, length); + if (count <= 0) { + result = -3; + goto exit; + } + + // STATUS + if (Status() < 0) { + result = -4; + goto exit; + } + + // MESSAGE IN + if (MessageIn() < 0) { + result = -5; + goto exit; + } + +exit: + // 繝舌せ繝輔Μ繝シ + BusFree(); + + // 謌仙粥縺ァ縺ゅl縺ー霆「騾∵焚繧定ソ斐☆ + if (result == 0) { + return count; + } + + return result; +} + +//--------------------------------------------------------------------------- +// +// 荳サ蜃ヲ逅 +// +//--------------------------------------------------------------------------- +int main(int argc, char* argv[]) +{ + int i; + int count; + char str[32]; + DWORD bsiz; + DWORD bnum; + DWORD duni; + DWORD dsiz; + DWORD dnum; + DWORD rest; + Fileio fio; + Fileio::OpenMode omode; + off64_t size; + + // 繝舌リ繝シ蜃コ蜉 + if (!Banner(argc, argv)) { + exit(0); + } + + // 蛻晄悄蛹 + if (!Init()) { + fprintf(stderr, "Error : Initializing\n"); + + // 諱舌i縺俊oot縺ァ縺ッ辟。縺シ + exit(EPERM); + } + + // 讒狗ッ + if (!ParseArgument(argc, argv)) { + // 繧ッ繝ェ繝シ繝ウ繧「繝繝 + Cleanup(); + + // 蠑墓焚繧ィ繝ゥ繝シ縺ァ邨ゆコ + exit(EINVAL); + } + + // 繝ェ繧サ繝繝 + Reset(); + + // 繝輔ぃ繧、繝ォ繧ェ繝シ繝励Φ + if (restore) { + omode = Fileio::ReadOnly; + } else { + omode = Fileio::WriteOnly; + } + if (!fio.Open(hdsfile.GetPath(), omode)) { + fprintf(stderr, "Error : Can't open hds file\n"); + + // 繧ッ繝ェ繝シ繝ウ繧「繝繝 + Cleanup(); + exit(EPERM); + } + + // 繝舌せ繝輔Μ繝シ + BusFree(); + + // RESET繧キ繧ー繝翫Ν逋コ陦 + bus.SetRST(TRUE); + usleep(1000); + bus.SetRST(FALSE); + + // 繝繝ウ繝鈴幕蟋 + printf("TARGET ID : %d\n", targetid); + printf("BORAD ID : %d\n", boardid); + + // TEST UNIT READY + count = TestUnitReady(targetid); + if (count < 0) { + fprintf(stderr, "TEST UNIT READY ERROR %d\n", count); + goto cleanup_exit; + } + + // REQUEST SENSE(for CHECK CONDITION) + count = RequestSense(targetid, buffer); + if (count < 0) { + fprintf(stderr, "REQUEST SENSE ERROR %d\n", count); + goto cleanup_exit; + } + + // INQUIRY + count = Inquiry(targetid, buffer); + if (count < 0) { + fprintf(stderr, "INQUIRY ERROR %d\n", count); + goto cleanup_exit; + } + + // INQUIRY縺ョ諠蝣ア繧定。ィ遉コ + memset(str, 0x00, sizeof(str)); + memcpy(str, &buffer[8], 8); + printf("Vendor : %s\n", str); + memset(str, 0x00, sizeof(str)); + memcpy(str, &buffer[16], 16); + printf("Product : %s\n", str); + memset(str, 0x00, sizeof(str)); + memcpy(str, &buffer[32], 4); + printf("Revison : %s\n", str); + + // 螳ケ驥丞叙蠕 + count = ReadCapacity(targetid, buffer); + if (count < 0) { + fprintf(stderr, "READ CAPACITY ERROR %d\n", count); + goto cleanup_exit; + } + + // 繝悶Ο繝繧ッ繧オ繧、繧コ縺ィ繝悶Ο繝繧ッ謨ー縺ョ陦ィ遉コ + bsiz = + (buffer[4] << 24) | (buffer[5] << 16) | + (buffer[6] << 8) | buffer[7]; + bnum = + (buffer[0] << 24) | (buffer[1] << 16) | + (buffer[2] << 8) | buffer[3]; + bnum++; + printf("Number of blocks : %d Blocks\n", bnum); + printf("Block length : %d Bytes\n", bsiz); + printf("Unit Capacity : %d MBytes %d Bytes\n", + bsiz * bnum / 1024 / 1024, + bsiz * bnum); + + // 繝ェ繧ケ繝医い繝輔ぃ繧、繝ォ繧オ繧、繧コ縺ョ蜿門セ + if (restore) { + size = fio.GetFileSize(); + printf("Restore file size : %d bytes", (int)size); + if (size != (off64_t)(bsiz * bnum)) { + printf("(WARNING : File size isn't equal to disk size)"); + } + printf("\n"); + } + + // 繝舌ャ繝輔ぃ繧オ繧、繧コ豈弱↓繝繝ウ繝励☆繧 + duni = BUFSIZE; + duni /= bsiz; + dsiz = BUFSIZE; + dnum = bnum * bsiz; + dnum /= BUFSIZE; + + if (restore) { + printf("Restore progress : "); + } else { + printf("Dump progress : "); + } + + for (i = 0; i < dnum; i++) { + if (i > 0) { + printf("\033[21D"); + printf("\033[0K"); + } + printf("%3d\%(%7d/%7d)", (i + 1) * 100 / dnum, i * duni, bnum); + fflush(stdout); + + if (restore) { + if (fio.Read(buffer, dsiz)) { + if (Write10(targetid, i * duni, duni, dsiz, buffer) >= 0) { + continue; + } + } + } else { + if (Read10(targetid, i * duni, duni, dsiz, buffer) >= 0) { + if (fio.Write(buffer, dsiz)) { + continue; + } + } + } + + printf("\n"); + printf("Error occured and aborted... %d\n", result); + goto cleanup_exit; + } + + // 螳ケ驥丈ク翫ョ遶ッ謨ー蜃ヲ逅 + dnum = bnum % duni; + dsiz = dnum * bsiz; + if (dnum > 0) { + if (restore) { + if (fio.Read(buffer, dsiz)) { + Write10(targetid, i * duni, duni, dsiz, buffer); + } + } else { + if (Read10(targetid, i * duni, dnum, dsiz, buffer) >= 0) { + fio.Write(buffer, dsiz); + } + } + } + + // 螳御コ繝。繝繧サ繝シ繧ク + printf("\033[21D"); + printf("\033[0K"); + printf("%3d\%(%7d/%7d)\n", 100, bnum, bnum); + +cleanup_exit: + // 繝輔ぃ繧、繝ォ繧ッ繝ュ繝シ繧コ + fio.Close(); + + // 繧ッ繝ェ繝シ繝ウ繧「繝繝 + Cleanup(); + + // 邨ゆコ + exit(0); +} diff --git a/src/raspberrypi/scsi.cpp b/src/raspberrypi/scsi.cpp new file mode 100644 index 00000000..b74e5aa6 --- /dev/null +++ b/src/raspberrypi/scsi.cpp @@ -0,0 +1,58 @@ +//--------------------------------------------------------------------------- +// +// X68000 EMULATOR "XM6" +// +// Copyright (C) 2001-2006 シーシゥシ(ytanaka@ipc-tokai.or.jp) +// Copyright (C) 2014-2018 GIMONS +// +// [ SCSI蜈ア騾 ] +// +//--------------------------------------------------------------------------- + +#include "os.h" +#include "xm6.h" +#include "scsi.h" + +//--------------------------------------------------------------------------- +// +// 繝輔ぉ繝シ繧コ蜿門セ +// +//--------------------------------------------------------------------------- +BUS::phase_t FASTCALL BUS::GetPhase() +{ + DWORD mci; + + ASSERT(this); + + // 繧サ繝ャ繧ッ繧キ繝ァ繝ウ繝輔ぉ繝シ繧コ + if (GetSEL()) { + return selection; + } + + // 繝舌せ繝輔Μ繝シ繝輔ぉ繝シ繧コ + if (!GetBSY()) { + return busfree; + } + + // 繝舌せ縺ョ菫。蜿キ邱壹°繧峨ち繝シ繧イ繝繝医ョ繝輔ぉ繝シ繧コ繧貞叙蠕 + mci = GetMSG() ? 0x04 : 0x00; + mci |= GetCD() ? 0x02 : 0x00; + mci |= GetIO() ? 0x01 : 0x00; + return GetPhase(mci); +} + +//--------------------------------------------------------------------------- +// +// 繝輔ぉ繝シ繧コ繝繝シ繝悶Ν +// +//--------------------------------------------------------------------------- +const BUS::phase_t BUS::phase_table[8] = { + dataout, + datain, + command, + status, + reserved, + reserved, + msgout, + msgin +}; diff --git a/src/raspberrypi/scsi.h b/src/raspberrypi/scsi.h new file mode 100644 index 00000000..5bed1f73 --- /dev/null +++ b/src/raspberrypi/scsi.h @@ -0,0 +1,128 @@ +//--------------------------------------------------------------------------- +// +// X68000 EMULATOR "XM6" +// +// Copyright (C) 2001-2006 シーシゥシ(ytanaka@ipc-tokai.or.jp) +// Copyright (C) 2014-2018 GIMONS +// +// [ SCSI蜈ア騾 ] +// +//--------------------------------------------------------------------------- + +#if !defined(scsi_h) +#define scsi_h + +//=========================================================================== +// +// SASI/SCSI 繝舌せ +// +//=========================================================================== +class BUS +{ +public: + // 蜍穂ス懊Δ繝シ繝牙ョ夂セゥ + enum mode_e { + TARGET = 0, + INITIATOR = 1, + MONITOR = 2, + }; + + // 繝輔ぉ繝シ繧コ螳夂セゥ + enum phase_t { + busfree, // 繝舌せ繝輔Μ繝シ繝輔ぉ繝シ繧コ + arbitration, // 繧「繝シ繝薙ヨ繝ャ繝シ繧キ繝ァ繝ウ繝輔ぉ繝シ繧コ + selection, // 繧サ繝ャ繧ッ繧キ繝ァ繝ウ繝輔ぉ繝シ繧コ + reselection, // 繝ェ繧サ繝ャ繧ッ繧キ繝ァ繝ウ繝輔ぉ繝シ繧コ + command, // 繧ウ繝槭Φ繝峨ヵ繧ァ繝シ繧コ + execute, // 螳溯。後ヵ繧ァ繝シ繧コ + datain, // 繝繝シ繧ソ繧、繝ウ + dataout, // 繝繝シ繧ソ繧「繧ヲ繝 + status, // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + msgin, // 繝。繝繧サ繝シ繧ク繝輔ぉ繝シ繧コ + msgout, // 繝。繝繧サ繝シ繧ク繧「繧ヲ繝医ヵ繧ァ繝シ繧コ + reserved // 譛ェ菴ソ逕ィ/繝ェ繧カ繝シ繝 + }; + + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + virtual BOOL FASTCALL Init(mode_e mode) = 0; + // 蛻晄悄蛹 + virtual void FASTCALL Reset() = 0; + // 繝ェ繧サ繝繝 + virtual void FASTCALL Cleanup() = 0; + // 繧ッ繝ェ繝シ繝ウ繧「繝繝 + phase_t FASTCALL GetPhase(); + // 繝輔ぉ繝シ繧コ蜿門セ + + static phase_t FASTCALL GetPhase(DWORD mci) + { + return phase_table[mci]; + } + // 繝輔ぉ繝シ繧コ蜿門セ + + virtual DWORD FASTCALL Aquire() = 0; + // 菫。蜿キ蜿悶j霎シ縺ソ + + virtual BOOL FASTCALL GetBSY() = 0; + // BSY繧キ繧ー繝翫Ν蜿門セ + virtual void FASTCALL SetBSY(BOOL ast) = 0; + // BSY繧キ繧ー繝翫Ν險ュ螳 + + virtual BOOL FASTCALL GetSEL() = 0; + // SEL繧キ繧ー繝翫Ν蜿門セ + virtual void FASTCALL SetSEL(BOOL ast) = 0; + // SEL繧キ繧ー繝翫Ν險ュ螳 + + virtual BOOL FASTCALL GetATN() = 0; + // ATN繧キ繧ー繝翫Ν蜿門セ + virtual void FASTCALL SetATN(BOOL ast) = 0; + // ATN繧キ繧ー繝翫Ν險ュ螳 + + virtual BOOL FASTCALL GetACK() = 0; + // ACK繧キ繧ー繝翫Ν蜿門セ + virtual void FASTCALL SetACK(BOOL ast) = 0; + // ACK繧キ繧ー繝翫Ν險ュ螳 + + virtual BOOL FASTCALL GetRST() = 0; + // RST繧キ繧ー繝翫Ν蜿門セ + virtual void FASTCALL SetRST(BOOL ast) = 0; + // RST繧キ繧ー繝翫Ν險ュ螳 + + virtual BOOL FASTCALL GetMSG() = 0; + // MSG繧キ繧ー繝翫Ν蜿門セ + virtual void FASTCALL SetMSG(BOOL ast) = 0; + // MSG繧キ繧ー繝翫Ν險ュ螳 + + virtual BOOL FASTCALL GetCD() = 0; + // CD繧キ繧ー繝翫Ν蜿門セ + virtual void FASTCALL SetCD(BOOL ast) = 0; + // CD繧キ繧ー繝翫Ν險ュ螳 + + virtual BOOL FASTCALL GetIO() = 0; + // IO繧キ繧ー繝翫Ν蜿門セ + virtual void FASTCALL SetIO(BOOL ast) = 0; + // IO繧キ繧ー繝翫Ν險ュ螳 + + virtual BOOL FASTCALL GetREQ() = 0; + // REQ繧キ繧ー繝翫Ν蜿門セ + virtual void FASTCALL SetREQ(BOOL ast) = 0; + // REQ繧キ繧ー繝翫Ν險ュ螳 + + virtual BYTE FASTCALL GetDAT() = 0; + // 繝繝シ繧ソ繧キ繧ー繝翫Ν蜿門セ + virtual void FASTCALL SetDAT(BYTE dat) = 0; + // 繝繝シ繧ソ繧キ繧ー繝翫Ν險ュ螳 + + virtual int FASTCALL ReceiveHandShake(BYTE *buf, int count) = 0; + // 繝繝シ繧ソ蜿嶺ソ。繝上Φ繝峨す繧ァ繧、繧ッ + virtual int FASTCALL SendHandShake(BYTE *buf, int count) = 0; + // 繝繝シ繧ソ騾∽ソ。繝上Φ繝峨す繧ァ繧、繧ッ + + virtual void FASTCALL SleepNsec(DWORD nsec) = 0; + // 繝翫ヮ遘貞腰菴阪ョ繧ケ繝ェ繝シ繝 + +private: + static const phase_t phase_table[8]; + // 繝輔ぉ繝シ繧コ繝繝シ繝悶Ν +}; + +#endif // scsi_h diff --git a/src/raspberrypi/xm6.h b/src/raspberrypi/xm6.h new file mode 100644 index 00000000..cdd09a2c --- /dev/null +++ b/src/raspberrypi/xm6.h @@ -0,0 +1,49 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technology. +// Copyright (C) 2016-2018 GIMONS +// +// [ 蜈ア騾壼ョ夂セゥ ] +// +//--------------------------------------------------------------------------- + +#if !defined(xm6_h) +#define xm6_h + +//--------------------------------------------------------------------------- +// +// VERSION +// +//--------------------------------------------------------------------------- +#define VERSION 0x0134 + +//--------------------------------------------------------------------------- +// +// RaSCSI +// +//--------------------------------------------------------------------------- +#define RASCSI VERSION + +//--------------------------------------------------------------------------- +// +// ID繝槭け繝ュ +// +//--------------------------------------------------------------------------- +#define MAKEID(a, b, c, d) ((DWORD)((a<<24) | (b<<16) | (c<<8) | d)) + +//--------------------------------------------------------------------------- +// +// 繧ッ繝ゥ繧ケ螳」險 +// +//--------------------------------------------------------------------------- +class Fileio; + // 繝輔ぃ繧、繝ォ蜈・蜃コ蜉 +class Disk; + // SASI/SCSI繝繧」繧ケ繧ッ +class Filepath; + // 繝輔ぃ繧、繝ォ繝代せ + +#endif // xm6_h diff --git a/src/x68k/RASDRV/BRIDGE.C b/src/x68k/RASDRV/BRIDGE.C new file mode 100644 index 00000000..cf0f9918 --- /dev/null +++ b/src/x68k/RASDRV/BRIDGE.C @@ -0,0 +1,2414 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technorogy. +// Copyright (C) 2016-2017 GIMONS +// [ ホストファイルシステム ブリッジドライバ ] +// +//--------------------------------------------------------------------------- + +#include +#include +#include +#include +#include +#include "bridge.h" + +//--------------------------------------------------------------------------- +// +// 変数宣言 +// +//--------------------------------------------------------------------------- +volatile BYTE *request; // リクエストヘッダアドレス +DWORD command; // コマンド番号 +DWORD unit; // ユニット番号 + +//=========================================================================== +// +/// ファイルシステム(SCSI連携) +// +//=========================================================================== +typedef struct +{ + char DeviceType; + char RMB; + char ANSI_Ver; + char RDF; + char AddLen; + char RESV0; + char RESV1; + char OptFunc; + char VendorID[8]; + char ProductID[16]; + char FirmRev[4]; +} INQUIRY_T; + +int scsiid; // SCSI ID + +//--------------------------------------------------------------------------- +// +// 初期化 +// +//--------------------------------------------------------------------------- +BOOL SCSI_Init(void) +{ + int i; + INQUIRY_T inq; + + // SCSI ID未定 + scsiid = -1; + + for (i = 0; i <= 7; i++) { + if (S_INQUIRY(sizeof(INQUIRY_T) , i, (struct INQUIRY*)&inq) < 0) { + continue; + } + + if (memcmp(&(inq.ProductID), "RASCSI BRIDGE", 13) != 0) { + continue; + } + + // SCSI ID確定 + scsiid = i; + return TRUE; + } + + return FALSE; +} + +//--------------------------------------------------------------------------- +// +// コマンド送信 +// +//--------------------------------------------------------------------------- +int SCSI_SendCmd(BYTE *buf, int len) +{ + int ret; + BYTE cmdbuf[10]; + BYTE sts; + BYTE msg; + BYTE retbuf[4]; + + ret = FS_FATAL_MEDIAOFFLINE; + + cmdbuf[0] = 0x2a; + cmdbuf[1] = 0; + cmdbuf[2] = 2; + cmdbuf[3] = command; + cmdbuf[4] = 0; + cmdbuf[5] = 0; + cmdbuf[6] = (BYTE)(len >> 16); + cmdbuf[7] = (BYTE)(len >> 8); + cmdbuf[8] = (BYTE)len; + cmdbuf[9] = 0; + + // セレクトがタイムアウトする時には再試行 + if (S_SELECT(scsiid) != 0) { + S_RESET(); + if (S_SELECT(scsiid) != 0) { + return ret; + } + } + + if (S_CMDOUT(10, cmdbuf) != 0) { + return ret; + } + + if (S_DATAOUT_P(len, buf) != 0) { + return ret; + } + + if (S_STSIN(&sts) != 0) { + return ret; + } + + if (S_MSGIN(&msg) != 0) { + return ret; + } + + cmdbuf[0] = 0x28; + cmdbuf[1] = 0; + cmdbuf[2] = 2; + cmdbuf[3] = command; + cmdbuf[4] = 0; + cmdbuf[5] = 0; + cmdbuf[6] = 0; + cmdbuf[7] = 0; + cmdbuf[8] = 4; + cmdbuf[9] = 0; + + // セレクトがタイムアウトする時には再試行 + if (S_SELECT(scsiid) != 0) { + S_RESET(); + if (S_SELECT(scsiid) != 0) { + return ret; + } + } + + if (S_CMDOUT(10, cmdbuf) != 0) { + return ret; + } + + if (S_DATAIN_P(4, retbuf) != 0) { + return ret; + } + + if (S_STSIN(&sts) != 0) { + return ret; + } + + if (S_MSGIN(&msg) != 0) { + return ret; + } + + ret = *(int*)retbuf; + return ret; +} + +//--------------------------------------------------------------------------- +// +// コマンド呼び出し +// +//--------------------------------------------------------------------------- +int SCSI_CalCmd(BYTE *buf, int len, BYTE *outbuf, int outlen) +{ + int ret; + BYTE cmdbuf[10]; + BYTE sts; + BYTE msg; + BYTE retbuf[4]; + + ret = FS_FATAL_MEDIAOFFLINE; + + cmdbuf[0] = 0x2a; + cmdbuf[1] = 0; + cmdbuf[2] = 2; + cmdbuf[3] = command; + cmdbuf[4] = 0; + cmdbuf[5] = 0; + cmdbuf[6] = (BYTE)(len >> 16); + cmdbuf[7] = (BYTE)(len >> 8); + cmdbuf[8] = (BYTE)len; + cmdbuf[9] = 0; + + // セレクトがタイムアウトする時には再試行 + if (S_SELECT(scsiid) != 0) { + S_RESET(); + if (S_SELECT(scsiid) != 0) { + return ret; + } + } + + if (S_CMDOUT(10, cmdbuf) != 0) { + return ret; + } + + if (S_DATAOUT_P(len, buf) != 0) { + return ret; + } + + if (S_STSIN(&sts) != 0) { + return ret; + } + + if (S_MSGIN(&msg) != 0) { + return ret; + } + + cmdbuf[0] = 0x28; + cmdbuf[1] = 0; + cmdbuf[2] = 2; + cmdbuf[3] = command; + cmdbuf[4] = 0; + cmdbuf[5] = 0; + cmdbuf[6] = 0; + cmdbuf[7] = 0; + cmdbuf[8] = 4; + cmdbuf[9] = 0; + + // セレクトがタイムアウトする時には再試行 + if (S_SELECT(scsiid) != 0) { + S_RESET(); + if (S_SELECT(scsiid) != 0) { + return ret; + } + } + + if (S_CMDOUT(10, cmdbuf) != 0) { + return ret; + } + + if (S_DATAIN_P(4, retbuf) != 0) { + return ret; + } + + if (S_STSIN(&sts) != 0) { + return ret; + } + + if (S_MSGIN(&msg) != 0) { + return ret; + } + + // エラーなら返却データの受信を止める + ret = *(int*)retbuf; + if (ret < 0) { + return ret; + } + + cmdbuf[0] = 0x28; + cmdbuf[1] = 0; + cmdbuf[2] = 2; + cmdbuf[3] = command; + cmdbuf[4] = 0; + cmdbuf[5] = 0; + cmdbuf[6] = (BYTE)(outlen >> 16); + cmdbuf[7] = (BYTE)(outlen >> 8); + cmdbuf[8] = (BYTE)outlen; + cmdbuf[9] = 1; + + // セレクトがタイムアウトする時には再試行 + if (S_SELECT(scsiid) != 0) { + S_RESET(); + if (S_SELECT(scsiid) != 0) { + return ret; + } + } + + if (S_CMDOUT(10, cmdbuf) != 0) { + return ret; + } + + if (S_DATAIN_P(outlen, outbuf) != 0) { + return ret; + } + + if (S_STSIN(&sts) != 0) { + return ret; + } + + if (S_MSGIN(&msg) != 0) { + return ret; + } + + ret = *(int*)retbuf; + return ret; +} + +//--------------------------------------------------------------------------- +// +// オプションデータ取得 +// +//--------------------------------------------------------------------------- +BOOL SCSI_ReadOpt(BYTE *buf, int len) +{ + BYTE cmdbuf[10]; + BYTE sts; + BYTE msg; + + cmdbuf[0] = 0x28; + cmdbuf[1] = 0; + cmdbuf[2] = 2; + cmdbuf[3] = command; + cmdbuf[4] = 0; + cmdbuf[5] = 0; + cmdbuf[6] = (BYTE)(len >> 16); + cmdbuf[7] = (BYTE)(len >> 8); + cmdbuf[8] = (BYTE)len; + cmdbuf[9] = 2; + + // セレクトがタイムアウトする時には再試行 + if (S_SELECT(scsiid) != 0) { + S_RESET(); + if (S_SELECT(scsiid) != 0) { + return FALSE; + } + } + + if (S_CMDOUT(10, cmdbuf) != 0) { + return FALSE; + } + + if (S_DATAIN_P(len, buf) != 0) { + return FALSE; + } + + if (S_STSIN(&sts) != 0) { + return FALSE; + } + + if (S_MSGIN(&msg) != 0) { + return FALSE; + } + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// オプションデータ書き込み +// +//--------------------------------------------------------------------------- +BOOL SCSI_WriteOpt(BYTE *buf, int len) +{ + BYTE cmdbuf[10]; + BYTE sts; + BYTE msg; + + cmdbuf[0] = 0x2a; + cmdbuf[1] = 0; + cmdbuf[2] = 2; + cmdbuf[3] = command; + cmdbuf[4] = 0; + cmdbuf[5] = 0; + cmdbuf[6] = (BYTE)(len >> 16); + cmdbuf[7] = (BYTE)(len >> 8); + cmdbuf[8] = (BYTE)len; + cmdbuf[9] = 1; + + // セレクトがタイムアウトする時には再試行 + if (S_SELECT(scsiid) != 0) { + S_RESET(); + if (S_SELECT(scsiid) != 0) { + return FALSE; + } + } + + if (S_CMDOUT(10, cmdbuf) != 0) { + return FALSE; + } + + if (S_DATAOUT_P(len, buf) != 0) { + return FALSE; + } + + if (S_STSIN(&sts) != 0) { + return FALSE; + } + + if (S_MSGIN(&msg) != 0) { + return FALSE; + } + + return TRUE; +} + +//=========================================================================== +// +/// ファイルシステム +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// $40 - デバイス起動 +// +//--------------------------------------------------------------------------- +DWORD FS_InitDevice(const argument_t* pArgument) +{ + return (DWORD)SCSI_SendCmd((BYTE*)pArgument, sizeof(argument_t)); +} + +//--------------------------------------------------------------------------- +// +// $41 - ディレクトリチェック +// +//--------------------------------------------------------------------------- +int FS_CheckDir(const namests_t* pNamests) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = unit; + i += sizeof(DWORD); + + memcpy(&buf[i], pNamests, sizeof(namests_t)); + i += sizeof(namests_t); + + return SCSI_SendCmd(buf, i); +} + +//--------------------------------------------------------------------------- +// +// $42 - ディレクトリ作成 +// +//--------------------------------------------------------------------------- +int FS_MakeDir(const namests_t* pNamests) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = unit; + i += sizeof(DWORD); + + memcpy(&buf[i], pNamests, sizeof(namests_t)); + i += sizeof(namests_t); + + return SCSI_SendCmd(buf, i); +} + +//--------------------------------------------------------------------------- +// +// $43 - ディレクトリ削除 +// +//--------------------------------------------------------------------------- +int FS_RemoveDir(const namests_t* pNamests) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = unit; + i += sizeof(DWORD); + + memcpy(&buf[i], pNamests, sizeof(namests_t)); + i += sizeof(namests_t); + + return SCSI_SendCmd(buf, i); +} + +//--------------------------------------------------------------------------- +// +// $44 - ファイル名変更 +// +//--------------------------------------------------------------------------- +int FS_Rename(const namests_t* pNamests, const namests_t* pNamestsNew) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = unit; + i += sizeof(DWORD); + + memcpy(&buf[i], pNamests, sizeof(namests_t)); + i += sizeof(namests_t); + + memcpy(&buf[i], pNamestsNew, sizeof(namests_t)); + i += sizeof(namests_t); + + return SCSI_SendCmd(buf, i); +} + +//--------------------------------------------------------------------------- +// +// $45 - ファイル削除 +// +//--------------------------------------------------------------------------- +int FS_Delete(const namests_t* pNamests) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = unit; + i += sizeof(DWORD); + + memcpy(&buf[i], pNamests, sizeof(namests_t)); + i += sizeof(namests_t); + + return SCSI_SendCmd(buf, i); +} + +//--------------------------------------------------------------------------- +// +// $46 - ファイル属性取得/設定 +// +//--------------------------------------------------------------------------- +int FS_Attribute(const namests_t* pNamests, DWORD nHumanAttribute) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = unit; + i += sizeof(DWORD); + + memcpy(&buf[i], pNamests, sizeof(namests_t)); + i += sizeof(namests_t); + + dp = (DWORD*)&buf[i]; + *dp = nHumanAttribute; + i += sizeof(DWORD); + + return SCSI_SendCmd(buf, i); +} + +//--------------------------------------------------------------------------- +// +// $47 - ファイル検索 +// +//--------------------------------------------------------------------------- +int FS_Files(DWORD nKey, + const namests_t* pNamests, files_t* info) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = unit; + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + *dp = nKey; + i += sizeof(DWORD); + + memcpy(&buf[i], pNamests, sizeof(namests_t)); + i += sizeof(namests_t); + + memcpy(&buf[i], info, sizeof(files_t)); + i += sizeof(files_t); + + return SCSI_CalCmd(buf, i, (BYTE*)info, sizeof(files_t)); +} + +//--------------------------------------------------------------------------- +// +// $48 - ファイル次検索 +// +//--------------------------------------------------------------------------- +int FS_NFiles(DWORD nKey, files_t* info) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = unit; + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + *dp = nKey; + i += sizeof(DWORD); + + memcpy(&buf[i], info, sizeof(files_t)); + i += sizeof(files_t); + + return SCSI_CalCmd(buf, i, (BYTE*)info, sizeof(files_t)); +} + +//--------------------------------------------------------------------------- +// +// $49 - ファイル作成 +// +//--------------------------------------------------------------------------- +int FS_Create(DWORD nKey, + const namests_t* pNamests, fcb_t* pFcb, DWORD nAttribute, BOOL bForce) +{ + BYTE buf[256]; + DWORD *dp; + BOOL *bp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = unit; + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + *dp = nKey; + i += sizeof(DWORD); + + memcpy(&buf[i], pNamests, sizeof(namests_t)); + i += sizeof(namests_t); + + memcpy(&buf[i], pFcb, sizeof(fcb_t)); + i += sizeof(fcb_t); + + dp = (DWORD*)&buf[i]; + *dp = nAttribute; + i += sizeof(DWORD); + + bp = (BOOL*)&buf[i]; + *bp = bForce; + i += sizeof(BOOL); + + return SCSI_CalCmd(buf, i, (BYTE*)pFcb, sizeof(fcb_t)); +} + +//--------------------------------------------------------------------------- +// +// $4A - ファイルオープン +// +//--------------------------------------------------------------------------- +int FS_Open(DWORD nKey, + const namests_t* pNamests, fcb_t* pFcb) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = unit; + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + *dp = nKey; + i += sizeof(DWORD); + + memcpy(&buf[i], pNamests, sizeof(namests_t)); + i += sizeof(namests_t); + + memcpy(&buf[i], pFcb, sizeof(fcb_t)); + i += sizeof(fcb_t); + + return SCSI_CalCmd(buf, i, (BYTE*)pFcb, sizeof(fcb_t)); +} + +//--------------------------------------------------------------------------- +// +// $4B - ファイルクローズ +// +//--------------------------------------------------------------------------- +int FS_Close(DWORD nKey, fcb_t* pFcb) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = unit; + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + *dp = nKey; + i += sizeof(DWORD); + + memcpy(&buf[i], pFcb, sizeof(fcb_t)); + i += sizeof(fcb_t); + + return SCSI_CalCmd(buf, i, (BYTE*)pFcb, sizeof(fcb_t)); +} + +//--------------------------------------------------------------------------- +// +// $4C - ファイル読み込み +// +//--------------------------------------------------------------------------- +int FS_Read(DWORD nKey, fcb_t* pFcb, BYTE* pAddress, DWORD nSize) +{ + BYTE buf[256]; + DWORD *dp; + int i; + int nResult; + + i = 0; + dp = (DWORD*)buf; + *dp = nKey; + i += sizeof(DWORD); + + memcpy(&buf[i], pFcb, sizeof(fcb_t)); + i += sizeof(fcb_t); + + dp = (DWORD*)&buf[i]; + *dp = nSize; + i += sizeof(DWORD); + + nResult = SCSI_CalCmd(buf, i, (BYTE*)pFcb, sizeof(fcb_t)); + + if (nResult > 0) { + SCSI_ReadOpt(pAddress, nResult); + } + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $4D - ファイル書き込み +// +//--------------------------------------------------------------------------- +int FS_Write(DWORD nKey, fcb_t* pFcb, BYTE* pAddress, DWORD nSize) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = nKey; + i += sizeof(DWORD); + + memcpy(&buf[i], pFcb, sizeof(fcb_t)); + i += sizeof(fcb_t); + + dp = (DWORD*)&buf[i]; + *dp = nSize; + i += sizeof(DWORD); + + if (nSize != 0) { + if (!SCSI_WriteOpt(pAddress, nSize)) { + return FS_FATAL_MEDIAOFFLINE; + } + } + + return SCSI_SendCmd(buf, i); +} + +//--------------------------------------------------------------------------- +// +// $4E - ファイルシーク +// +//--------------------------------------------------------------------------- +int FS_Seek(DWORD nKey, fcb_t* pFcb, DWORD nMode, int nOffset) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = nKey; + i += sizeof(DWORD); + + memcpy(&buf[i], pFcb, sizeof(fcb_t)); + i += sizeof(fcb_t); + + dp = (DWORD*)&buf[i]; + *dp = nMode; + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + *dp = nOffset; + i += sizeof(int); + + return SCSI_CalCmd(buf, i, (BYTE*)pFcb, sizeof(fcb_t)); +} + +//--------------------------------------------------------------------------- +// +// $4F - ファイル時刻取得/設定 +// +//--------------------------------------------------------------------------- +DWORD FS_TimeStamp(DWORD nKey, + fcb_t* pFcb, DWORD nHumanTime) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = unit; + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + *dp = nKey; + i += sizeof(DWORD); + + memcpy(&buf[i], pFcb, sizeof(fcb_t)); + i += sizeof(fcb_t); + + dp = (DWORD*)&buf[i]; + *dp = nHumanTime; + i += sizeof(DWORD); + + return (DWORD)SCSI_CalCmd(buf, i, (BYTE*)pFcb, sizeof(fcb_t)); +} + +//--------------------------------------------------------------------------- +// +// $50 - 容量取得 +// +//--------------------------------------------------------------------------- +int FS_GetCapacity(capacity_t* cap) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = unit; + i += sizeof(DWORD); + + return SCSI_CalCmd(buf, i, (BYTE*)cap, sizeof(capacity_t)); +} + +//--------------------------------------------------------------------------- +// +// $51 - ドライブ状態検査/制御 +// +//--------------------------------------------------------------------------- +int FS_CtrlDrive(ctrldrive_t* pCtrlDrive) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = unit; + i += sizeof(DWORD); + + memcpy(&buf[i], pCtrlDrive, sizeof(ctrldrive_t)); + i += sizeof(ctrldrive_t); + + return SCSI_CalCmd(buf, i, (BYTE*)pCtrlDrive, sizeof(ctrldrive_t)); +} + +//--------------------------------------------------------------------------- +// +// $52 - DPB取得 +// +//--------------------------------------------------------------------------- +int FS_GetDPB(dpb_t* pDpb) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = unit; + i += sizeof(DWORD); + + return SCSI_CalCmd(buf, i, (BYTE*)pDpb, sizeof(dpb_t)); +} + +//--------------------------------------------------------------------------- +// +// $53 - セクタ読み込み +// +//--------------------------------------------------------------------------- +int FS_DiskRead(BYTE* pBuffer, DWORD nSector, DWORD nSize) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = unit; + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + *dp = nSector; + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + *dp = nSize; + i += sizeof(DWORD); + + return SCSI_CalCmd(buf, i, (BYTE*)pBuffer, 0x200); +} + +//--------------------------------------------------------------------------- +// +// $54 - セクタ書き込み +// +//--------------------------------------------------------------------------- +int FS_DiskWrite() +{ + BYTE buf[256]; + DWORD *dp; + + dp = (DWORD*)buf; + *dp = unit; + + return SCSI_SendCmd(buf, 4); +} + +//--------------------------------------------------------------------------- +// +// $55 - IOCTRL +// +//--------------------------------------------------------------------------- +int FS_Ioctrl(DWORD nFunction, ioctrl_t* pIoctrl) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = unit; + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + *dp = nFunction; + i += sizeof(DWORD); + + memcpy(&buf[i], pIoctrl, sizeof(ioctrl_t)); + i += sizeof(ioctrl_t); + + return SCSI_CalCmd(buf, i, (BYTE*)pIoctrl, sizeof(ioctrl_t)); +} + +//--------------------------------------------------------------------------- +// +// $56 - フラッシュ +// +//--------------------------------------------------------------------------- +int FS_Flush() +{ + BYTE buf[256]; + DWORD *dp; + + dp = (DWORD*)buf; + *dp = unit; + + return SCSI_SendCmd(buf, 4); +} + +//--------------------------------------------------------------------------- +// +// $57 - メディア交換チェック +// +//--------------------------------------------------------------------------- +int FS_CheckMedia() +{ + BYTE buf[256]; + DWORD *dp; + + dp = (DWORD*)buf; + *dp = unit; + + return SCSI_SendCmd(buf, 4); +} + +//--------------------------------------------------------------------------- +// +// $58 - 排他制御 +// +//--------------------------------------------------------------------------- +int FS_Lock() +{ + BYTE buf[256]; + DWORD *dp; + + dp = (DWORD*)buf; + *dp = unit; + + return SCSI_SendCmd(buf, 4); +} + +//=========================================================================== +// +// コマンドハンドラ +// +//=========================================================================== +#define GetReqByte(a) (request[a]) +#define SetReqByte(a,d) (request[a] = (d)) +#define GetReqWord(a) (*((WORD*)&request[a])) +#define SetReqWord(a,d) (*((WORD*)&request[a]) = (d)) +#define GetReqLong(a) (*((DWORD*)&request[a])) +#define SetReqLong(a,d) (*((DWORD*)&request[a]) = (d)) +#define GetReqAddr(a) ((BYTE*)((*((DWORD*)&request[a])) & 0x00ffffff)) + +//--------------------------------------------------------------------------- +// +// NAMESTS読み込み +// +//--------------------------------------------------------------------------- +void GetNameStsPath(BYTE *addr, namests_t* pNamests) +{ + DWORD i; + + ASSERT(this); + ASSERT(pNamests); + + // ワイルドカード情報 + pNamests->wildcard = *addr; + + // ドライブ番号 + pNamests->drive = addr[1]; + + // パス名 + for (i = 0; i < sizeof(pNamests->path); i++) { + pNamests->path[i] = addr[2 + i]; + } + + // ファイル名1 + memset(pNamests->name, 0x20, sizeof(pNamests->name)); + + // 拡張子 + memset(pNamests->ext, 0x20, sizeof(pNamests->ext)); + + // ファイル名2 + memset(pNamests->add, 0, sizeof(pNamests->add)); +} + +//--------------------------------------------------------------------------- +// +// NAMESTS読み込み +// +//--------------------------------------------------------------------------- +void GetNameSts(BYTE *addr, namests_t* pNamests) +{ + DWORD i; + + ASSERT(this); + ASSERT(pNamests); + ASSERT(addr <= 0xFFFFFF); + + // ワイルドカード情報 + pNamests->wildcard = *addr; + + // ドライブ番号 + pNamests->drive = addr[1]; + + // パス名 + for (i = 0; i < sizeof(pNamests->path); i++) { + pNamests->path[i] = addr[2 + i]; + } + + // ファイル名1 + for (i = 0; i < sizeof(pNamests->name); i++) { + pNamests->name[i] = addr[67 + i]; + } + + // 拡張子 + for (i = 0; i < sizeof(pNamests->ext); i++) { + pNamests->ext[i] = addr[75 + i]; + } + + // ファイル名2 + for (i = 0; i < sizeof(pNamests->add); i++) { + pNamests->add[i] = addr[78 + i]; + } +} + +//--------------------------------------------------------------------------- +// +// FILES読み込み +// +//--------------------------------------------------------------------------- +void GetFiles(BYTE *addr, files_t* pFiles) +{ + ASSERT(this); + ASSERT(pFiles); + ASSERT(addr <= 0xFFFFFF); + + // 検索情報 + pFiles->fatr = *addr; + pFiles->sector = *((DWORD*)&addr[2]); + pFiles->offset = *((WORD*)&addr[8]);; + + pFiles->attr = 0; + pFiles->time = 0; + pFiles->date = 0; + pFiles->size = 0; + memset(pFiles->full, 0, sizeof(pFiles->full)); +} + +//--------------------------------------------------------------------------- +// +// FILES書き込み +// +//--------------------------------------------------------------------------- +void SetFiles(BYTE *addr, const files_t* pFiles) +{ + DWORD i; + + ASSERT(this); + ASSERT(pFiles); + + *((DWORD*)&addr[2]) = pFiles->sector; + *((WORD*)&addr[8]) = pFiles->offset; + + // ファイル情報 + addr[21] = pFiles->attr; + *((WORD*)&addr[22]) = pFiles->time; + *((WORD*)&addr[24]) = pFiles->date; + *((DWORD*)&addr[26]) = pFiles->size; + + // フルファイル名 + addr += 30; + for (i = 0; i < sizeof(pFiles->full); i++) { + *addr = pFiles->full[i]; + addr++; + } +} + +//--------------------------------------------------------------------------- +// +// FCB読み込み +// +//--------------------------------------------------------------------------- +void GetFcb(BYTE *addr, fcb_t* pFcb) +{ + ASSERT(this); + ASSERT(pFcb); + + // FCB情報 + pFcb->fileptr = *((DWORD*)&addr[6]); + pFcb->mode = *((WORD*)&addr[14]); + + // 属性 + pFcb->attr = addr[47]; + + // FCB情報 + pFcb->time = *((WORD*)&addr[58]); + pFcb->date = *((WORD*)&addr[60]); + pFcb->size = *((DWORD*)&addr[64]); +} + +//--------------------------------------------------------------------------- +// +// FCB書き込み +// +//--------------------------------------------------------------------------- +void SetFcb(BYTE *addr, const fcb_t* pFcb) +{ + ASSERT(this); + ASSERT(pFcb); + + // FCB情報 + *((DWORD*)&addr[6]) = pFcb->fileptr; + *((WORD*)&addr[14]) = pFcb->mode; + + // 属性 + addr[47] = pFcb->attr; + + // FCB情報 + *((WORD*)&addr[58]) = pFcb->time; + *((WORD*)&addr[60]) = pFcb->date; + *((DWORD*)&addr[64]) = pFcb->size; +} + +//--------------------------------------------------------------------------- +// +// CAPACITY書き込み +// +//--------------------------------------------------------------------------- +void SetCapacity(BYTE *addr, const capacity_t* pCapacity) +{ + ASSERT(this); + ASSERT(pCapacity); + + *((WORD*)&addr[0]) = pCapacity->freearea; + *((WORD*)&addr[2]) = pCapacity->clusters; + *((WORD*)&addr[4]) = pCapacity->sectors; + *((WORD*)&addr[6]) = pCapacity->bytes; +} + +//--------------------------------------------------------------------------- +// +// DPB書き込み +// +//--------------------------------------------------------------------------- +void SetDpb(BYTE *addr, const dpb_t* pDpb) +{ + ASSERT(this); + ASSERT(pDpb); + + // DPB情報 + *((WORD*)&addr[0]) = pDpb->sector_size; + addr[2] = pDpb->cluster_size; + addr[3] = pDpb->shift; + *((WORD*)&addr[4]) = pDpb->fat_sector; + addr[6] = pDpb->fat_max; + addr[7] = pDpb->fat_size; + *((WORD*)&addr[8]) = pDpb->file_max; + *((WORD*)&addr[10]) = pDpb->data_sector; + *((WORD*)&addr[12]) = pDpb->cluster_max; + *((WORD*)&addr[14]) = pDpb->root_sector; + addr[20] = pDpb->media; +} + +//--------------------------------------------------------------------------- +// +// IOCTRL読み込み +// +//--------------------------------------------------------------------------- +void GetIoctrl(DWORD param, DWORD func, ioctrl_t* pIoctrl) +{ + DWORD *lp; + + ASSERT(this); + ASSERT(pIoctrl); + + switch (func) { + case 2: + // メディア再認識 + pIoctrl->param = param; + return; + + case -2: + // オプション設定 + lp = (DWORD*)param; + pIoctrl->param = *lp; + return; + } +} + +//--------------------------------------------------------------------------- +// +// IOCTRL書き込み +// +//--------------------------------------------------------------------------- +void SetIoctrl(DWORD param, DWORD func, ioctrl_t* pIoctrl) +{ + DWORD i; + BYTE *bp; + WORD *wp; + DWORD *lp; + + ASSERT(this); + ASSERT(pIoctrl); + + switch (func) { + case 0: + // メディアIDの獲得 + wp = (WORD*)param; + *wp = pIoctrl->media; + return; + + case 1: + // Human68k互換のためのダミー + lp = (DWORD*)param; + *lp = pIoctrl->param; + return; + + case -1: + // 常駐判定 + bp = (BYTE*)param; + for (i = 0; i < 8; i++) { + *bp = pIoctrl->buffer[i]; + bp++; + } + return; + + case -3: + // オプション獲得 + lp = (DWORD*)param; + *lp = pIoctrl->param; + return; + } +} + +//--------------------------------------------------------------------------- +// +// ARGUMENT読み込み +// +// バッファサイズよりも長い場合は転送を打ち切って必ず終端する。 +// +//--------------------------------------------------------------------------- +void GetArgument(BYTE *addr, argument_t* pArgument) +{ + BOOL bMode; + BYTE *p; + DWORD i; + BYTE c; + + ASSERT(this); + ASSERT(pArgument); + + bMode = FALSE; + p = pArgument->buf; + for (i = 0; i < sizeof(pArgument->buf) - 2; i++) { + c = addr[i]; + *p++ = c; + if (bMode == 0) { + if (c == '\0') + return; + bMode = TRUE; + } else { + if (c == '\0') + bMode = FALSE; + } + } + + *p++ = '\0'; + *p = '\0'; +} + +//--------------------------------------------------------------------------- +// +// 終了値書き込み +// +//--------------------------------------------------------------------------- +void SetResult(DWORD nResult) +{ + DWORD code; + + ASSERT(this); + + // 致命的エラー判定 + switch (nResult) { + case FS_FATAL_INVALIDUNIT: + code = 0x5001; + goto fatal; + case FS_FATAL_INVALIDCOMMAND: + code = 0x5003; + goto fatal; + case FS_FATAL_WRITEPROTECT: + code = 0x700D; + goto fatal; + case FS_FATAL_MEDIAOFFLINE: + code = 0x7002; + fatal: + SetReqByte(3, (BYTE)code); + SetReqByte(4, code >> 8); + // @note リトライ可能を返すときは、(a5 + 18)を書き換えてはいけない。 + // その後白帯で Retry を選択した場合、書き換えた値を読み込んで誤動作してしまう。 + if (code & 0x2000) + break; + nResult = FS_INVALIDFUNC; + default: + SetReqLong(18, nResult); + break; + } +} + +//--------------------------------------------------------------------------- +// +// $40 - デバイス起動 +// +// in (offset size) +// 0 1.b 定数(22) +// 2 1.b コマンド($40/$c0) +// 18 1.l パラメータアドレス +// 22 1.b ドライブ番号 +// out (offset size) +// 3 1.b エラーコード(下位) +// 4 1.b 〃 (上位) +// 13 1.b ユニット数 +// 14 1.l デバイスドライバの終了アドレス + 1 +// +// ローカルドライブのコマンド 0 と同様に組み込み時に呼ばれるが、BPB 及 +// びそのポインタの配列を用意する必要はない. +// 他のコマンドと違い、このコマンドだけa5 + 1には有効な値が入っていない +// (0初期化なども期待してはいけない)ので注意すること。 +// +//--------------------------------------------------------------------------- +DWORD InitDevice(void) +{ + argument_t arg; + DWORD units; + + ASSERT(this); + ASSERT(fs); + + // オプション内容を獲得 + GetArgument(GetReqAddr(18), &arg); + + // Human68k側で利用可能なドライブ数の範囲で、ファイルシステムを構築 + units = FS_InitDevice(&arg); + + // ドライブ数を返信 + SetReqByte(13, units); + + return 0; +} + +//--------------------------------------------------------------------------- +// +// $41 - ディレクトリチェック +// +// in (offset size) +// 14 1.L NAMESTS構造体アドレス +// +//--------------------------------------------------------------------------- +DWORD CheckDir(void) +{ + namests_t ns; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // 検索対象ファイル名獲得 + GetNameStsPath(GetReqAddr(14), &ns); + + // ファイルシステム呼び出し + nResult = FS_CheckDir(&ns); + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $42 - ディレクトリ作成 +// +// in (offset size) +// 14 1.L NAMESTS構造体アドレス +// +//--------------------------------------------------------------------------- +DWORD MakeDir(void) +{ + namests_t ns; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // 検索対象ファイル名獲得 + GetNameSts(GetReqAddr(14), &ns); + + // ファイルシステム呼び出し + nResult = FS_MakeDir(&ns); + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $43 - ディレクトリ削除 +// +// in (offset size) +// 14 1.L NAMESTS構造体アドレス +// +//--------------------------------------------------------------------------- +DWORD RemoveDir(void) +{ + namests_t ns; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // 検索対象ファイル名獲得 + GetNameSts(GetReqAddr(14), &ns); + + // ファイルシステム呼び出し + nResult = FS_RemoveDir(&ns); + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $44 - ファイル名変更 +// +// in (offset size) +// 14 1.L NAMESTS構造体アドレス 旧ファイル名 +// 18 1.L NAMESTS構造体アドレス 新ファイル名 +// +//--------------------------------------------------------------------------- +DWORD Rename(void) +{ + namests_t ns; + namests_t ns_new; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // 検索対象ファイル名獲得 + GetNameSts(GetReqAddr(14), &ns); + GetNameSts(GetReqAddr(18), &ns_new); + + // ファイルシステム呼び出し + nResult = FS_Rename(&ns, &ns_new); + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $45 - ファイル削除 +// +// in (offset size) +// 14 1.L NAMESTS構造体アドレス +// +//--------------------------------------------------------------------------- +DWORD Delete(void) +{ + namests_t ns; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // 検索対象ファイル名獲得 + GetNameSts(GetReqAddr(14), &ns); + + // ファイルシステム呼び出し + nResult = FS_Delete(&ns); + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $46 - ファイル属性取得/設定 +// +// in (offset size) +// 12 1.B 読み出し時に0x01になるので注意 +// 13 1.B 属性 $FFだと読み出し +// 14 1.L NAMESTS構造体アドレス +// +//--------------------------------------------------------------------------- +DWORD Attribute(void) +{ + namests_t ns; + DWORD attr; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // 検索対象ファイル名獲得 + GetNameSts(GetReqAddr(14), &ns); + + // 対象属性 + attr = GetReqByte(13); + + // ファイルシステム呼び出し + nResult = FS_Attribute(&ns, attr); + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $47 - ファイル検索 +// +// in (offset size) +// 0 1.b 定数(26) +// 1 1.b ユニット番号 +// 2 1.b コマンド($47/$c7) +// 13 1.b 検索属性 (WindrvXMでは未使用。検索バッファに値が書かれている) +// 14 1.l ファイル名バッファ(namests 形式) +// 18 1.l 検索バッファ(files 形式) このバッファに検索途中情報と検索結果を書き込む +// out (offset size) +// 3 1.b エラーコード(下位) +// 4 1.b 〃 (上位) +// 18 1.l リザルトステータス +// +// ディレクトリから指定ファイルを検索する. DOS _FILES から呼び出される. +// 検索に失敗した場合、若しくは検索に成功してもワイルドカードが使われて +// いない場合は、次回検索時に必ず失敗させる為に検索バッファのオフセットに +// -1 を書き込む. 検索が成功した場合は見つかったファイルの情報を設定する +// と共に、次検索用の情報のセクタ番号、オフセット、ルートディレクトリの場 +// 合は更に残りセクタ数を設定する. 検索ドライブ・属性、パス名は DOS コー +// ル処理内で設定されるので書き込む必要はない. +// +// +// (offset size) +// 0 1.b NAMWLD 0:ワイルドカードなし -1:ファイル指定なし +// (ワイルドカードの文字数) +// 1 1.b NAMDRV ドライブ番号(A=0,B=1,…,Z=25) +// 2 65.b NAMPTH パス('\'+あればサブディレクトリ名+'\') +// 67 8.b NAMNM1 ファイル名(先頭 8 文字) +// 75 3.b NAMEXT 拡張子 +// 78 10.b NAMNM2 ファイル名(残りの 10 文字) +// +// パス区切り文字は0x2F(/)や0x5C(\)ではなく0x09(TAB)を使っているので注意。 +// +//--------------------------------------------------------------------------- +DWORD Files(void) +{ + BYTE *files; + files_t info; + namests_t ns; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // 検索途中経過格納領域 + files = GetReqAddr(18); + GetFiles(files, &info); + + // 検索対象ファイル名獲得 + GetNameSts(GetReqAddr(14), &ns); + + // ファイルシステム呼び出し + nResult = FS_Files((DWORD)files, &ns, &info); + + // 検索結果の反映 + if (nResult >= 0) { + SetFiles(files, &info); + } + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $48 - ファイル次検索 +// +// in (offset size) +// 18 1.L FILES構造体アドレス +// +//--------------------------------------------------------------------------- +DWORD NFiles(void) +{ + BYTE *files; + files_t info; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // ワーク領域の読み込み + files = GetReqAddr(18); + GetFiles(files, &info); + + // ファイルシステム呼び出し + nResult = FS_NFiles((DWORD)files, &info); + + // 検索結果の反映 + if (nResult >= 0) { + SetFiles(files, &info); + } + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $49 - ファイル作成(Create) +// +// in (offset size) +// 1 1.B ユニット番号 +// 13 1.B 属性 +// 14 1.L NAMESTS構造体アドレス +// 18 1.L モード (0:_NEWFILE 1:_CREATE) +// 22 1.L FCB構造体アドレス +// +//--------------------------------------------------------------------------- +DWORD Create(void) +{ + namests_t ns; + BYTE *pFcb; + fcb_t fcb; + DWORD attr; + BOOL force; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // 対象ファイル名獲得 + GetNameSts(GetReqAddr(14), &ns); + + // FCB獲得 + pFcb = GetReqAddr(22); + GetFcb(pFcb, &fcb); + + // 属性 + attr = GetReqByte(13); + + // 強制上書きモード + force = (BOOL)GetReqLong(18); + + // ファイルシステム呼び出し + nResult = FS_Create((DWORD)pFcb, &ns, &fcb, attr, force); + + // 結果の反映 + if (nResult >= 0) { + SetFcb(pFcb, &fcb); + } + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $4A - ファイルオープン +// +// in (offset size) +// 1 1.B ユニット番号 +// 14 1.L NAMESTS構造体アドレス +// 22 1.L FCB構造体アドレス +// 既にFCBにはほとんどのパラメータが設定済み +// 時刻・日付はオープンした瞬間のものになってるので上書き +// サイズは0になっているので上書き +// +//--------------------------------------------------------------------------- +DWORD Open(void) +{ + namests_t ns; + BYTE *pFcb; + fcb_t fcb; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // 対象ファイル名獲得 + GetNameSts(GetReqAddr(14), &ns); + + // FCB獲得 + pFcb = GetReqAddr(22); + GetFcb(pFcb, &fcb); + + // ファイルシステム呼び出し + nResult = FS_Open((DWORD)pFcb, &ns, &fcb); + + // 結果の反映 + if (nResult >= 0) { + SetFcb(pFcb, &fcb); + } + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $4B - ファイルクローズ +// +// in (offset size) +// 22 1.L FCB構造体アドレス +// +//--------------------------------------------------------------------------- +DWORD Close(void) +{ + BYTE *pFcb; + fcb_t fcb; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // FCB獲得 + pFcb = GetReqAddr(22); + GetFcb(pFcb, &fcb); + + // ファイルシステム呼び出し + nResult = FS_Close((DWORD)pFcb, &fcb); + + // 結果の反映 + if (nResult >= 0) { + SetFcb(pFcb, &fcb); + } + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $4C - ファイル読み込み +// +// in (offset size) +// 14 1.L 読み込みバッファ ここにファイル内容を読み込む +// 18 1.L サイズ 16MBを超える値が指定される可能性もあり +// 22 1.L FCB構造体アドレス +// +// バスエラーが発生するアドレスを指定した場合の動作は保証しない。 +// +// 20世紀のアプリは「負の数だとファイルを全部読む」という作法で書かれている +// 可能性が微レ存。あれれー?このファイル16MB超えてるよー?(CV.高山みなみ) +// +// むしろ4〜12MBくらいの当時のプログラマーから見た実質的な「∞」の値で +// クリップするような配慮こそが現代では必要なのではなかろうか。 +// または、末尾が12MBと16MB位置を超えたらサイズをクリップすると良いかも。 +// +//--------------------------------------------------------------------------- +DWORD Read(void) +{ + BYTE *pFcb; + fcb_t fcb; + BYTE *pAddress; + DWORD nSize; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // FCB獲得 + pFcb = GetReqAddr(22); + GetFcb(pFcb, &fcb); + + // 読み込みバッファ + pAddress = GetReqAddr(14); + + // 読み込みサイズ + nSize = GetReqLong(18); + + // クリッピング + if (nSize >= WINDRV_CLIPSIZE_MAX) { + nSize = WINDRV_CLIPSIZE_MAX; + } + + // ファイルシステム呼び出し + nResult = FS_Read((DWORD)pFcb, &fcb, pAddress, nSize); + + // 結果の反映 + if (nResult >= 0) { + SetFcb(pFcb, &fcb); + } + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $4D - ファイル書き込み +// +// in (offset size) +// 14 1.L 書き込みバッファ ここにファイル内容を書き込む +// 18 1.L サイズ 負の数ならファイルサイズを指定したのと同じ +// 22 1.L FCB構造体アドレス +// +// バスエラーが発生するアドレスを指定した場合の動作は保証しない。 +// +//--------------------------------------------------------------------------- +DWORD Write(void) +{ + BYTE *pFcb; + fcb_t fcb; + BYTE *pAddress; + DWORD nSize; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // FCB獲得 + pFcb = GetReqAddr(22); + GetFcb(pFcb, &fcb); + + // 書き込みバッファ + pAddress = GetReqAddr(14); + + // 書き込みサイズ + nSize = GetReqLong(18); + + // クリッピング + if (nSize >= WINDRV_CLIPSIZE_MAX) { + nSize = WINDRV_CLIPSIZE_MAX; + } + + // ファイルシステム呼び出し + nResult = FS_Write((DWORD)pFcb, &fcb, pAddress, nSize); + + // 結果の反映 + if (nResult >= 0) { + SetFcb(pFcb, &fcb); + } + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $4E - ファイルシーク +// +// in (offset size) +// 12 1.B 0x2B になってるときがある 0のときもある +// 13 1.B モード +// 18 1.L オフセット +// 22 1.L FCB構造体アドレス +// +//--------------------------------------------------------------------------- +DWORD Seek(void) +{ + BYTE *pFcb; + fcb_t fcb; + DWORD nMode; + DWORD nOffset; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // FCB獲得 + pFcb = GetReqAddr(22); + GetFcb(pFcb, &fcb); + + // シークモード + nMode = GetReqByte(13); + + // シークオフセット + nOffset = GetReqLong(18); + + // ファイルシステム呼び出し + nResult = FS_Seek((DWORD)pFcb, &fcb, nMode, nOffset); + + // 結果の反映 + if (nResult >= 0) { + SetFcb(pFcb, &fcb); + } + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $4F - ファイル時刻取得/設定 +// +// in (offset size) +// 18 1.W DATE +// 20 1.W TIME +// 22 1.L FCB構造体アドレス +// +// FCBが読み込みモードで開かれた状態でも設定変更が可能。 +// FCBだけでは書き込み禁止の判定ができないので注意。 +// +//--------------------------------------------------------------------------- +DWORD TimeStamp(void) +{ + BYTE *pFcb; + fcb_t fcb; + DWORD nTime; + DWORD nResult; + + ASSERT(this); + ASSERT(fs); + + // FCB獲得 + pFcb = GetReqAddr(22); + GetFcb(pFcb, &fcb); + + // 時刻獲得 + nTime = GetReqLong(18); + + // ファイルシステム呼び出し + nResult = FS_TimeStamp((DWORD)pFcb, &fcb, nTime); + + // 結果の反映 + if (nResult < 0xFFFF0000) { + SetFcb(pFcb, &fcb); + } + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $50 - 容量取得 +// +// in (offset size) +// 0 1.b 定数(26) +// 1 1.b ユニット番号 +// 2 1.b コマンド($50/$d0) +// 14 1.l バッファアドレス +// out (offset size) +// 3 1.b エラーコード(下位) +// 4 1.b 〃 (上位) +// 18 1.l リザルトステータス +// +// メディアの総容量/空き容量、クラスタ/セクタサイズを収得する. バッファ +// に書き込む内容は以下の通り. リザルトステータスとして使用可能なバイト数 +// を返すこと. +// +// (offset size) +// 0 1.w 使用可能なクラスタ数 +// 2 1.w 総クラスタ数 +// 4 1.w 1 クラスタ当りのセクタ数 +// 6 1.w 1 セクタ当りのバイト数 +// +//--------------------------------------------------------------------------- +DWORD GetCapacity(void) +{ + BYTE *pCapacity; + capacity_t cap; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // バッファ取得 + pCapacity = GetReqAddr(14); + +#if 0 + // ファイルシステム呼び出し + nResult = FS_GetCapacity(&cap); +#else + // いつも同じ内容が返ってくるのでスキップしてみる + cap.freearea = 0xFFFF; + cap.clusters = 0xFFFF; + cap.sectors = 64; + cap.bytes = 512; + nResult = 0x7FFF8000; +#endif + + // 結果の反映 + if (nResult >= 0) { + SetCapacity(pCapacity, &cap); + } + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $51 - ドライブ状態検査/制御 +// +// in (offset size) +// 1 1.B ユニット番号 +// 13 1.B 状態 0: 状態検査 1: イジェクト +// +//--------------------------------------------------------------------------- +DWORD CtrlDrive(void) +{ + ctrldrive_t ctrl; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // ドライブ状態取得 + ctrl.status = GetReqByte(13); + + // ファイルシステム呼び出し + nResult = FS_CtrlDrive(&ctrl); + + // 結果の反映 + if (nResult >= 0) { + SetReqByte(13, ctrl.status); + } + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $52 - DPB取得 +// +// in (offset size) +// 0 1.b 定数(26) +// 1 1.b ユニット番号 +// 2 1.b コマンド($52/$d2) +// 14 1.l バッファアドレス(先頭アドレス + 2 を指す) +// out (offset size) +// 3 1.b エラーコード(下位) +// 4 1.b 〃 (上位) +// 18 1.l リザルトステータス +// +// 指定メディアの情報を v1 形式 DPB で返す. このコマンドで設定する必要 +// がある情報は以下の通り(括弧内は DOS コールが設定する). ただし、バッフ +// ァアドレスはオフセット 2 を指したアドレスが渡されるので注意すること. +// +// (offset size) +// 0 1.b (ドライブ番号) +// 1 1.b (ユニット番号) +// 2 1.w 1 セクタ当りのバイト数 +// 4 1.b 1 クラスタ当りのセクタ数 - 1 +// 5 1.b クラスタ→セクタのシフト数 +// bit 7 = 1 で MS-DOS 形式 FAT(16bit Intel 配列) +// 6 1.w FAT の先頭セクタ番号 +// 8 1.b FAT 領域の個数 +// 9 1.b FAT の占めるセクタ数(複写分を除く) +// 10 1.w ルートディレクトリに入るファイルの個数 +// 12 1.w データ領域の先頭セクタ番号 +// 14 1.w 総クラスタ数 + 1 +// 16 1.w ルートディレクトリの先頭セクタ番号 +// 18 1.l (ドライバヘッダのアドレス) +// 22 1.b (小文字の物理ドライブ名) +// 23 1.b (DPB 使用フラグ:常に 0) +// 24 1.l (次の DPB のアドレス) +// 28 1.w (カレントディレクトリのクラスタ番号:常に 0) +// 30 64.b (カレントディレクトリ名) +// +//--------------------------------------------------------------------------- +DWORD GetDPB(void) +{ + BYTE *pDpb; + dpb_t dpb; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // DPB取得 + pDpb = GetReqAddr(14); + + // ファイルシステム呼び出し + nResult = FS_GetDPB(&dpb); + + // 結果の反映 + if (nResult >= 0) { + SetDpb(pDpb, &dpb); + } + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $53 - セクタ読み込み +// +// in (offset size) +// 1 1.B ユニット番号 +// 14 1.L バッファアドレス +// 18 1.L セクタ数 +// 22 1.L セクタ番号 +// +//--------------------------------------------------------------------------- +DWORD DiskRead(void) +{ + BYTE *pAddress; + DWORD nSize; + DWORD nSector; + BYTE buffer[0x200]; + int nResult; + int i; + + ASSERT(this); + ASSERT(fs); + + pAddress = GetReqAddr(14); // アドレス (上位ビットが拡張フラグ) + nSize = GetReqLong(18); // セクタ数 + nSector = GetReqLong(22); // セクタ番号 + + // ファイルシステム呼び出し + nResult = FS_DiskRead(buffer, nSector, nSize); + + // 結果の反映 + if (nResult >= 0) { + for (i = 0; i < sizeof(buffer); i++) { + *pAddress = buffer[i]; + pAddress++; + } + } + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $54 - セクタ書き込み +// +// in (offset size) +// 1 1.B ユニット番号 +// 14 1.L バッファアドレス +// 18 1.L セクタ数 +// 22 1.L セクタ番号 +// +//--------------------------------------------------------------------------- +DWORD DiskWrite(void) +{ + BYTE *pAddress; + DWORD nSize; + DWORD nSector; + int nResult; + + ASSERT(this); + ASSERT(fs); + + pAddress = GetReqAddr(14); // アドレス(上位ビットが拡張フラグ) + nSize = GetReqLong(18); // セクタ数 + nSector = GetReqLong(22); // セクタ番号 + + // ファイルシステム呼び出し + nResult = FS_DiskWrite(); + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $55 - IOCTRL +// +// in (offset size) +// 1 1.B ユニット番号 +// 14 1.L パラメータ +// 18 1.W 機能番号 +// +//--------------------------------------------------------------------------- +DWORD Ioctrl(void) +{ + DWORD param; + DWORD func; + ioctrl_t ioctrl; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // IOCTRL取得 + param = GetReqLong(14); // パラメータ + func = GetReqWord(18); // 機能番号 + GetIoctrl(param, func, &ioctrl); + + // ファイルシステム呼び出し + nResult = FS_Ioctrl(func, &ioctrl); + + // 結果の反映 + if (nResult >= 0) + SetIoctrl(param, func, &ioctrl); + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $56 - フラッシュ +// +// in (offset size) +// 1 1.B ユニット番号 +// +//--------------------------------------------------------------------------- +DWORD Flush(void) +{ + int nResult; + + ASSERT(this); + ASSERT(fs); + + // ファイルシステム呼び出し + nResult = FS_Flush(); + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $57 - メディア交換チェック +// +// in (offset size) +// 0 1.b 定数(26) +// 1 1.b ユニット番号 +// 2 1.b コマンド($57/$d7) +// out (offset size) +// 3 1.b エラーコード(下位) +// 4 1.b 〃 (上位) +// 18 1.l リザルトステータス +// +// メディアが交換されたか否かを調べる. 交換されていた場合のフォーマット +// 確認はこのコマンド内で行うこと. +// +//--------------------------------------------------------------------------- +DWORD CheckMedia(void) +{ +#if 1 + static DWORD last = 0; + DWORD now; +#endif + int nResult; + + ASSERT(this); + ASSERT(fs); + +#if 1 + // 連続で呼び出されるの回避する + now = TIMEGET(); + if ((now - last) < 3) { + return 0; + } else { + last = now; + } +#endif + + // ファイルシステム呼び出し + nResult = FS_CheckMedia(); + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $58 - 排他制御 +// +// in (offset size) +// 1 1.B ユニット番号 +// +//--------------------------------------------------------------------------- +DWORD Lock(void) +{ + int nResult; + + ASSERT(this); + ASSERT(fs); + + // ファイルシステム呼び出し + nResult = FS_Lock(); + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// コマンド実行 +// +//--------------------------------------------------------------------------- +DWORD ExecuteCommand() +{ + ASSERT(this); + + // エラー情報クリア + SetReqByte(3, 0); + SetReqByte(4, 0); + + // コマンド番号 + command = (DWORD)GetReqByte(2); // ビット7はベリファイフラグ + + // ユニット番号 + unit = GetReqByte(1); + + // コマンド分岐 + switch (command & 0x7F) { + case 0x40: return InitDevice(); // $40 - デバイス起動 + case 0x41: return CheckDir(); // $41 - ディレクトリチェック + case 0x42: return MakeDir(); // $42 - ディレクトリ作成 + case 0x43: return RemoveDir(); // $43 - ディレクトリ削除 + case 0x44: return Rename(); // $44 - ファイル名変更 + case 0x45: return Delete(); // $45 - ファイル削除 + case 0x46: return Attribute(); // $46 - ファイル属性取得/設定 + case 0x47: return Files(); // $47 - ファイル検索 + case 0x48: return NFiles(); // $48 - ファイル次検索 + case 0x49: return Create(); // $49 - ファイル作成 + case 0x4A: return Open(); // $4A - ファイルオープン + case 0x4B: return Close(); // $4B - ファイルクローズ + case 0x4C: return Read(); // $4C - ファイル読み込み + case 0x4D: return Write(); // $4D - ファイル書き込み + case 0x4E: return Seek(); // $4E - ファイルシーク + case 0x4F: return TimeStamp(); // $4F - ファイル更新時刻の取得/設定 + case 0x50: return GetCapacity();// $50 - 容量取得 + case 0x51: return CtrlDrive(); // $51 - ドライブ制御/状態検査 + case 0x52: return GetDPB(); // $52 - DPB取得 + case 0x53: return DiskRead(); // $53 - セクタ読み込み + case 0x54: return DiskWrite(); // $54 - セクタ書き込み + case 0x55: return Ioctrl(); // $55 - IOCTRL +#if 0 + case 0x56: return Flush(); // $56 - フラッシュ +#else + case 0x56: return 0; // $56 - フラッシュ +#endif + case 0x57: return CheckMedia(); // $57 - メディア交換チェック +#if 0 + case 0x58: return Lock(); // $58 - 排他制御 +#else + case 0x58: return 0; // $58 - 排他制御 +#endif + } + + return FS_FATAL_INVALIDCOMMAND; +} + +//--------------------------------------------------------------------------- +// +// 初期化 +// +//--------------------------------------------------------------------------- +BOOL Init() +{ + ASSERT(this); + + return SCSI_Init(); +} + +//--------------------------------------------------------------------------- +// +// 実行 +// +//--------------------------------------------------------------------------- +void Process(DWORD nA5) +{ + ASSERT(this); + ASSERT(nA5 <= 0xFFFFFF); + ASSERT(m_bAlloc); + ASSERT(m_bFree); + + // リクエストヘッダのアドレス + request = (BYTE*)nA5; + + // コマンド実行 + SetResult(ExecuteCommand()); +} diff --git a/src/x68k/RASDRV/BRIDGE.H b/src/x68k/RASDRV/BRIDGE.H new file mode 100644 index 00000000..b59c642d --- /dev/null +++ b/src/x68k/RASDRV/BRIDGE.H @@ -0,0 +1,256 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technorogy. +// Copyright (C) 2016-2017 GIMONS +// [ ホストファイルシステム ブリッジドライバ ] +// +//--------------------------------------------------------------------------- + +#ifndef bridge_h +#define bridge_h + +typedef unsigned char BYTE; +typedef unsigned short WORD; +typedef unsigned long DWORD; +typedef int BOOL; + +#if !defined(FALSE) +#define FALSE 0 +#endif + +#if !defined(TRUE) +#define TRUE 1 +#endif + +#define FASTCALL +#define ASSERT(x) + +//--------------------------------------------------------------------------- +// +// 定数定義 +// +//--------------------------------------------------------------------------- +#define FILEPATH_MAX _MAX_PATH +#define WINDRV_CLIPSIZE_MAX 0xC00000 + +//--------------------------------------------------------------------------- +// +// ステータスコード定義 +// +//--------------------------------------------------------------------------- +#define FS_INVALIDFUNC 0xFFFFFFFF // 無効なファンクションコードを実行した +#define FS_FILENOTFND 0xFFFFFFFE // 指定したファイルが見つからない +#define FS_DIRNOTFND 0xFFFFFFFD // 指定したディレクトリが見つからない +#define FS_OVEROPENED 0xFFFFFFFC // オープンしているファイルが多すぎる +#define FS_CANTACCESS 0xFFFFFFFB // ディレクトリやボリュームラベルはアクセス不可 +#define FS_NOTOPENED 0xFFFFFFFA // 指定したハンドルはオープンされていない +#define FS_INVALIDMEM 0xFFFFFFF9 // メモリ管理領域が破壊された +#define FS_OUTOFMEM 0xFFFFFFF8 // 実行に必要なメモリがない +#define FS_INVALIDPTR 0xFFFFFFF7 // 無効なメモリ管理ポインタを指定した +#define FS_INVALIDENV 0xFFFFFFF6 // 不正な環境を指定した +#define FS_ILLEGALFMT 0xFFFFFFF5 // 実行ファイルのフォーマットが異常 +#define FS_ILLEGALMOD 0xFFFFFFF4 // オープンのアクセスモードが異常 +#define FS_INVALIDPATH 0xFFFFFFF3 // ファイル名の指定に誤りがある +#define FS_INVALIDPRM 0xFFFFFFF2 // 無効なパラメータでコールした +#define FS_INVALIDDRV 0xFFFFFFF1 // ドライブ指定に誤りがある +#define FS_DELCURDIR 0xFFFFFFF0 // カレントディレクトリは削除できない +#define FS_NOTIOCTRL 0xFFFFFFEF // IOCTRLできないデバイス +#define FS_LASTFILE 0xFFFFFFEE // これ以上ファイルが見つからない +#define FS_CANTWRITE 0xFFFFFFED // 指定のファイルは書き込みできない +#define FS_DIRALREADY 0xFFFFFFEC // 指定のディレクトリは既に登録されている +#define FS_CANTDELETE 0xFFFFFFEB // ファイルがあるので削除できない +#define FS_CANTRENAME 0xFFFFFFEA // ファイルがあるのでリネームできない +#define FS_DISKFULL 0xFFFFFFE9 // ディスクが一杯でファイルが作れない +#define FS_DIRFULL 0xFFFFFFE8 // ディレクトリが一杯でファイルが作れない +#define FS_CANTSEEK 0xFFFFFFE7 // 指定の位置にはシークできない +#define FS_SUPERVISOR 0xFFFFFFE6 // スーパーバイザ状態でスーパバイザ指定した +#define FS_THREADNAME 0xFFFFFFE5 // 同じスレッド名が存在する +#define FS_BUFWRITE 0xFFFFFFE4 // プロセス間通信のバッファが書込み禁止 +#define FS_BACKGROUND 0xFFFFFFE3 // バックグラウンドプロセスを起動できない +#define FS_OUTOFLOCK 0xFFFFFFE0 // ロック領域が足りない +#define FS_LOCKED 0xFFFFFFDF // ロックされていてアクセスできない +#define FS_DRIVEOPENED 0xFFFFFFDE // 指定のドライブはハンドラがオープンされている +#define FS_LINKOVER 0xFFFFFFDD // シンボリックリンクネストが16回を超えた +#define FS_FILEEXIST 0xFFFFFFB0 // ファイルが存在する + +#define FS_FATAL_MEDIAOFFLINE 0xFFFFFFA3 // メディアが入っていない +#define FS_FATAL_WRITEPROTECT 0xFFFFFFA2 // 書き込み禁止違反 +#define FS_FATAL_INVALIDCOMMAND 0xFFFFFFA1 // 不正なコマンド番号 +#define FS_FATAL_INVALIDUNIT 0xFFFFFFA0 // 不正なユニット番号 + +#define HUMAN68K_PATH_MAX 96 // Human68kのパス最大長 + +//=========================================================================== +// +/// Human68k 名前空間 +// +//=========================================================================== +/// ファイル属性ビット +enum attribute_t { + AT_READONLY = 0x01, // 読み込み専用属性 + AT_HIDDEN = 0x02, // 隠し属性 + AT_SYSTEM = 0x04, // システム属性 + AT_VOLUME = 0x08, // ボリュームラベル属性 + AT_DIRECTORY= 0x10, // ディレクトリ属性 + AT_ARCHIVE = 0x20, // アーカイブ属性 + AT_ALL = 0xFF, // 全ての属性ビットが1 +}; + +/// ファイルオープンモード +enum open_t { + OP_READ = 0, // 読み込み + OP_WRITE = 1, // 書き込み + OP_FULL = 2, // 読み書き + OP_MASK = 0x0F, // 判定用マスク + OP_SHARE_NONE = 0x10, // 共有禁止 + OP_SHARE_READ = 0x20, // 読み込み共有 + OP_SHARE_WRITE = 0x30, // 書き込み共有 + OP_SHARE_FULL = 0x40, // 読み書き共有 + OP_SHARE_MASK = 0x70, // 共有判定用マスク + OP_SPECIAL = 0x100,// 辞書アクセス +}; + +/// シーク種類 +enum seek_t { + SK_BEGIN = 0, // ファイル先頭から + SK_CURRENT = 1, // 現在位置から + SK_END = 2, // ファイル末尾から +}; + +/// メディアバイト +enum media_t { + MEDIA_2DD_10 = 0xE0, // 2DD/10セクタ + MEDIA_1D_9 = 0xE5, // 1D/9セクタ + MEDIA_2D_9 = 0xE6, // 2D/9セクタ + MEDIA_1D_8 = 0xE7, // 1D/8セクタ + MEDIA_2D_8 = 0xE8, // 2D/8セクタ + MEDIA_2HT = 0xEA, // 2HT + MEDIA_2HS = 0xEB, // 2HS + MEDIA_2HDE = 0xEC, // 2DDE + MEDIA_1DD_9 = 0xEE, // 1DD/9セクタ + MEDIA_1DD_8 = 0xEF, // 1DD/8セクタ + MEDIA_MANUAL = 0xF1, // リモートドライブ (手動イジェクト) + MEDIA_REMOVABLE = 0xF2, // リモートドライブ (リムーバブル) + MEDIA_REMOTE = 0xF3, // リモートドライブ + MEDIA_DAT = 0xF4, // SCSI-DAT + MEDIA_CDROM = 0xF5, // SCSI-CDROM + MEDIA_MO = 0xF6, // SCSI-MO + MEDIA_SCSI_HD = 0xF7, // SCSI-HD + MEDIA_SASI_HD = 0xF8, // SASI-HD + MEDIA_RAMDISK = 0xF9, // RAMディスク + MEDIA_2HQ = 0xFA, // 2HQ + MEDIA_2DD_8 = 0xFB, // 2DD/8セクタ + MEDIA_2DD_9 = 0xFC, // 2DD/9セクタ + MEDIA_2HC = 0xFD, // 2HC + MEDIA_2HD = 0xFE, // 2HD +}; + +/// namests構造体 +typedef struct { + BYTE wildcard; // ワイルドカード文字数 + BYTE drive; // ドライブ番号 + BYTE path[65]; // パス(サブディレクトリ+/) + BYTE name[8]; // ファイル名 (PADDING 0x20) + BYTE ext[3]; // 拡張子 (PADDING 0x20) + BYTE add[10]; // ファイル名追加 (PADDING 0x00) +} namests_t; + +/// files構造体 +typedef struct { + BYTE fatr; // + 0 検索する属性 読込専用 + BYTE pad1[3]; // padding +// BYTE drive; // + 1 ドライブ番号 読込専用 + DWORD sector; // + 2 ディレクトリのセクタ DOS _FILES先頭アドレスで代用 +// WORD cluster; // + 6 ディレクトリのクラスタ 詳細不明 (未使用) + WORD offset; // + 8 ディレクトリエントリ 書込専用 +// BYTE name[8]; // +10 作業用ファイル名 読込専用 (未使用) +// BYTE ext[3]; // +18 作業用拡張子 読込専用 (未使用) + BYTE attr; // +21 ファイル属性 書込専用 + BYTE pad2; // padding + WORD time; // +22 最終変更時刻 書込専用 + WORD date; // +24 最終変更月日 書込専用 + DWORD size; // +26 ファイルサイズ 書込専用 + BYTE full[23]; // +30 フルファイル名 書込専用 + BYTE pad3; // padding +} files_t; + +/// FCB構造体 +typedef struct { +// BYTE pad00[6]; // + 0〜+ 5 (未使用) + DWORD fileptr; // + 6〜+ 9 ファイルポインタ +// BYTE pad01[4]; // +10〜+13 (未使用) + WORD mode; // +14〜+15 オープンモード +// BYTE pad02[16]; // +16〜+31 (未使用) +// DWORD zero; // +32〜+35 オープンのとき0が書き込まれている (未使用) +// BYTE name[8]; // +36〜+43 ファイル名 (PADDING 0x20) (未使用) +// BYTE ext[3]; // +44〜+46 拡張子 (PADDING 0x20) (未使用) + BYTE attr; // +47 ファイル属性 + BYTE pad; // padding +// BYTE add[10]; // +48〜+57 ファイル名追加 (PADDING 0x00) (未使用) + WORD time; // +58〜+59 最終変更時刻 + WORD date; // +60〜+61 最終変更月日 +// WORD cluster; // +62〜+63 クラスタ番号 (未使用) + DWORD size; // +64〜+67 ファイルサイズ +// BYTE pad03[28]; // +68〜+95 FATキャッシュ (未使用) +} fcb_t; + +/// capacity構造体 +typedef struct { + WORD freearea; // + 0 使用可能なクラスタ数 + WORD clusters; // + 2 総クラスタ数 + WORD sectors; // + 4 クラスタあたりのセクタ数 + WORD bytes; // + 6 セクタ当たりのバイト数 +} capacity_t; + +/// ctrldrive構造体 +typedef struct { + BYTE status; // +13 状態 + BYTE pad[3]; // padding +} ctrldrive_t; + +/// DPB構造体 +typedef struct { + WORD sector_size; // + 0 1セクタ当りのバイト数 + BYTE cluster_size; // + 2 1クラスタ当りのセクタ数-1 + BYTE shift; // + 3 クラスタ→セクタのシフト数 + WORD fat_sector; // + 4 FATの先頭セクタ番号 + BYTE fat_max; // + 6 FAT領域の個数 + BYTE fat_size; // + 7 FATの占めるセクタ数(複写分を除く) + WORD file_max; // + 8 ルートディレクトリに入るファイルの個数 + WORD data_sector; // +10 データ領域の先頭セクタ番号 + WORD cluster_max; // +12 総クラスタ数+1 + WORD root_sector; // +14 ルートディレクトリの先頭セクタ番号 +// DWORD driverentry; // +16 デバイスドライバへのポインタ (未使用) + BYTE media; // +20 メディア識別子 +// BYTE flag; // +21 DPB使用フラグ (未使用) + BYTE pad; // padding +} dpb_t; + +/// ディレクトリエントリ構造体 +typedef struct { + BYTE name[8]; // + 0 ファイル名 (PADDING 0x20) + BYTE ext[3]; // + 8 拡張子 (PADDING 0x20) + BYTE attr; // +11 ファイル属性 + BYTE add[10]; // +12 ファイル名追加 (PADDING 0x00) + WORD time; // +22 最終変更時刻 + WORD date; // +24 最終変更月日 + WORD cluster; // +26 クラスタ番号 + DWORD size; // +28 ファイルサイズ +} dirent_t; + +/// IOCTRLパラメータ共用体 +typedef union { + BYTE buffer[8]; // バイト単位でのアクセス + DWORD param; // パラメータ(先頭4バイト) + WORD media; // メディアバイト(先頭2バイト) +} ioctrl_t; + +/// コマンドライン引数構造体 +typedef struct { + BYTE buf[256]; // コマンドライン引数 +} argument_t; + +#endif // bridge_h diff --git a/src/x68k/RASDRV/Makefile b/src/x68k/RASDRV/Makefile new file mode 100644 index 00000000..4a449de3 --- /dev/null +++ b/src/x68k/RASDRV/Makefile @@ -0,0 +1,17 @@ +# +# Makefile for RASDRV.SYS +# + +CC = gcc -O2 -Wall -fomit-frame-pointer +AS = has +LK = hlk -l -x + +RASDRV.SYS : RASDRV.o BRIDGE.o + $(LK) -o $@ $^ libc.a libiocs.a libscsi.a + +RASDRV.o : RASDRV.S + $(AS) $^ + +BRIDGE.o : BRIDGE.C + $(CC) -c -o $@ $^ + \ No newline at end of file diff --git a/src/x68k/RASDRV/RASDRV.S b/src/x68k/RASDRV/RASDRV.S new file mode 100644 index 00000000..4bd36f1e --- /dev/null +++ b/src/x68k/RASDRV/RASDRV.S @@ -0,0 +1,193 @@ +*--------------------------------------------------------------------------- +* +* SCSI Target Emulator RaSCSI (*^..^*) +* for Raspberry Pi +* +* Powered by XM6 TypeG Technorogy. +* Copyright (C) 2016-2017 GIMONS +* [ ホストファイルシステム ブリッジドライバ ] +* +* Based on +* X68k Emulator Host Filesystem Driver version 0.27 +* Programmed By co +* +*--------------------------------------------------------------------------- + + CPU 68010 + + INCLUDE DOSCALL.MAC + INCLUDE IOCSCALL.MAC + +.XREF _Init, _Process ;bridge.c + +COMMAND EQU 2 コマンド番号 +ERRLOW EQU 3 エラーコード下位8ビット +ERRHIGH EQU 4 エラーコード上位8ビット +MXUNIT EQU 13 ユニット数 +DEVEND EQU 14 ドライバ終了アドレス +BDEVNO EQU 22 ベースドライブ番号 + +DDHEADER: + DC.L -1 +$00 リンクポインタ + DC.W $2040 +$04 デバイス属性 + DC.L DDSTRATEGY +$06 + DC.L DDENTRY_FIRST +$0A + DC.B '*EMUHOST' +$0E デバイス名 + +DDREQUEST: + DC.L 0 + +DDSTRATEGY: + MOVE.L A5,DDREQUEST + RTS + +*デバイスドライバエントリ +DDENTRY: + MOVE.L SP,(STACK_BUFF) + LEA (DEF_STACK),SP + MOVEM.L D1-D3/A0-A2,-(SP) + MOVEM.L DDREQUEST(PC),D0 D0.L: リクエストヘッダアドレス + MOVE.L D0,-(SP) + BSR _Process + ADDQ.L #4,SP + MOVEM.L (SP)+,D1-D3/A0-A2 + MOVEA.L (STACK_BUFF),SP + RTS + +KEEP_HERE: + +*初回のみのデバイスドライバエントリ +DDENTRY_FIRST: + MOVEM.L D1-D3/A0-A2/A5,-(SP) + MOVEA.L DDREQUEST(PC),A5 A5.L: リクエストヘッダアドレス +* CMPI.B #$40,COMMAND(A5) 現行のHuman68kではチェック不要 +* BNE UNSUPPORTED エラー: 未対応 + +*タイトル表示 + PEA MESSAGE_TITLE(PC) + DOS _PRINT + ADDQ.L #4,SP + +*デバイスチェック +DEVICE_CHECK: + BSR _Init + + TST.L D0 + BEQ NOTFOUND エラー: デバイスが存在しません + +*常駐開始 + LEA DDENTRY(PC),A1 + + LEA DDHEADER+$0A(PC),A0 + MOVE.L A1,(A0) ドライバエントリを設定 + MOVE.L #PROG_END,DEVEND(A5) 常駐終了アドレスを設定 + + ST.B MXUNIT(A5) ポート未実装の判定のため負の値を設定しておく + JSR (A1) ドライバエントリを実行 + + TST.B MXUNIT(A5) ユニット数確認 + BLE NODRIVE エラー: ドライブがありません + + MOVE.B BDEVNO(A5),D0 + MOVE.B MXUNIT(A5),D1 + LEA FIRSTDRIVE(PC),A0 + ADD.B D0,(A0) 開始ドライブ名書き換え + ADD.B D1,D0 終了ドライブ名書き換え + ADD.B D0,LASTDRIVE-FIRSTDRIVE(A0) + + PEA MESSAGE_DRIVENAME(PC) 正常: ドライブA: + DOS _PRINT + + PEA MESSAGE_DRIVENAME2(PC) 正常: からZ: + SUBQ.B #2,D1 + BCS @F + DOS _PRINT +@@ ADDQ.L #8,SP + + PEA MESSAGE_DRIVENAME3(PC) 正常: を登録しました + BRA QUIT + +NOTFOUND: + PEA MESSAGE_NOTFOUND(PC) エラー: デバイスが存在しません + BRA ABORT + +UNSUPPORTED: + PEA MESSAGE_UNSUPPORTED(PC) エラー: 未対応 + BRA ABORT + +NODRIVE: + PEA MESSAGE_NODRIVE(PC) エラー: ドライブがありません + +ABORT: + MOVE.B #$0D,ERRLOW(A5) + MOVE.B #$70,ERRHIGH(A5) + +QUIT: + DOS _PRINT + ADDQ.L #4,SP + + MOVEM.L (SP)+,D1-D3/A0-A2/A5 + RTS + +SECRET: + PEA MESSAGE_TITLE2(PC) + DOS _PRINT + PEA CREDIT(PC) + DOS _PRINT + ADDQ.L #8,SP + DOS _EXIT + + DATA + +*エラーメッセージ +MESSAGE_NOTFOUND: + DC.B 'デバイスが存在しません',$0D,$0A,0 + +MESSAGE_UNSUPPORTED: + DC.B '未対応',$0D,$0A,0 + +MESSAGE_NODRIVE: + DC.B 'ドライブがありません',$0D,$0A,0 + +*登録メッセージ +MESSAGE_DRIVENAME: + DC.B 'ドライブ' +FIRSTDRIVE: + DC.B 'A:',0 +MESSAGE_DRIVENAME2: + DC.B 'から' +LASTDRIVE: + DC.B '@:',0 +MESSAGE_DRIVENAME3: + DC.B 'を登録しました',$0D,$0A,0 + +*タイトル +MESSAGE_TITLE: + DC.B $0D,$0A +MESSAGE_TITLE2: + DC.B 'RaSCSI FileSystem Driver version 1.21',$0D,$0A,0 + +*ありがとう! +CREDIT: + DC.B 'Coded by GIMONS',$0D,$0A + DC.B 'Special thanks to',$0D,$0A + DC.B 9,'co',$0D,$0A + DC.B 9,'PI.',$0D,$0A + DC.B 9,'立花@桑島技研',$0D,$0A + DC.B 0 + + BSS + QUAD + +STACK_BUFF: + .DS.L 1 + + STACK + QUAD + + .DS.B 1024*2 +DEF_STACK: + + +PROG_END: + END SECRET diff --git a/src/x68k/RASDRV/RASDRV.TXT b/src/x68k/RASDRV/RASDRV.TXT new file mode 100644 index 00000000..cbb094e2 --- /dev/null +++ b/src/x68k/RASDRV/RASDRV.TXT @@ -0,0 +1,29 @@ +RaSCSI ファイルシステムドライバ +RASDRV version 1.21 + +■概要 + + 本プログラムはX68000実機で動作しているHuman68kからRaSCSIのブリッジデバイスを + 通してRaspberry Pi側のファイルシステムを直接操作するためのデバイスドライバです。 + X68000エミュレータであるXM6及びXM6改ならびにTypeGのWindrvXMと同等の機能を提供 + します。 + +■解説 + + 利用するにはRaspberry PiのRaSCSIでブリッジデバイスを有効にする必要があります。 + 例えばSCSI ID6にブリッジデバイスを有効にする場合はrascsi -ID6 BRIDGEといった + 指定が必要です。 + + 次にデバイスドライバRASCSI.SYSを実機の環境にコピーします。あとはCONFIG.SYSの + 後半部分に以下のように記述してください。 + + DEVICE = \SYS\RASDRV.SYS + + 起動オプションを指定しない場合はRaspberry Piのルートディレクトリ配下をマウント + します。引数にディレクトリ名を指定することでそのディレクトリをマウントできます。 + 例えば/home/pi/appと/home/pi/dataというディレクトリをマウントする場合は + + DEVICE = \SYS\RASDRV.SYS /home/pi/app /home/pi/data + + と記述することで二つのディレクトリを別々のドライブとしてマウント可能です。 + その他のオプションとしてWindrvXMのものが指定可能です。 diff --git a/src/x68k/RASETHER/Makefile b/src/x68k/RASETHER/Makefile new file mode 100644 index 00000000..92557b33 --- /dev/null +++ b/src/x68k/RASETHER/Makefile @@ -0,0 +1,33 @@ +# +# Makefile for RASETHER.SYS +# + +TARGET = RASETHER.SYS + +OBJS = re.o asmsub.o main.o scsictl.o +LIBS = libc.a libgnu.a libscsi.a + +CC = gcc -O2 -Wall -fomit-frame-pointer +CFLAGS = -D__DOS_INLINE__ -D__IOCS_INLINE__ +#CFLAGS = -D__DOS_INLINE__ -D__IOCS_INLINE__ -DUSE_DMA + +AS = has +ASFLAGS = +LD = hlk +LDFLAGS = -l -x + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(LD) $(LDFLAGS) -o $@ $^ $(LIBS) + +scsictl.o: scsictl.c scsictl.h + $(COMPILE.c) $< + +main.o: main.c main.h scsictl.h + $(COMPILE.c) $< + +asmsub.o: asmsub.s + +# EOF + \ No newline at end of file diff --git a/src/x68k/RASETHER/RASETHER.DOC b/src/x68k/RASETHER/RASETHER.DOC new file mode 100644 index 00000000..5e37f13c --- /dev/null +++ b/src/x68k/RASETHER/RASETHER.DOC @@ -0,0 +1,42 @@ +RaSCSI用 Ethernetドライバ +RASETHER version 1.20 + +Based on + Neptune-X board driver for Human-68k(ESP-X) version 0.03 + Programed 1996-7 by Shi-MAD. + Special thanks to Niggle, FIRST, yamapu ... + +● このプログラムは + + Shi-MAD さんの作られた Ethernet 用 ISA バスブリッジ "Neptune-X" 用デバ + イスドライバ ether_ne.sys を改造した ether_ne.sys ver0.03 +M01 +1 +L12を + 参考にして開発したRaSCSI用のイーサーネット通信ドライバです。 + +● 使い方 + + 基本的にはオリジナルのドライバと同じようにデバイスドライバとしてCONFIG.SYS + で組み込んで下さい。 + + 例) + DEVICE = \SYS\RASETHER.SYS + + 以下のオプションが指定可能です。 + -tx [xは数字] : 使用するtrapを指定します。xは0から6が指定可能です。 + ただし、指定したtrapが使用中である場合は、trap #0から + 空いている所を自動探索し、見つかった空きtrapを利用し + ます。 + -n : APIにtrapを使用しません。 + + RASETHERで拡張したオプションは以下のとおりです。 + -px [xは数字] : パケット受信のポーリング間隔を指定します1がデフォルトです。 + 1の場合は約16ms毎にポーリングします。2,3・・・8まで指定が可能 + です。数字が一つ増えるごとに16ms間隔が大きくなります。 + + -ix [xは数字] : ポーリングに使用する割り込みのタイプを指定します。 + デフォルトは0でMFPのGPIP割り込み(V-DISP)を利用します。 + 1を指定するとTimer-A割り込みを使用します。 + + +● このドライバについて + オリジナルのether_ne.sys及び改造版のether_ne.sys ver0.03 +M01 +1 +L12の + 利用規定に従います。 diff --git a/src/x68k/RASETHER/asmsub.s b/src/x68k/RASETHER/asmsub.s new file mode 100644 index 00000000..87d85957 --- /dev/null +++ b/src/x68k/RASETHER/asmsub.s @@ -0,0 +1,22 @@ +* asmsub.s + + .xdef _DI, _EI * ne2000.c nagai. + + .text + .even + + + +_DI: + move.w sr,sendp_sr + ori.w #$700,sr + rts +_EI: + move.w sendp_sr,sr + rts + +sendp_sr: + .ds.w 1 + + + .even diff --git a/src/x68k/RASETHER/main.c b/src/x68k/RASETHER/main.c new file mode 100644 index 00000000..a6b6bb4a --- /dev/null +++ b/src/x68k/RASETHER/main.c @@ -0,0 +1,282 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technorogy. +// Copyright (C) 2016-2017 GIMONS +// [ RaSCSI イーサーネット メイン ] +// +// Based on +// Neptune-X board driver for Human-68k(ESP-X) version 0.03 +// Programed 1996-7 by Shi-MAD. +// Special thanks to Niggle, FIRST, yamapu ... +// +//--------------------------------------------------------------------------- + +#include +#include +#include +#include "main.h" +#include "scsictl.h" + +unsigned int scsiid; +int trap_no; +int num_of_prt; +struct prt PRT_LIST[NPRT]; + +// マルチキャスト(未対応) +#ifdef MULTICAST +int num_of_multicast; +struct eaddr multicast_array[NMULTICAST]; +#endif + +/************************************************ + * * + ************************************************/ +static int sprint_eaddr(unsigned char* dst, void* e) +{ + unsigned char* p = e; + + return sprintf( + dst, + "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", + p[0], p[1], p[2], p[3], p[4], p[5]); +} + +/************************************************ + * TRAP nが使用可能か調べる * + ************************************************/ +static int is_valid_trap(int trap_no) +{ + unsigned int addr; + + if (trap_no < 0 || 7 < trap_no) { + return 0; + } + + // 使用中かどうかチェック + addr = (unsigned int)_dos_intvcg(TRAP_VECNO(trap_no)); + + // 処理アドレスの最上位バイトにベクタ番号が入っていれば未使用 + if (addr & 0xff000000) { + return -1; + } + + return 0; +} + +/************************************************ + * 未使用のTRAP nを検索 * + ************************************************/ +static int search_trap_no(int def) +{ + int i; + + // もしdefが使用可能ならそれに決定 + if (is_valid_trap(def)) { + return def; + } + + for (i = 0; i <= 6; i++) { + if (is_valid_trap(i)) { + return i; + } + } + + return -1; +} + +/************************************************ + * vector set * + ************************************************/ +static void* trap_vector(int trap_no, void *func) +{ + return _dos_intvcs(TRAP_VECNO(trap_no), func); +} + +/************************************************ + 初期化関数(ne.sイニシャライズで呼びます) * + ************************************************/ +int Initialize(void) +{ + unsigned char buff[128]; + unsigned char buff2[32]; + struct eaddr ether_addr; + + if (SearchRaSCSI()) + { + Print("RaSCSI Ether Adapter の存在を確認できませんでした\r\n"); + return -1; + } + + if (InitList(NPRT) + || InitRaSCSI()) + { + Print("RaSCSI Ether Adapter Driver の初期化に失敗しました\r\n"); + return -1; + } + + memset(ðer_addr, 0x00, sizeof(ether_addr)); + GetMacAddr(ðer_addr); + + // 未使用trap番号を調べる(指定番号優先) + if (trap_no >= 0) { + trap_no = search_trap_no(trap_no); + } + + if (trap_no >= 0) { + // trapをフックする + trap_vector(trap_no, (void*)trap_entry); + sprintf(buff, " API trap number:%d ", trap_no); + } else { + sprintf(buff, " API trap number:n/a "); + } + Print(buff); + + sprintf(buff, "SCSI ID:%d ", scsiid); + Print(buff); + + sprint_eaddr(buff2, ether_addr.eaddr); + sprintf(buff, "MAC Addr:%s\r\n", buff2); + Print(buff); + + // ポーリング開始 + RegisterIntProcess(poll_interval); + + return 0; +} + +/************************************************ + * プロトコルリスト初期化 * + ************************************************/ +int InitList(int n) +{ + struct prt* p; + int i; + + p = &PRT_LIST[0]; + for (i = 0; i < NPRT; i++, p++) { + p->type = -1; + p->func = 0; + p->malloc = (malloc_func)-1; + } + num_of_prt = 0; + +#ifdef MULTICAST + num_of_multicast = 0; +#endif + + return 0; +} + +/************************************************ + * 受信ハンドラ(プロトコル)追加 * + ************************************************/ +int AddList(int type, int_handler handler) +{ + struct prt* p; + int i, result; + + if (type == -1) { + return -1; + } + + result = -1; + + // overwrite if alreay exist + p = &PRT_LIST[0]; + for (i = 0; i < NPRT; i++, p++) { + if ((p->type == type && p->malloc != (malloc_func)-1) + || p->type == -1) + { + if (p->type == -1) + num_of_prt++; + + p->type = type; + p->func = handler; + p->malloc = (malloc_func)-1; + i++; + p++; + result = 0; + break; + } + } + + // clear if exist more + for (; i < NPRT; i++, p++) { + if (p->type == type && p->malloc != (malloc_func)-1) { + p->type = -1; + } + } + + return result; +} + +/************************************************ + * 受信ハンドラ(プロトコル)削除 * + ************************************************/ +int DeleteList(int type) +{ + struct prt* p; + int i, result; + + if (type == -1) { + return -1; + } + + result = -1; + for (i = 0, p = &PRT_LIST[0]; i < NPRT; i++, p++) { + if (p->type == type && p->malloc != (malloc_func)-1) { + p->type = -1; + result = 0; + num_of_prt--; + } + } + + return result; +} + +/************************************************ + * 受信ハンドラ(プロトコル)サーチ * + ************************************************/ +int_handler SearchList(int type) +{ + struct prt* p; + int i; + + if (type == -1) { + return 0; + } + + for (i = 0, p = &PRT_LIST[0]; i < NPRT; i++, p++) { + if (p->type == type) { + return p->func; + } + } + + return 0; +} + + +/************************************************ + * 受信ハンドラ(プロトコル)サーチ * + ************************************************/ +int_handler SearchList2(int type, int n) +{ + struct prt *p; + int i, cur; + + if (type == -1) { + return NULL; + } + + cur = 0; + for (i = 0, p = &PRT_LIST[0]; i < NPRT; i++, p++) { + if (p->type == type && cur++ == n) { + return p->func; + } + } + + return NULL; +} diff --git a/src/x68k/RASETHER/main.h b/src/x68k/RASETHER/main.h new file mode 100644 index 00000000..fa481a06 --- /dev/null +++ b/src/x68k/RASETHER/main.h @@ -0,0 +1,81 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technorogy. +// Copyright (C) 2016-2017 GIMONS +// [ RaSCSI イーサーネット メイン ] +// +// Based on +// Neptune-X board driver for Human-68k(ESP-X) version 0.03 +// Programed 1996-7 by Shi-MAD. +// Special thanks to Niggle, FIRST, yamapu ... +// +//--------------------------------------------------------------------------- + +#ifndef main_h +#define main_h + +#define ID_EN0 (('e'<<24)+('n'<<16)+('0'<<8)) +#undef MULTICAST + +// number of protocol type we can handle **EDIT this** +#define NPRT (16) + +// number of multicast address we can handle **EDIT this** +#define NMULTICAST (64) +/* ただし、まだマルチキャストには対応していない */ + +struct eaddr { + unsigned char eaddr [6]; +}; + +typedef void (*int_handler) (int, void*, int); +typedef void (*malloc_func) (unsigned int*); + +struct prt { + int type; + int_handler func; + malloc_func malloc; +}; + + +// グローバル変数 +extern unsigned int scsiid; +extern int trap_no; +extern int num_of_prt; +extern struct prt PRT_LIST [NPRT]; + +#ifdef MULTICAST +extern int num_of_multicast; +extern struct eaddr multicast_array [NMULTICAST]; +#endif + + +// プロトタイプ宣言 +extern int Initialize (void); +extern int InitList (int); +extern int AddList (int, int_handler); +extern int DeleteList (int); +extern int_handler SearchList (int); +extern int_handler SearchList2 (int, int); +extern malloc_func GetMallocFunc (int, int); + +#ifdef MULTICAST +extern int AddMulticastArray (struct eaddr*); +extern void DelMulticastArray (struct eaddr*); +extern void MakeMulticastTable (unsigned char*); +#endif + + +// ne.s 内関数 +extern void trap_entry (void); + + +#include +#define Print _iocs_b_print + +#define TRAP_VECNO(n) (0x20 + n) + +#endif // main_h diff --git a/src/x68k/RASETHER/re.s b/src/x68k/RASETHER/re.s new file mode 100644 index 00000000..2eba98a8 --- /dev/null +++ b/src/x68k/RASETHER/re.s @@ -0,0 +1,574 @@ +**--------------------------------------------------------------------------- +** +** SCSI Target Emulator RaSCSI (*^..^*) +** for Raspberry Pi +** +** Powered by XM6 TypeG Technorogy. +** Copyright (C) 2016-2017 GIMONS +** [ RaSCSI イーサーネット ドライバ ] +** +** Based on +** Neptune-X board driver for Human-68k(ESP-X) version 0.03 +** Programed 1996-7 by Shi-MAD. +** Special thanks to Niggle, FIRST, yamapu ... +** +**--------------------------------------------------------------------------- + +* Include Files ----------------------- * + + .include doscall.mac + .include iocscall.mac + + +* Global Symbols ---------------------- * + +* +* C言語用 外部宣言 +* + .xref _Initialize, _AddList, _SearchList, _DeleteList ;main.c + .xref _GetMacAddr, _SetMacAddr ;scsictl.c + .xref _SendPacket, _SetPacketReception ;scsictl.c +* .xref _AddMulticastAddr, _DelMulticastAddr ;未実装 + +* +* C言語用 外部変数 +* + .xref _num_of_prt ;main.c 登録プロトコル数 + .xref _trap_no ;使用trapナンバー + .xref _trans_counter ;scsictl.c 送信/受信バイト数 + .xref _intr_type ;scsictl.c 割り込み種別 + .xref _poll_interval ;scsictl.c ポーリング間隔 + + +* Text Section -------------------------------- * + + .cpu 68000 + .text + + +* +* デバイスヘッダー +* +device_header: + .dc.l -1 ;リンクポインター + .dc $8000 ;device att. + .dc.l strategy_entry ;stategy entry + .dc.l interupt_entry ;interupt entry + .dc.b '/dev/en0' ;device name + .dc.b 'EthD' ;for etherlib.a + .dc.b 'RASC' ;driver name (この後にエントリーを置く) + +* 'RASC' から superjsr_entry の間には何も置かないこと + +* +* イーサドライバ 関数 エントリー ( for DOS _SUPERJSR ) +* in: d0: command number +* a0: args +* +superjsr_entry: + movem.l d1-d7/a1-a7,-(sp) + +* move.l d0,-(sp) +* pea (mes11,pc) +* DOS _PRINT +* addq.l #4,sp +* move.l (sp)+,d0 +* .data +*mes11: .dc.b 'en0:spjEntry',13,10,0 +* .text + + bsr do_command + movem.l (sp)+,d1-d7/a1-a7 + rts ;普通のリターン + + +* +* イーサドライバ 関数 エントリー ( for trap #n ) +* in: d0: command number +* a0: args +* +_trap_entry:: + movem.l d1-d7/a1-a7,-(sp) + +* move.l d0,-(sp) +* pea (mes10,pc) +* DOS _PRINT +* addq.l #4,sp +* move.l (sp)+,d0 +* .data +*mes10: .dc.b 'en0:trapEntry',13,10,0 +* .text + + bsr do_command + movem.l (sp)+,d1-d7/a1-a7 + rte ;割り込みリターン + + +* +* 各処理ふりわけ +* +do_command: + moveq #FUNC_MIN,d1 + cmp.l d0,d1 + bgt error ;d0<-2 なら未対応コマンド番号 + moveq #FUNC_MAX,d1 + cmp.l d1,d0 + bgt error ;9 + bsr _SetPacketReception ;割り込み許可 ... scsictl.c + addq.l #4,sp + +* moveq #0,d0 ;SetPacketReception() で常に 0 が返るので省略 +set_int_addr_rts: + rts + + +* +* コマンド 06: 割り込みハンドラのアドレス取得 +* return: interupt address +* +get_int_addr: +* pea (mes07,pc) +* DOS _PRINT +* addq.l #4,sp +* .data +*mes07: .dc.b 'GetIntAddr',13,10,0 +* .text + + pea (a0) + bsr _SearchList + addq.l #4,sp + rts + + +* +* コマンド 07: 割り込みハンドラの削除 +* return: 0 (if no errors) +* +del_int_addr: +* pea (mes06,pc) +* DOS _PRINT +* addq.l #4,sp +* .data +*mes06: .dc.b 'DelIntAddr',13,10,0 +* .text + + pea (a0) + bsr _DeleteList ;main.c 関数 + move.l d0,(sp)+ + bmi del_int_addr_ret ;削除失敗 + + tst.l (_num_of_prt) ;ハンドラが一つもなくなれば割り込みを禁止する + bne del_int_addr_ret + + clr.l -(sp) ;0=<禁止> + bsr _SetPacketReception ;割り込み禁止 ... scsictl.c + addq.l #4,sp + +* moveq #0,d0 ;SetPacketReception() で常に 0 が返るので省略 +del_int_addr_ret: + rts + + +* +* コマンド 08: マルチキャストアドレスの設定 +* +set_multicast_addr: +* pea (mes08,pc) +* .data +* DOS _PRINT +* addq.l #4,sp +*mes08: .dc.b 'SetMulticastAddr',13,10,0 +* .text + + moveq #0,d0 + rts + + +* +* コマンド 09: 統計読み出し +* +get_statistics: +* pea (mes09,pc) +* DOS _PRINT +* addq.l #4,sp +* .data +*mes09: .dc.b 'GetStatistics',13,10,0 +* .text + + moveq #0,d0 + rts + +* +* デバイスドライバエントリー +* +strategy_entry: + move.l a5,(request_buffer) + rts + + +interupt_entry: + move.l sp,(stack_buff) ;自前のスタックエリアを使う + lea (def_stack),sp ; + + movem.l d1-d7/a0-a5,-(sp) + movea.l (request_buffer,pc),a5 + tst.b (2,a5) + bne errorret + + pea (mestitle,pc) + DOS _PRINT + addq.l #4,sp + movea.l (18,a5),a4 +@@: + tst.b (a4)+ + bne @b + + moveq #0,d0 + move.l d0,(_trap_no) + move.l d0,(_intr_type) + moveq #1,d0 + move.l d0,(_poll_interval) + +arg_loop: + move.b (a4)+,d0 + beq arg_end + cmpi.b #'-',d0 + beq @f + cmpi.b #'/',d0 + bne param_errret +@@: + move.b (a4)+,d0 + beq param_errret +opt_loop: + andi.b #$df,d0 + cmpi.b #'I',d0 + beq opt_i + cmpi.b #'P',d0 + beq opt_p + cmpi.b #'T',d0 + beq opt_t + cmpi.b #'N',d0 + beq opt_n + bra param_errret + +opt_n: + moveq #-1,d0 + move.l d0,(_trap_no) + move.b (a4)+,d0 + beq arg_loop + bra opt_loop + +opt_t: + bsr get_num + tst.b d0 + bne param_errret + cmpi #6,d2 + bgt param_errret + move.l d2,(_trap_no) + move.b (a4)+,d0 + beq arg_loop + bra opt_loop + +opt_p: + bsr get_num + tst.b d0 + bne param_errret + cmpi #1,d2 + blt param_errret + cmpi #8,d2 + bgt param_errret + move.l d2,(_poll_interval) + move.b (a4)+,d0 + beq arg_loop + bra opt_loop + +opt_i: + bsr get_num + tst.b d0 + bne param_errret + cmpi #1,d2 + bgt param_errret + move.l d2,(_intr_type) + move.b (a4)+,d0 + beq arg_loop + bra opt_loop + +arg_end: + bsr _Initialize ;main.c 関数 + ;I/Oアドレス設定 + ;MACアドレス取得 + ;プロトコルリスト初期化 + ;SCSICTL初期化 + ;割り込みハンドラ(ベクタ設定) + ;trapサービス(ベクタ設定) + tst.l d0 + bne errorret + +* moveq #0,d0 + move.l #prog_end,(14,a5) + bra intret + + +param_errret: + pea (mesparam_err,pc) + DOS _PRINT + addq.l #4,sp +errorret: + move #$5003,d0 +intret: + move.b d0,(4,a5) + lsr #8,d0 + move.b d0,(3,a5) + movem.l (sp)+,d1-d7/a0-a5 + + movea.l (stack_buff,pc),sp ;スタックポインタを元にもどす + rts + +get_num: + moveq #1,d0 + moveq #0,d1 + moveq #0,d2 +@@: + move.b (a4),d1 + subi.b #'0',d1 + bcs @f + cmpi.b #9,d1 + bgt @f + move.b #0,d0 + andi #$f,d1 + mulu #10,d2 + add d1,d2 + addq.l #1,a4 + bra @b +@@: + rts + + +* Data Section ------------------------ * + + .data +mestitle: + .dc.b 13,10 + .dc.b 'RaSCSI Ethernet Driver version 1.20 / Based on ether_ne.sys+M01L12',13,10 + .dc.b 0 +mesparam_err: + .dc.b 'パラメータが異常です',13,10,0 + .even + + +* BSS --------------------------------- * + + .bss + .quad + +stack_buff: + .ds.l 1 +request_buffer: + .ds.l 1 +stack_buff_i: + .ds.l 1 + + +* Stack Section ----------------------- * + + .stack + .quad + +* +* スタックエリア +* + .ds.b 1024*8 +def_stack: + +prog_end: + .end + + +* EOF --------------------------------- * diff --git a/src/x68k/RASETHER/scsictl.c b/src/x68k/RASETHER/scsictl.c new file mode 100644 index 00000000..8d30dc6d --- /dev/null +++ b/src/x68k/RASETHER/scsictl.c @@ -0,0 +1,537 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technorogy. +// Copyright (C) 2016-2017 GIMONS +// [ RaSCSI イーサーネット SCSI制御部 ] +// +// Based on +// Neptune-X board driver for Human-68k(ESP-X) version 0.03 +// Programed 1996-7 by Shi-MAD. +// Special thanks to Niggle, FIRST, yamapu ... +// +//--------------------------------------------------------------------------- + +#include +#include +#include +#include +#include +#include "main.h" +#include "scsictl.h" + +typedef struct +{ + char DeviceType; + char RMB; + char ANSI_Ver; + char RDF; + char AddLen; + char RESV0; + char RESV1; + char OptFunc; + char VendorID[8]; + char ProductID[16]; + char FirmRev[4]; +} INQUIRY_T; + +typedef struct +{ + INQUIRY_T info; + char options[8]; +} INQUIRYOPT_T; + +#define MFP_AEB 0xe88003 +#define MFP_IERB 0xe88009 +#define MFP_IMRB 0xe88015 + +// asmsub.s 内のサブルーチン +extern void DI(); +extern void EI(); + +volatile short* iocsexec = (short*)0xa0e; // IOCS実行中ワーク +struct trans_counter trans_counter; // 送受信カウンタ +unsigned char rx_buff[2048]; // 受信バッファ +int imr; // 割り込み許可フラグ +int scsistop; // SCSI停止中フラグ +int intr_type; // 割り込み種別(0:V-DISP 1:TimerA) +int poll_interval; // ポーリング間隔(設定) +int poll_current; // ポーリング間隔(現在) +int idle; // アイドルカウンタ + +#define POLLING_SLEEP 255 // 4-5s + +/************************************************ + * MACアドレス取得命令発行 * + ************************************************/ +int SCSI_GETMACADDR(unsigned char *mac) +{ + unsigned char cmd[10]; + unsigned char sts; + unsigned char msg; + + if (S_SELECT(scsiid) != 0) { + return 0; + } + + cmd[0] = 0x28; + cmd[1] = 0; + cmd[2] = 1; + cmd[3] = 0; + cmd[4] = 0; + cmd[5] = 0; + cmd[6] = 0; + cmd[7] = 0; + cmd[8] = 6; + cmd[9] = 0; + if (S_CMDOUT(10, cmd) != 0) { + return 0; + } + +#ifdef USE_DMA + if (S_DATAIN(6, mac) != 0) { +#else + if (S_DATAIN_P(6, mac) != 0) { +#endif + return 0; + } + + S_STSIN(&sts); + S_MSGIN(&msg); + + return 1; +} + +/************************************************ + * MACアドレス設定命令発行 * + ************************************************/ +int SCSI_SETMACADDR(const unsigned char *mac) +{ + unsigned char cmd[10]; + unsigned char sts; + unsigned char msg; + + if (S_SELECT(scsiid) != 0) { + return 0; + } + + cmd[0] = 0x2a; + cmd[1] = 0; + cmd[2] = 1; + cmd[3] = 0; + cmd[4] = 0; + cmd[5] = 0; + cmd[6] = 0; + cmd[7] = 0; + cmd[8] = 6; + cmd[9] = 0; + if (S_CMDOUT(10, cmd) != 0) { + return 0; + } + +#ifdef USE_DMA + S_DATAOUT(6, mac); +#else + S_DATAOUT_P(6, mac); +#endif + + S_STSIN(&sts); + S_MSGIN(&msg); + + return 1; +} + +/************************************************ + * パケット受信サイズ取得命令発行 * + ************************************************/ +int SCSI_GETPACKETLEN(int *len) +{ + unsigned char cmd[10]; + unsigned char buf[2]; + unsigned char sts; + unsigned char msg; + + if (S_SELECT(scsiid) != 0) { + return 0; + } + + cmd[0] = 0x28; + cmd[1] = 0; + cmd[2] = 1; + cmd[3] = 1; + cmd[4] = 0; + cmd[5] = 0; + cmd[6] = 0; + cmd[7] = 0; + cmd[8] = 2; + cmd[9] = 0; + if (S_CMDOUT(10, cmd) != 0) { + return 0; + } + +#ifdef USE_DMA + if (S_DATAIN(2, buf) != 0) { +#else + if (S_DATAIN_P(2, buf) != 0) { +#endif + return 0; + } + + S_STSIN(&sts); + S_MSGIN(&msg); + + *len = (int)(buf[0] << 8) + (int)(buf[1]); + + return 1; +} + +/************************************************ + * パケット受信命令発行 * + ************************************************/ +int SCSI_GETPACKETBUF(unsigned char *buf, int len) +{ + unsigned char cmd[10]; + unsigned char sts; + unsigned char msg; + + if (S_SELECT(scsiid) != 0) { + return 0; + } + + cmd[0] = 0x28; + cmd[1] = 0; + cmd[2] = 1; + cmd[3] = 1; + cmd[4] = 0; + cmd[5] = 0; + cmd[6] = (unsigned char)(len >> 16); + cmd[7] = (unsigned char)(len >> 8); + cmd[8] = (unsigned char)len; + cmd[9] = 1; + if (S_CMDOUT(10, cmd) != 0) { + return 0; + } + +#ifdef USE_DMA + if (S_DATAIN(len, buf) != 0) { +#else + if (S_DATAIN_P(len, buf) != 0) { +#endif + return 0; + } + + S_STSIN(&sts); + S_MSGIN(&msg); + + return 1; +} + +/************************************************ + * パケット送信命令発行 * + ************************************************/ +int SCSI_SENDPACKET(const unsigned char *buf, int len) +{ + unsigned char cmd[10]; + unsigned char sts; + unsigned char msg; + + if (S_SELECT(scsiid) != 0) { + return 0; + } + + cmd[0] = 0x2a; + cmd[1] = 0; + cmd[2] = 1; + cmd[3] = 1; + cmd[4] = 0; + cmd[5] = 0; + cmd[6] = (unsigned char)(len >> 16); + cmd[7] = (unsigned char)(len >> 8); + cmd[8] = (unsigned char)len; + cmd[9] = 0; + if (S_CMDOUT(10, cmd) != 0) { + return 0; + } + +#ifdef USE_DMA + S_DATAOUT(len, buf); +#else + S_DATAOUT_P(len, buf); +#endif + S_STSIN(&sts); + S_MSGIN(&msg); + + return 1; +} + +/************************************************ + * MACアドレス取得 * + ************************************************/ +int GetMacAddr(struct eaddr* buf) +{ + if (SCSI_GETMACADDR(buf->eaddr) != 0) { + return 0; + } else { + return -1; + } +} + +/************************************************ + * MACアドレス設定 * + ************************************************/ +int SetMacAddr(const struct eaddr* data) +{ + if (SCSI_SETMACADDR(data->eaddr) != 0) { + return 0; + } else { + return -1; + } +} + +/************************************************ + * RaSCSI検索 * + ************************************************/ +int SearchRaSCSI() +{ + int i; + INQUIRYOPT_T inq; + + for (i = 0; i <= 7; i++) { + // BRIDGEデバイス検索 + if (S_INQUIRY(sizeof(INQUIRY_T) , i, (struct INQUIRY*)&inq) < 0) { + continue; + } + + if (memcmp(&(inq.info.ProductID), "RASCSI BRIDGE", 13) != 0) { + continue; + } + + // TAP初期化状態を取得 + if (S_INQUIRY(sizeof(INQUIRYOPT_T) , i, (struct INQUIRY*)&inq) < 0) { + continue; + } + + if (inq.options[1] != '1') { + continue; + } + + // SCSI ID確定 + scsiid = i; + return 0; + } + + return -1; +} + +/************************************************ + * RaSCSI初期化 関数 * + ************************************************/ +int InitRaSCSI(void) +{ +#ifdef MULTICAST + unsigned char multicast_table[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +#endif + + imr = 0; + scsistop = 0; + poll_current = -1; + idle = 0; + + return 0; +} + +/************************************************ + * RaSCSI 割り込み処理 関数(ポーリング) * + ************************************************/ +void interrupt IntProcess(void) +{ + unsigned char phase; + unsigned int len; + int type; + int_handler func; + int i; + + // V-DISP GPIP割り込みはアイドルカウンタで制御 + if (intr_type == 0) { + // アイドル加算 + idle++; + + // 次回の処理予定に到達していないならスキップ + if (idle < poll_current) { + return; + } + + // アイドルカウンタをクリア + idle = 0; + } + + // 割り込み開始 + + // 割り込み許可の時だけ + if (imr == 0) { + return; + } + + // IOCS実行中ならばスキップ + if (*iocsexec != -1) { + return; + } + + // 受信処理中は割り込み禁止 + DI (); + + // バスフリーの時だけ + phase = S_PHASE(); + if (phase != 0) { + // 終了 + goto ei_exit; + } + + // 受信処理 + if (SCSI_GETPACKETLEN(&len) == 0) { + // RaSCSI停止中 + scsistop = 1; + + // ポーリング間隔の再設定(寝る) + UpdateIntProcess(POLLING_SLEEP); + + // 終了 + goto ei_exit; + } + + // RaSCSIは動作中 + if (scsistop) { + scsistop = 0; + + // ポーリング間隔の再設定(急ぐ) + UpdateIntProcess(poll_interval); + } + + // パケットは到着してなかった + if (len == 0) { + // 終了 + goto ei_exit; + } + + // 受信バッファメモリへパケット転送 + if (SCSI_GETPACKETBUF(rx_buff, len) == 0) { + // 失敗 + goto ei_exit; + } + + // 割り込み許可 + EI (); + + // パケットタイプでデータ分別 + type = rx_buff[12] * 256 + rx_buff[13]; + i = 0; + while ((func = SearchList2(type, i))) { + i++; + func(len, (void*)&rx_buff, ID_EN0); + } + trans_counter.recv_byte += len; + return; + +ei_exit: + // 割り込み許可 + EI (); +} + +/************************************************ + * RaSCSI パケット送信 関数 (ne.sから) * + ************************************************/ +int SendPacket(int len, const unsigned char* data) +{ + if (len < 1) { + return 0; + } + + if (len > 1514) { // 6 + 6 + 2 + 1500 + return -1; // エラー + } + + // RaSCSI停止中のようならエラー + if (scsistop) { + return -1; + } + + // 送信処理中は割り込み禁止 + DI (); + + // 送信処理と送信フラグアップ + if (SCSI_SENDPACKET(data, len) == 0) { + // 割り込み許可 + EI (); + return -1; + } + + // 割り込み許可 + EI (); + + // 送信依頼済み + trans_counter.send_byte += len; + + return 0; +} + +/************************************************ + * RaSCSI 割り込み許可、不許可設定 関数 * + ************************************************/ +int SetPacketReception(int i) +{ + imr = i; + return 0; +} + +/************************************************ + * RaSCSI 割り込み処理登録 * + ************************************************/ +void RegisterIntProcess(int n) +{ + volatile unsigned char *p; + + // ポーリング間隔(現在)の更新とアイドルカウンタクリア + poll_current = n; + idle = 0; + + if (intr_type == 0) { + // V-DISP GPIP割り込みベクタを書き換えて + // 割り込みを有効にする + B_INTVCS(0x46, (int)IntProcess); + p = (unsigned char *)MFP_AEB; + *p = *p | 0x10; + p = (unsigned char *)MFP_IERB; + *p = *p | 0x40; + p = (unsigned char *)MFP_IMRB; + *p = *p | 0x40; + } else if (intr_type == 1) { + // TimerAはカウントモードを設定 + VDISPST(NULL, 0, 0); + VDISPST(IntProcess, 0, poll_current); + } +} + +/************************************************ + * RaSCSI 割り込み処理変更 * + ************************************************/ +void UpdateIntProcess(int n) +{ + // ポーリング間隔(現在)と同じなら更新しない + if (n == poll_current) { + return; + } + + // ポーリング間隔(現在)の更新とアイドルカウンタクリア + poll_current = n; + idle = 0; + + if (intr_type == 1) { + // TimerAは再登録必要 + VDISPST(NULL, 0, 0); + VDISPST(IntProcess, 0, poll_current); + } +} + +// EOF diff --git a/src/x68k/RASETHER/scsictl.h b/src/x68k/RASETHER/scsictl.h new file mode 100644 index 00000000..ae6bf477 --- /dev/null +++ b/src/x68k/RASETHER/scsictl.h @@ -0,0 +1,40 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technorogy. +// Copyright (C) 2016-2017 GIMONS +// [ RaSCSI イーサーネット SCSI制御部 ] +// +// Based on +// Neptune-X board driver for Human-68k(ESP-X) version 0.03 +// Programed 1996-7 by Shi-MAD. +// Special thanks to Niggle, FIRST, yamapu ... +// +//--------------------------------------------------------------------------- + +#ifndef scsictl_h +#define scsictl_h + +// グローバル変数 +extern int intr_type; +extern int poll_interval; + +// 送受信カウンタ +struct trans_counter { + unsigned int send_byte; + unsigned int recv_byte; +}; +extern struct trans_counter trans_counter; + +extern int SearchRaSCSI(); +extern int InitRaSCSI(void); +extern int GetMacAddr(struct eaddr* buf); +extern int SetMacAddr(const struct eaddr* data); +extern int SetPacketReception(int i); +extern int SendPacket(int len, const unsigned char* data); +extern void RegisterIntProcess(int n); +extern void UpdateIntProcess(int n); + +#endif // scsictl_h