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 | 垂直位置的掩码 |