Aros/開發者/文件/庫/底層
lowlevel.library,在 Workbench/Kickstart 3.1 中引入,為遊戲和演示程式設計師提供計時器和鍵盤/操縱桿支援功能。
原始庫由康懋達設計,存在以下問題...
- 輸入函式是輪詢式的,而 AmigaOS 是事件驅動的。
- 輸入函式是系統範圍的,而不是應用程式範圍的。如果按下左鍵,只希望活動應用程式檢測到它。使用低階庫,其他應用程式也會檢測到它。
- 某些功能一次只能由一個應用程式使用。在多工環境中,這是一個非常糟糕的想法。
- 某些其他計時器函式只對 16 小時有效。然後它會返回錯誤的結果。
- 鼓勵程式設計師使用軟體中斷而不是高優先順序執行緒。
lowlevel.library 不維護中斷處理程式列表,它只維護一箇中斷處理程式,該處理程式會額外新增到標準鍵盤處理中。
ReadJoyPort() 已針對 USB 使用進行修補。
在原始的 AmigaOS 中,lowlevel.library 和 keyboard.device 密切相關,實際上只是一個模組的兩個介面,不能分開。無論如何,現在有兩個新的 HIDD,它們管理鍵盤和滑鼠驅動程式。現在可以同時插入多個低階驅動程式,它們的輸入流將被合併。請參閱 rom/hidd/keyboard 和 rom/hidd/mouse。
ReadJoyPort(unit) 獲取通常的數字位置 ReadJoyPort(unit + JP_TYPE_ANALOGUE) 獲取新的模擬位置,其中包含兩個八位計數器,用於儲存兩個操縱桿軸的絕對位置。
模擬軸資訊是 0 到 255 之間的無符號整數,不一定經過校準使其以 128 為中心。
應用程式也可以控制,並可以透過將 JP_ANALOGUE_PORT_MAGIC 新增到 portNumber 或在 SetJoyPortAttrs() 中將 SJA_TYPE 設定為 SJA_TYPE_ANALOGUE 來明確要求 JP_TYPE_ANALOGUE 資料。
- 要使用第二個模擬操縱桿,必須將其分配為第二個操縱桿(例如,將左操縱桿作為埠 0 中的操縱桿,另一個作為埠 1 中的操縱桿),並在該“第二個”操縱桿上啟用模擬駭客。
- 對兩個低階單元使用 JP_ANALOGUE_PORT_MAGIC。然後將操縱桿的第二個模擬搖桿對映到低階單元 0 的軸。
- 你的遊戲現在可以讀取一個操縱桿的兩個模擬搖桿 :-)
SetJoyPortAttrsA() 為力反饋和震動包支援添加了三個選項。這些目前是對操縱桿中找到的兩個馬達的非常基本的控制。
- portNumber - 相關的操縱桿埠 (0-3)。
- SJA_Type (ULONG) - 將當前控制器型別設定為滑鼠、操縱桿或遊戲控制器。提供以下之一:SJA_TYPE_GAMECTLR、SJA_TYPE_MOUSE、SJA_TYPE_JOYSTK 或 SJA_TYPE_AUTOSENSE。如果使用 SJA_TYPE_AUTOSENSE,則 SJA_TYPE_ANALOGUE 或 SJA_TYPE_AUTOSENSE。
如果使用 SJA_TYPE_AUTOSENSE,ReadJoyPort() 將嘗試自動確定插入給定埠的控制器型別。如果使用其他型別之一,ReadJoyPort() 將強制埠釋放任何已分配的資源;將隱含型別返回到 SJA_TYPE_AUTOSENSE。
- SJA_RumbleSetSlowMotor (UBYTE) - 如果有震動包,使用此標記將設定慢速馬達的速度為給定值 (0 - 255)。
- SJA_RumbleSetFastMotor (UBYTE) - 如果有震動包,使用此標記將設定快速馬達的速度為給定值 (0 - 255)。
- SJA_RumbleOff (BOOL) - 如果設定,這將關閉震動包馬達。
RESULT success - 如果一切按計劃進行,則為 TRUE,否則為 FALSE。
開啟震動的呼叫是
SetJoyPortAttrsA(joy, SJA_RumbleSetFastMotor, 255, TAG_DONE);
其中 joy 是相應的單元
ReadJoyPort() ignores buttons 8-12 on the gamepad, even though they work fine in Preferences
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/lowlevel.h>
#include <libraries/lowlevel_ext.h>
#include <stdio.h>
#include <stdlib.h>
struct Library *LowLevelBase;
static void printbuttons(ULONG val)
{
if (val & JPF_BUTTON_PLAY) printf("[PLAY/MMB]");
if (val & JPF_BUTTON_REVERSE) printf("[REVERSE]");
if (val & JPF_BUTTON_FORWARD) printf("[FORWARD]");
if (val & JPF_BUTTON_GREEN) printf("[SHUFFLE]");
if (val & JPF_BUTTON_RED) printf("[SELECT/LMB/FIRE]");
if (val & JPF_BUTTON_BLUE) printf("[STOP/RMB]");
}
static void printmousedirections(ULONG val)
{
printf("[%d,%d]", (val & JP_MHORZ_MASK), (val & JP_MVERT_MASK) >> 8);
}
static void printajoydirections(ULONG val)
{
printf("[%d, %d]", (val & JP_XAXIS_MASK), (val & JP_YAXIS_MASK) >> 8);
}
static void printjoydirections(ULONG val)
{
if (val & JPF_JOY_UP) printf("[UP]");
if (val & JPF_JOY_DOWN) printf("[DOWN]");
if (val & JPF_JOY_LEFT) printf("[LEFT]");
if (val & JPF_JOY_RIGHT) printf("[RIGHT]");
}
static void printjoyport(ULONG val)
{
int i;
for(i = 31; i >= 0; i--)
{
printf("%d", (val & (1 << i)) ? 1 : 0);
}
printf(" - ");
if ((val & JP_TYPE_MASK) == JP_TYPE_NOTAVAIL) printf("NOT AVAILABLE");
if ((val & JP_TYPE_MASK) == JP_TYPE_UNKNOWN) printf("UNKNOWN");
if ((val & JP_TYPE_MASK) == JP_TYPE_JOYSTK)
{
printf("JOYSTICK - ");
printjoydirections(val);
printbuttons(val);
}
if ((val & JP_TYPE_MASK) == JP_TYPE_GAMECTLR)
{
printf("GAME CONTROLLER - ");
printjoydirections(val);
printbuttons(val);
}
if ((val & JP_TYPE_MASK) == JP_TYPE_MOUSE)
{
printf("MOUSE - ");
printmousedirections(val);
printbuttons(val);
}
if ((val & JP_TYPE_MASK) == JP_TYPE_ANALOGUE)
{
printf("JOYSTICK[ANALOGUE] - ");
printajoydirections(val);
printbuttons(val);
}
printf("\n");
}
int main(int argc, char **argv)
{
int unit = 1;
if (argc == 2) unit = atoi(argv[1]);
LowLevelBase = OpenLibrary("lowlevel.library", 0);
if (LowLevelBase)
{
ULONG old = 0;
while(!CheckSignal(SIGBREAKF_CTRL_C))
{
ULONG new;
new = ReadJoyPort(unit);
if (new != old)
{
old = new;
printjoyport(new);
}
Delay(1);
}
CloseLibrary(LowLevelBase);
}
return 0;
}
value other than JP_TYPE_NOTAVAIL) this function may be used in interrupts. As an extension to the former available data, analogue joystick data may be returned. This is currently only supported by the Poseidon USB HID class, however, in future other devices may also add support for it. The user may specify the analogue data override option in the HID class and the data returned by ReadJoyPort() will be of type JP_TYPE_ANALOGUE, which contains two eight bit counters holding the absolute position of two joystick axis. An application can also take control and can explicitly demand JP_TYPE_ANALOGUE data by either adding JP_ANALOGUE_PORT_MAGIC to the portNumber or setting SJA_TYPE to SJA_TYPE_ANALOGUE in SetJoyPortAttrs(). The analogue axis information is an unsigned integer from 0 to 255 and has not necessarily been calibrated to be centered at 128. Compatibility issues: - If the HID class is not loaded, use of SJA_TYPE_ANALOGUE will have no effect and JP_TYPE_NOTAVAIL will be returned on ReadJoyPort(). - If the HID class is not loaded, and JP_ANALOGUE_PORT_MAGIC is used, JP_TYPE_NOTAVAIL will be returned on ReadJoyPort(). - If SetJoyPortAttrs() has been set to SJA_TYPE_JOYSTK or SJA_TYPE_GAMECTRL, using portNumbers from 0 to 3 still will return digitally interpreted data, whereas using portNumbers from JP_ANALOGUE_PORT_MAGIC to JP_ANALOGUE_PORT_MAGIC+3 will return the analogue data from the ports. INPUTS portNumber - port to read, in the range 0 to 3. If the JP_ANALOGUE_PORT_MAGIC bit is set additionally, the returned bitmask will be of JP_TYPE_ANALOGUE, even if the port was set to JP_TYPE_GAMECTRL or JP_TYPE_JOYSTK before. RESULT portState - bit map that identifies the device and the current JP_TYPE_GAMECTLR game controller JP_TYPE_MOUSE mouse JP_TYPE_JOYSTK joystick JP_TYPE_ANALOGUE analogue stick (EXT) JP_TYPE_UNKNOWN unknown device If type = JP_TYPE_GAMECTLR the bit map of portState is: JP_MVERT_MASK Mask for vertical counter JP_MHORZ_MASK Mask for horizontal counter If type = JP_TYPE_ANALOGUE the bit map of portState is: JPF_BUTTON_RED Button 1 (standard fire) JPF_BUTTON_BLUE Button 2 JPF_BUTTON_GREEN Button 3 JPF_BUTTON_YELLOW Button 4 JPF_BUTTON_FORWARD Button 5 JPF_BUTTON_REVERSE Button 6 JPF_BUTTON_PLAY Button 7 JP_XAXIS_MASK Mask for horizontal position JP_YAXIS_MASK Mask for vertical position SEE ALSO SetJoyPortAttrs() time attempting to sense which type of controller is in use -- and, optionally, to force ReadJoyPort() into utilizing a certain controller type. SetJoyPortAttrs() adds three options for force feedback and rumble pack support. These are currently very basic controls of two motors found in the joypad. INPUTS portNumber - the joyport in question (0-3). SJA_Type (ULONG) - Sets the current controller type to the mouse, joystick, or game controller. Supply one of SJA_TYPE_GAMECTLR, SJA_TYPE_MOUSE, SJA_TYPE_JOYSTK, or SJA_TYPE_AUTOSENSE. If SJA_TYPE_AUTOSENSE is used, SJA_TYPE_ANALOGUE, or SJA_TYPE_AUTOSENSE. If SJA_TYPE_AUTOSENSE is used, ReadJoyPort() will attempt to determine the type of controller plugged into the given port automatically. If one of the other types is used, ReadJoyPort() will forcing a port to deallocate any allocated resources; return the implied type to SJA_TYPE_AUTOSENSE. SJA_RumbleSetSlowMotor (UBYTE) - If a rumble pack is available, using this tag will set the speed of the slow motor to the given value (0 - 255). SJA_RumbleSetFastMotor (UBYTE) - If a rumble pack is available, using this tag will set the speed of the fast motor to the given value (0 - 255). SJA_RumbleOff (BOOL) - If set, this will turn the rumble pack motors off. success - TRUE if everything went according to plan, or FALSE upon failure <libraries/lowlevel.h>
implemented ULONG ReadJoyPort(ULONG port) UBYTE GetLanguageSelection() ULONG GetKey() VOID QueryKeys(struct KeyQuery * queryArray, UBYTE arraySize) APTR AddKBInt(const APTR intRoutine, const APTR intData) VOID RemKBInt(APTR intHandle) ULONG SystemControlA(const struct TagItem * tagList) ULONG SystemControl(Tag tagList, ...) APTR AddTimerInt(const APTR intRoutine, const APTR intData) VOID RemTimerInt(APTR intHandle) ULONG ElapsedTime(struct EClockVal * context) APTR AddVBlankInt(const APTR intRoutine, const APTR intData) VOID RemVBlankInt(APTR intHandle) BOOL SetJoyPortAttrsA(ULONG portNumber, const struct TagItem * tagList) not implemented BOOL SetJoyPortAttrs(ULONG portNumber, Tag tagList, ...) VOID StopTimerInt(APTR intHandle) VOID StartTimerInt(APTR intHandle, ULONG timeInterval, BOOL continuous)
可以透過將掩碼 JP_TYPE_MASK 應用於返回值並將結果值與以下值進行比較來確定裝置型別
| JP_TYPE_NOTAVAIL | 埠資料不可用 |
| JP_TYPE_GAMECTLR | 遊戲控制器 |
| JP_TYPE_MOUSE | 滑鼠 |
| JP_TYPE_JOYSTK | 操縱桿 |
| JP_TYPE_ANALOGUE | 模擬搖桿 |
| JP_TYPE_UNKNOWN | 未知裝置 |
| 如果 type = JP_TYPE_GAMECTL R,則 portState 的點陣圖是 | |
|---|---|
| JPF_BUTTON_BLUE | 藍色 - 停止 |
| JPF_BUTTON_RED | 紅色 - 選擇 |
| JPF_BUTTON_YELLOW | 黃色 - 重複 |
| JPF_BUTTON_GREEN | 綠色 - 隨機播放 |
| JPF_BUTTON_FORWARD | 炭灰色 - 向前 |
| JPF_BUTTON_REVERSE | 炭灰色 - 向後 |
| JPF_BUTTON_PLAY | 灰色 - 播放/暫停 |
| JPF_JOY_UP | 向上 |
| JPF_JOY_DOWN | 向下 |
| JPF_JOY_LEFT | 向左 |
| JPF_JOY_RIGHT | 向右 |
| 如果 type = JP_TYPE_JOYSTK,則 portState 的點陣圖是 | |
| JPF_BUTTON_BLUE | 向右 |
| JPF_BUTTON_RED | 開火 |
| JPF_JOY_UP | 向上 |
| JPF_JOY_DOWN | 向下 |
| JPF_JOY_LEFT | 向左 |
| JPF_JOY_RIGHT | 向右 |
| 如果 type = JP_TYPE_MOUSE,則 portState 的點陣圖是 | |
| JPF_BUTTON_BLUE | 右鍵 |
| JPF_BUTTON_RED | 左鍵 |
| JPF_BUTTON_PLAY | 中鍵 |
| JP_MVERT_MASK | 垂直計數器的掩碼 |
| JP_MHORZ_MASK | 水平計數器的掩碼 |
| 如果 type = JP_TYPE_ANALOGUE,則 portState 的點陣圖是 | |
| JPF_BUTTON_RED | 按鈕 1(標準開火) |
| JPF_BUTTON_BLUE | 按鈕 2 |
| JPF_BUTTON_GREEN | 按鈕 3 |
| JPF_BUTTON_YELLOW | 按鈕 4 |
| JPF_BUTTON_FORWARD | 按鈕 5 |
| JPF_BUTTON_REVERSE | 按鈕 6 |
| JPF_BUTTON_PLAY | 按鈕 7 |
| JP_XAXIS_MASK | 水平位置的掩碼 |
| JP_YAXIS_MASK | 垂直位置的掩碼 |