*MUTEX(互斥體) [#u3cf670d]
SSP存在確認的方法~
SSP啟動時,創建名為"ssp"的MUTEX.下可由此確認SSP是否啟動。
 m_hMutex = ::OpenMutex(MUTEX_ALL_ACCESS,FALSE,"ssp");
 if(m_hMutex){
    //SSP已啟動
 }
 else{
    //SSP未啟動
 }

另外,因為Materia等平台對應的MUTEX名為"sakura"。~
在SSP的設置裡可以勾選生成名為"sakura"的Mutex來模擬Materia。 (SSP/1.09.00 Pre8追加)~
例如:
 hmutex=OpenMutex(MUTEX_ALL_ACCESS,FALSE,"sakura");
 if (hmutex==0) {
  // 不存在
 } else {
  // 存在
  CloseHandle(hmutex);
 }


FMO寫入、讀出時的互斥性可以利用名為"SakuraFMO"的Mutex(SSP/1.08.00追加)加鎖。~
可以對讀寫衝突所造成的數據破壞和數據不完全讀出進行有效的阻止,建議在啟動時取得。~

代碼用例:
 
 HANDLE hMutex = CreateMutex(NULL,FALSE,"SakuraFMO");
 if ( hMutex == NULL ) { 錯誤處理; } 
 if ( WaitForSingleObject(hMutex, 1000) != WAIT_TIMEOUT ) {
   //FMO讀寫;
  ReleaseMutex(Mutex);
 }
 CloseHandle(Mutex);
 
此外、如果處理中的進程帶著Mutex異常結束、WaitForSingleObject返回WAIT_ABANDONED。~
請注意不要忘記和WAIT_OBJECT_0經行比較。~

*File Mapping Objects [#la35e287]
當SSP等偽春菜平台運行時會創建一個特定的內存對象。~
所有其他進程可以從這個內存對像中以低成本獲取人格的資料信息。~
默認該filemapping對象名為"sakura",SSP可通過設置變更FMO名(SSP/1.09.00追加)~
內存映射結構~
0-3 長度值。指定大小。~
4- 數據主體~

主體數據格式~
主體是連續的一個項目挨著一個項目。~
項目形式如下:~
[ID].項[1]值[13][10]~

例如:
 ssp_fmo_header_0000108c_00110554.hwnd [1] 1115476
 ssp_fmo_header_0000108c_00110554.name [1] Emily
 ssp_fmo_header_0000108c_00110554.keroname [1] Teddy
 ssp_fmo_header_0000108c_00110554.path [1] Z:\ssp\
 ssp_fmo_header_0000108c_00110554.sakura.surface [1] 5
 ssp_fmo_header_0000108c_00110554.kero.surface [1] 10
 ssp_fmo_header_0000108c_00110554.kerohwnd [1] 591248
 ssp_fmo_header_0000108c_00110554.hwndlist [1] 1115476,591248,787914,787868,656814
 ssp_fmo_header_0000108c_00110554.ghostpath [1] Z:\ssp\ghost\emily4\

數據的意義~
[ID]在項名稱之前用"."分隔範圍。項名和值是由字符0x01分隔。一行的終止是回車(CR:字符0x0D)+換行(LF:字符0x0A)。~
[ID]為SSP的標識,形式為~
ssp_fmo_header_[進程ID-16進制]_[Sakura側hwnd-16進制]~
樣子的32字節字符串生成,作為毎個人格的唯一標識。可以通過SHIORI Event的uniqueid(即SSP/HF3.0追加的ID,SSP/HF3.2更名為uniqueid)獲得。~
注:Materia以進程ID的MD5值作為[ID],但是由於SSP的1個進程建立了複數個人格,所以未使用~

有效項如下:
|[ID].hwnd | 人格主窗口句柄|
|[ID].name | 活動的人格名稱|
|[ID].keroname | 活動的kero側人格名稱|
|[ID].path | SSP主程序的路徑|
|[ID].sakura.surface | 主人格surface編號(SSP/2.01.47後復活)|
|[ID].kero.surface | kero側人格surface編號(SSP/2.01.47後復活)|
|[ID].kerohwnd | kero側的hwnd存放unsigned int值。|
|[ID].hwndlist | 逗號分隔至\0的hwnd(無符號數值)列舉,無效窗口為0。 (SSP/2.02.33追加)|
|[ID].ghostpath | 人格所在文件的路徑(SSP/1.04.07追加)|

數據大小~
暫時的數據大小為1024 * 64個字節。數據的大小也有一個長度值。因此,真正的大小為(1024 * 64) - 4個字節。~

yaya可以使用READFMO函數讀取FMO,詳細可見yaya的說明。~
yaya可以使用READFMO函數讀取FMO,詳細可見yaya的說明。[[READFMO>開發文件/SHIORI/AYA/AYA系統函式參照表#READFMO]]~

*SAKURA API [#l02f74ca]
任何外部進程都可以從遠程控制偽春菜,或通過發送WM_SAKURAAPI給偽春菜進程來低成本的獲取偽春菜的內部信息。~
WM_SAKURAAPI被定義名為"Sakura"的窗口消息。~
詳見:[[開發文件/技術文檔/SAKURA API>開發文件/技術文檔/SAKURA API]]

 WM_SAKURAAPI = RegisterWindowMessage("Sakura");

SAKURA API只使用窗口消息WM_SAKURAAPI,具體命令是通過參數“wparam”和“lparam”來控制的。~
控制參數“wparam 0-127”被分為EXECUTE請求。偽春菜執行指示命令。~
控制參數“wparam 128-255”被分為GET請求。偽春菜返回請求的數據到客戶端。~
控制參數“wparam 256-384”被分為的NOTIFY請求。偽春菜收到事件請求。~

API列表~

EXECUTE  
 SA_EXECUTEREMAKEMENU 0
 SA_EXECUTEREWRITEFMO 1
 SA_EXECUTEWINDOWSTATESWITCH 2
 SA_EXECUTERELOADSHIORI 3
 SA_EXECUTENOTIFYOTHERGHOSTNAME 4

GET
 SA_GETHEADCOLLISIONRECTSAKURA 128
 SA_GETFACECOLLISIONRECTSAKURA 129
 SA_GETBUSTCOLLISIONRECTSAKURA 130
 SA_GETCENTERPOINTSAKURA 131
 SA_GETABSOLUTEKINOKOFIELDCENTERPOINTSAKURA 132
 SA_GETHEADCOLLISIONRECTKERO 133
 SA_GETFACECOLLISIONRECTKERO 134
 SA_GETBUSTCOLLISIONRECTKERO 135
 SA_GETCENTERPOINTKERO 136
 SA_GETABSOLUTEKINOKOFIELDCENTERPOINTKERO 137
 SA_GETPROCESSID 138
 SA_GETSHAREDMEMORY 139
 SA_GETGHOSTSTATE 140

NOTIFY
 SA_NOTIFYEVENT 256

SAKURA API/1.0~

SAKURA API/1.0是處理一般EXECUTE命令的請求。~

SA_EXECUTEREMAKEMENU / wparam = 0 / lparam = n/a~
這個API用來重建彈出菜單。在移動外表或人格等的文件時,偽春菜的菜單樹是不符合的,但您可以直接通過發送此命令刷新菜單樹。~

SA_EXECUTEREWRITEFMO / wparam = 1 / lparam = n/a~
這個API是用來重寫FMO。僅供內部使用。~

SA_EXECUTENOTIFYOTHERGHOSTNAME / wparam = 4 / lparam = n/a~
這個API的EXECUTE的NOTIFY otherghostname。~


SAKURA API/1.1~

SAKURA API/1.1處理一般GET命令的請求。~

SA_GETHEADCOLLISIONRECTSAKURA / wparam = 128 / lparam = 0 - 3~
SA_GETFACECOLLISIONRECTSAKURA / wparam = 129 / lparam = 0 - 3~
SA_GETBUSTCOLLISIONRECTSAKURA / wparam = 130 / lparam = 0 - 3~
這些API是用來返回head/face/bust(頭/臉/胸)的碰撞區域的主菜皮膚的矩形坐標。~
|lparam|lparam的|
|0 |左邊|
|1 |頂端|
|2 |右邊|
|3 |底部|


SA_GETCENTERPOINTSAKURA / wparam = 131 / lparam = 0 - 1~
這個API是用來返回當前顯示主菜皮膚的中心坐標的x和y值。~
|lparam|lparam的|
|0 |centerx|
|1 |centery|


SA_GETHEADCOLLISIONRECTKERO / wparam = 133 / lparam = 0 - 3~
SA_GETFACECOLLISIONRECTKERO / wparam = 134 / lparam = 0 - 3~
SA_GETBUSTCOLLISIONRECTKERO / wparam = 135 / lparam = 0 - 3~
這些API是用來返回head/face/bust(頭/臉/胸)的碰撞區域的使魔皮膚的矩形坐標。控制參數“lparam”的規格類似控制代碼128。~

SA_GETCENTERPOINTKERO / wparam = 136 / lparam = 0 - 1~
這個API是用來返回當前顯示使魔皮膚的中心坐標的x和y值。~
 lparam
 0 centerx
 1 centery
 


SA_GETGHOSTSTATE / wparam = 140 / lparam = n/a~
這個API是用來返回人格的當前狀態。返回值意義如下。~
 result
 GS_NONE 0 沒有事件,空閒狀態
 GS_TALKING 1 現在談話中
 GS_TIMECRITICALSESSION 2 time critical session


SAKURA API/1.2~

SAKURA API/1.2是獲得KINOKO絕對領域(AKF)的請求。~
SA_GETABSOLUTEKINOKOFIELDCENTERPOINTSAKURA / wparam = 132 / lparam = 0 - 1~
這個API是用來返回當前顯示主菜皮膚KINOKO絕對領域的中心坐標的x和y值。~
 lparam
 0 kinoko.centerx
 1 kinoko.centery


SA_GETABSOLUTEKINOKOFIELDCENTERPOINTKERO / wparam = 137 / lparam = 0 - 1~
這個API是用來返回當前顯示使魔皮膚KINOKO絕對領域的中心坐標的x和y值。控制參數“lparam”的規格類似控制代碼132。~


SAKURA API/1.3~

SAKURA API/1.3 是通知事件的請求。~

SA_GETPROCESSID / wparam = 138 / lparam = n/a~
這個API返回偽春菜的進程ID。~

SA_GETSHAREDMEMORY / wparam = 139 / lparam = -1 - 7~
這個API返回一個指針,它指向在進程空間中永久存在的8192bytes的靜態內存區。該指針作為內存插槽存在。在內存內的插槽數目為9(8192x9bytes),你可以得到每個插槽的指針值。~

外部進程通知事件給偽春菜用以上所示的兩種類型的信息。具體來說,首先,希望通知事件的外部進程必須使用SA_GETPROCESSID得到進程ID。接下來,通過使用函數“openprocess”打開進程。然後,通過使用函數WriteProcessMemory向SA_GETSHAREDMEMORY獲得的指針寫入所需的資料,最後,向偽春菜發送事件定義消息。當偽春菜收到事件請求時,根據從SHAREDMEMORY的每個插槽獲取的信息識別事件並適當的運行(在此之際,偽春菜主要是通知事件給SHIORI。)。~

插槽編號-1是為特殊用途使用。例如,當您使用SAKURA API/1.3通知事件給SHIORI/2.2時,插槽0-7對應於關於SHIORI規範的Reference0-7,-1用於事件的標識符。~

SA_NOTIFYEVENT / wparam = 256 / lparam = n/a~
這個API通知觸發事件給偽春菜。此消息除了觸發的事件無其他信息。發送者必須在發送此消息之前把SHAREDMEMORY設置正確的值。~


SAKURA API/1.4~

SA_EXECUTEWINDOWSTATESWITCH / wparam = 2 / lparam = n/a~
執行最小化。如果已經最小化,執行恢復。~


SAKURA API/1.5~

SA_EXECUTERELOADSHIORI / wparam = 3 / lparam = n/a~
重載當前人格的SHIORI模塊。~


FMO變更時給其他進程的通知~
NOTIFY otherghostname實裝、其他使用FMO的工具製作時、一次次的定期讀入FMO進行更新檢查的話花費太高。~
因此……SAKURA_API_BROADCAST_FMOUPDATE(1024)(SSP/HF3.2追加)。~

 #define SAKURA_API_BROADCAST_GHOSTCHANGE 1024
 
 WM_SAKURAAPI = RegisterWindowMessage("Sakura");
 
 SendNotifyMessage(HWND_BROADCAST,WM_SAKURAAPI,SAKURA_API_BROADCAST_GHOSTCHANGE,m_ProcID);
 
上述、更新FMO側~
 •message = Sakura API相同
 •wParam = 1024
 •lParam = SSP自己的進程ID
 
人格變化後對所有程序主窗體廣播FMO的更新通知。
 
 #define SAKURA_API_BROADCAST_GHOSTCHANGE 1024
 
 WM_SAKURAAPI = RegisterWindowMessage("Sakura");
 
 int CALLBACK WindowProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) {
 switch( message ){
   case WM_SAKURAAPI:
     if ( wParam == SAKURA_API_BROADCAST_GHOSTCHANGE ) {
       if ( lParam != GetCurrentProcessId() ) {
         做些什麼;
       }
     }
 }

接收側可以按更新的通知檢查。

*Direct SSTP [#e8ba6617]
Direct SSTP是一種利用窗口消息(非socket)進行SSTP協議通信的辦法。 Direct SSTP具有以下優點:~

可以使用SSTP進行簡單快速地通信(對於成本)。~
在本地計算機上兩個或更多的服務器很容易共存。 (人格彼此之間的通信很容易。)~
Direct SSTP只是一個通信方法。 Direct SSTP 與SSTP協議無關~。
注意: Direct SSTP的執行依賴於微軟Windows。~
Direct SSTP只是一個通信方法,與協議本身無關。~
&color(#ff0000){注意: Direct SSTP的執行依賴於微軟Windows。};~
Direct SSTP使用wm_copydata傳輸數據請求到服務器使用以下協議。 Direct SSTP服務器處理請求並返回相同格式的應答給報頭中指定的HWND窗口句柄。~

 copydatastruct
 dwData = 9801
 cbData = 請求報頭的長度
 lpData = 請求報頭字符串的指針

請求報頭如

 SEND SSTP/1.4
 Sender: CardCaptor
 Script: \h\s0Ah... Oh... Hmm...\e
 HWnd: 1024
 Charset: Shift_JIS
    
請求報頭的規格是與SSTP相同的。然而,應注意的是不管什麼樣的請求HWND報頭必須包含。不包含HWnd的Direct SSTP通信請求會被認為是一個“錯誤的請求”。

*SSTP [#l05c40cb]
''SSTP協議基本結構''~
''概念''~
所有的"SAKURA"都能作為SSTP的服務器。一個SSTP的服務器通過使用SSTP的固定協議和一個SSTP的客戶端通信,並按要求進行各種操作。有了這個結構,我們可以預期以下的"SAKURA":~

使用一個“表達對象”。~

給予“偽AI”適當的資料實現更好的潛力。~

由於這項服務是不依賴於操作系統的,所以可能並不終止於本地機器。~
例如:~
從SSTP客戶端"SAKURA"通過互聯網發送SSTP數據包給獨立的計算機。~
從網絡服務器發送SSTP數據包到"SAKURA"客戶機。~

''操作''~
"SAKURA"會偵聽9801端口(和/或端口7743)。客戶端連接到這個端口,並使用SSTP協議發送數據包。當客戶端發送數據包,"SAKURA"在兩秒鐘內返回一個狀態碼。如果包是正確的,"SAKURA"回應包中的請求並執行相應的操作。~
一台服務器只可以連接到一個客戶端。如果服務器已經連接到另一個客戶端,服務器會返回一個衝突。
通信假定會在很短的時間內完成。因此,如果在很短的時間內不能結束溝通,服務器將返回一個超時並強制斷開連接。~

''SSTP的協議定義''~
''字符集''~
請求主體和基本報頭(非DBCS,只有單字節字符在報頭)只使用ASCII碼。~
報頭中需要使用多字節字符的字符串(Sender/Script/Document/Songname/Sentence等)(發件人/腳本/文件/歌名/句子)可以使用下面的字符集和編碼:
 ASCII
 Shift_JIS
 ISO-2022-JP
 EUC-JP
 UTF-8

該字符集設置必須定義。如果字符集沒有定義,默認為Shift_JIS,但不建議使用。~
例如:

 SEND SSTP/1.1
 Sender: カードキャプター
 Script: \0\s0汝のあるべき姿に戻れ。 \e
 Option: nodescript,notranslate
 Charset: UTF-8
 
 [EOD]
    

在這個例子中,發件人和腳本頭被定義為使用UTF-8編碼。~

''請求''~
詳見:[[開發文件/技術文檔/SSTP>開發文件/技術文檔/SSTP]]

''返回狀態碼''~
|>|~2xx - 過程完成|
|200|OK 正常結束|
|204|無內容正常結束,但沒有數據被返回|
|210|中斷 SSTP發生中斷|
|>|~4xx - 請求錯誤|
|400|錯誤的請求 無效的請求內容|
|408|請求超時 發送數據時發生超時|
|409|衝突另一個客戶端已經連接,或關鍵會話正在運行|
|420|拒絕 人格拒絕SSTP|
|>|~5xx - 服務器錯誤|
|501|未實現服務器不支持所請求的功能。|
|503|服務不可用服務器設置不接受已發送請求。|
|510|非本地IP 服務器設置為只接受本地IP請求。|
|511|在黑名單中請求的服務器在服務器黑名單中登入。|
|512|無法顯示服務器在無法顯示信息的狀態。 (即使發送請求也是沒有用的。)|

''Reguration''~
通信時限為服務器端計時2秒。如果請求無法在2秒鐘下完成,服務器將返回“請求超時”,並強制斷開連接。


首頁   新建條目 一覽 搜索 最近的變更   幫助   最近更新的RSS