diff --git a/README.md b/README.md index dc05a29..3c398da 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,36 @@ # nim-libnx -Libnx ported to the Nim programming language. You will need a nim compiler with Nintendo switch support which can be found [here](https://github.com/jyapayne/Nim/tree/nintendo_switch_support) until the PR is accepted. +Libnx ported to the Nim programming language. You will need a Nim compiler with Nintendo switch support which can be found in the latest devel branch of the Nim compiler. -You also must have DevkitPro and switch (libnx) libraries for [Mac and Linux](https://github.com/devkitPro/pacman/releases) or [Windows](https://github.com/devkitPro/installer/releases) installed. The DEVKITPRO environment variable must also exist and point to a directory with the following structure: +You also must have DevkitPro and switch (libnx) libraries for [Mac and Linux](https://github.com/devkitPro/pacman/releases) or [Windows](https://github.com/devkitPro/installer/releases) installed. + +From dkp-pacman, the switch libraries can be installed with: + +``` +dkp-pacman -Syu +dkp-pacman -S switch-dev +## When it asks for installation options, choose the default which will install everything +``` + +The DEVKITPRO environment variable must also exist and point to a directory with the following structure: -- `DEVKITPRO/portlibs/switch/lib` - `DEVKITPRO/libnx/lib` -- `DEVKITPRO/portlibs/switch/include` - `DEVKITPRO/libnx/include` +OR you must specify a valid libnx path and/or devkitpro path to the `switch_build` utility: -##Install +```bash +switch_build --libnxPath:"C:\devkitPro\libnx" --author:"Joey" --version:"1.0.0" .\examples\accounts\account_ex.nim +# OR +switch_build --devkitProPath:"C:\devkitPro" --author:"Joey" --version:"1.0.0" .\examples\accounts\account_ex.nim +``` + +## Install Simply run ```bash # Because of a bug in nimble right now, you must install this first! -nimble install "https://github.com/jyapayne/nimgenEx#head" +nimble install nimgen@#head nimble install ``` diff --git a/config.nims b/config.nims deleted file mode 100644 index dc3dbe4..0000000 --- a/config.nims +++ /dev/null @@ -1,4 +0,0 @@ -switch("passC", "-I" & thisDir() & "/src/libnx/wrapper/nx/include") -switch("passL", "-specs="&thisDir()&"/src/libnx/wrapper/nx/switch.specs -L"&thisDir()&"/src/libnx/wrapper/nx/lib -lnx") -#switch("passC", "-I$DEVKITPRO/libnx/include") -#switch("passL", "-specs=$DEVKITPRO/libnx/switch.specs -L$DEVKITPRO/libnx/lib -lnx") diff --git a/examples/accounts/account_ex.nim b/examples/accounts/account_ex.nim index b73216c..b6a15ab 100644 --- a/examples/accounts/account_ex.nim +++ b/examples/accounts/account_ex.nim @@ -2,7 +2,7 @@ import sets, strutils import libnx/[graphics, console, account, input, app] import libnx/ext/integer128 -proc main() = +mainFunction: graphics.initDefault() console.init() @@ -43,5 +43,3 @@ proc main() = if ControllerKey.Plus in keysDown: break - -main() diff --git a/examples/helloworld/helloworld.nim b/examples/helloworld/helloworld.nim index a56a303..3796e3b 100644 --- a/examples/helloworld/helloworld.nim +++ b/examples/helloworld/helloworld.nim @@ -2,7 +2,7 @@ import sets import libnx/[graphics, console, app, input] -proc main() = +mainFunction: initDefault() console.init() @@ -15,5 +15,3 @@ proc main() = if ControllerKey.Plus in keysDown: break - -main() diff --git a/libnx.nimble b/libnx.nimble index 98fafcf..6724840 100644 --- a/libnx.nimble +++ b/libnx.nimble @@ -1,23 +1,39 @@ # Package -version = "0.1.6" +version = "0.2.2" author = "Joey Payne" description = "Nintendo Switch library libnx for Nim." license = "The Unlicense" srcDir = "src" +import distros + +var prefix = "" +var username = getEnv("USER") +if detectOs(Windows): + prefix = "cmd /c " + username = getEnv("USERNAME") + # Deps -requires "nim >= 0.18.1", "https://github.com/genotrance/nimgen#head" -requires "https://github.com/jyapayne/switch-build#head" +requires "nim >= 0.18.1", "nimgen#dc9943a22c9c8f6a5a6a92f0055e1de4dfaf87d2" +requires "switch_build >= 0.1.3" task setup, "Download and generate bindings": echo "Building libnx..." - exec "nimgen libnxGen.cfg" + exec prefix & "nimgen libnxGen.cfg" task buildExamples, "Build switch examples": - exec "switch_build --libnxPath='" & thisDir() & "/src/libnx/wrapper/nx/' --author='jyapayne' --version='1.0.0' examples/helloworld/helloworld.nim" - exec "switch_build --libnxPath='" & thisDir() & "/src/libnx/wrapper/nx/' --author='jyapayne' --version='1.0.0' examples/accounts/account_ex.nim" + if detectOs(Windows): + let devkitPath = getEnv("DEVKITPRO") + if devkitPath == "" or not dirExists(devkitPath): + echo "You must set the DEVKITPRO environment variable to something valid!" + else: + exec prefix & "switch_build --libnxPath=\"" & devkitPath & "/libnx/\" --author=\"" & username & "\" --version=\"1.0.0\" examples/helloworld/helloworld.nim" + exec prefix & "switch_build --libnxPath=\"" & devkitPath & "/libnx/\" --author=\"" & username & "\" --version=\"1.0.0\" examples/accounts/account_ex.nim" + else: + exec prefix & "switch_build --libnxPath=\"" & thisDir() & "/src/libnx/wrapper/nx/\" --author=\"" & username & "\" --version=\"1.0.0\" examples/helloworld/helloworld.nim" + exec prefix & "switch_build --libnxPath=\"" & thisDir() & "/src/libnx/wrapper/nx/\" --author=\"" & username & "\" --version=\"1.0.0\" examples/accounts/account_ex.nim" before install: setupTask() diff --git a/libnxGen.cfg b/libnxGen.cfg index 3a35ed1..4404075 100644 --- a/libnxGen.cfg +++ b/libnxGen.cfg @@ -8,26 +8,63 @@ filter=lock "${output}/nx/include" "${output}/nx/include/switch" "${output}/nx/include/switch/arm" -"${output}/nx/include/switch/kernel" -"${output}/nx/include/switch/services" "${output}/nx/include/switch/audio" -"${output}/nx/include/switch/gfx" +"${output}/nx/include/switch/display" +"${output}/nx/include/switch/kernel" +"${output}/nx/include/switch/nvidia" "${output}/nx/include/switch/runtime" "${output}/nx/include/switch/runtime/util" "${output}/nx/include/switch/runtime/devices" +"${output}/nx/include/switch/services" "${DEVKITPRO}/devkitA64/aarch64-none-elf/include/" -"${DEVKITA64}/aarch64-none-elf/include/" [n.exclude] "${output}/nim.cfg" "${output}/config.nims" +[svc.h] +search = "PACKED" +replace = "" + +search.noreturn = "NORETURN" +replace.noreturn = "" + +defines=true + +[result.h] +defines = true + +[thread_context.h] +preprocess = false + +[hid.h] +defines = true +search.static_assert = "static_assert" +replace.static_assert = "// static_assert" +search.touch = "touchPosition" +replace.touch = "TouchPosition" + +[ipc.h] +defines = true + +[romfs_dev.h] +search = "romfs_" +replace = "Romfs_" + +[gfx.h] +defines = true + +[ioctl.h] +defines = true +search = "_NV_" +replace = "UNV_" + +search.nv = "__nv_" +replace.nv = "DUnv_" + [n.wildcard] wildcard.1 = "console.h" -rename = "$replace(console=con)" - -search = "_Bool" -replace = "bool" +rename = "$replace(console=cons)" wildcard.2 = "*.h" @@ -68,10 +105,8 @@ replace.cdecl = "cdecl" [n.prepare] git = "https://github.com/switchbrew/libnx" -execute = """ -cd ${output} -make -""" +execute-lin = """cd ${output}; make;""" +execute-mac = """cd ${output}; make;""" [n.post] reset=true @@ -81,56 +116,21 @@ create = """ --path:"../" --path:"../../" """ +noprocess=true [src/libnx/wrapper/config.nims] create = """ switch("passC", "-I" & thisDir() & "/nx/include") switch("passL", "-specs=" & thisDir() & "/nx/switch.specs -L" & thisDir() & "/nx/lib -lnx") """ - -[result.h] -defines = true - -[hid.h] -defines = true -search.static_assert = "static_assert" -replace.static_assert = "// static_assert" -search.touch = "touchPosition" -replace.touch = "TouchPosition" - -[ipc.h] -defines = true - -[romfs_dev.h] -search = "romfs_" -replace = "Romfs_" - -[gfx.h] -defines = true - -[ioctl.h] -defines = true -search = "_NV_" -replace = "UNV_" - -search.nv = "__nv_" -replace.nv = "DUnv_" - -[svc.h] -search = "PACKED" -replace = "" - -search.noreturn = "NORETURN" -replace.noreturn = "" - -defines=true -pipe = "vim -es +'g/^static inline.*{/norm f{d%r;' -es +%print -es +q! $file" +noprocess=true [switch.h] preprocess = true defines = true recurse = true + [types.nim] search.o = " uint8*" prepend.o = """ @@ -169,6 +169,26 @@ import libnx/ext/integer128 template BIT*(n): auto = (1.uint shl n) """ +[thread_context.nim] +search.timport = "../types" +replace.timport = "libnx/wrapper/types" + +prepend.o = """ +import libnx/ext/integer128 +""" + +search.cpuall = "RegisterGroup_CpuAll =" +comment.cpuall = 1 + +search.fpugprs = "RegisterGroup_FpuGprs =" +prepend.fpugprs = "RegisterGroup_CpuAll = BIT(0) or BIT(1), ## /< All CPU registers." + +search.fpuall = "RegisterGroup_FpuGprs or RegisterGroup_FpuSprs" +replace.fpuall = "BIT(2) or BIT(3)" + +search.groupall = "RegisterGroup_CpuAll or RegisterGroup_FpuAll" +replace.groupall = "BIT(0) or BIT(1) or BIT(2) or BIT(3)" + [svc.nim] search.timport = "../types" replace.timport = "libnx/wrapper/types" @@ -313,7 +333,12 @@ prepend.o = """ import libnx/ext/integer128 """ -[con.nim] +[fence.nim] +prepend.o = """ +import libnx/wrapper/types +""" + +[cons.nim] search.o = "type\n" prepend.o = """ @@ -349,11 +374,16 @@ replace.threedmoo = "debugDevice_3DMOO*" search.timport = "../types" replace.timport = "libnx/wrapper/types" +search.fimport = "../nvidia/fence" +replace.fimport = "libnx/wrapper/fence" + [romfs_dev.nim] search.timport = "../types" replace.timport = "libnx/wrapper/types" search.servimport = "../services/" replace.servimport = "libnx/wrapper/" +search.o = "../libnx" +replace.o = "libnx" [n.sourcefile] "${output}/*.nim" diff --git a/src/libnx/account.nim b/src/libnx/account.nim index 4cc63ee..aa46b36 100644 --- a/src/libnx/account.nim +++ b/src/libnx/account.nim @@ -53,7 +53,7 @@ proc init() = if code.failed: raiseEx( AccountInitError, - "Error, account api could not be initialized: " & code.description + "Error, account api could not be initialized", code ) enabled = true @@ -88,7 +88,7 @@ proc getImageSize*(profile: AccountProfile): int = result = 0 let code = accountProfileGetImageSize(profile.unsafeAddr, res.addr).newResult if code.failed: - raiseEx(AccountImageSizeError, "Error, could not get image size: " & code.description) + raiseEx(AccountImageSizeError, "Error, could not get image size", code) result = res.int @@ -99,7 +99,7 @@ proc imageSize*(user: User): int = let res = accountProfileGetImageSize(prof.addr, size.addr).newResult if res.failed: - raiseEx(AccountImageSizeError, "Error, could not get image size: " & res.description) + raiseEx(AccountImageSizeError, "Error, could not get image size", res) result = size.int @@ -108,7 +108,7 @@ proc getProfileHelper(userID: u128): AccountProfile = let res = accountGetProfile(result.addr, userID).newResult if res.failed: - raiseEx(AccountUserProfileError, "Error, could not get user profile: " & res.description) + raiseEx(AccountUserProfileError, "Error, could not get user profile", res) proc loadImage*(user: User): AccountImage = @@ -128,7 +128,7 @@ proc loadImage*(user: User): AccountImage = if res.failed: prof.close() - raiseEx(AccountImageLoadError, "Error, could not load image: " & res.description) + raiseEx(AccountImageLoadError, "Error, could not load image", res) prof.close() @@ -152,7 +152,7 @@ proc getUser*(userID: u128): User = let res = accountProfileGet(prof.addr, userData.addr, profBase.addr).newResult if res.failed: - raiseEx(AccountUserDataError, "Error, could not get user data: " & res.description) + raiseEx(AccountUserDataError, "Error, could not get user data", res) result.username = profBase.username.join("") result.lastEdited = profBase.lastEditTimestamp @@ -173,7 +173,7 @@ proc getActiveUser*(): User = var res = accountGetActiveUser(userID.addr, selected.addr).newResult if res.failed: - raiseEx(AccountActiveUserError, "Error, could not get active user ID: " & res.description) + raiseEx(AccountActiveUserError, "Error, could not get active user ID", res) if not selected: raiseEx(AccountUserNotSelectedError, "No user currently selected!") @@ -189,7 +189,7 @@ proc getActiveUser*(): User = res = accountProfileGet(prof.addr, userData.addr, profBase.addr).newResult if res.failed: - raiseEx(AccountUserDataError, "Error, could not get user data: " & res.description) + raiseEx(AccountUserDataError, "Error, could not get user data", res) result.username = profBase.username.join("") result.lastEdited = profBase.lastEditTimestamp @@ -209,7 +209,7 @@ proc getProfile*(user: User): Profile = if res.failed: raiseEx( AccountUserProfileError, - "Error, could not get account profile: " & res.description + "Error, could not get account profile", res ) result.service = newService(prof.s) @@ -224,7 +224,7 @@ proc getUserCount*(): int32 = if res.failed: raiseEx( AccountUserCountError, - "Error, could not get user count: " & res.description + "Error, could not get user count", res ) result = count @@ -247,7 +247,7 @@ proc listAllUsers*(): seq[User] = if res.failed: raiseEx( AccountUserListError, - "Error, could not list users: " & res.description + "Error, could not list users", res ) for i in 0 ..< usersReturned.int: diff --git a/src/libnx/app.nim b/src/libnx/app.nim index e94e192..7934d59 100644 --- a/src/libnx/app.nim +++ b/src/libnx/app.nim @@ -1,8 +1,40 @@ -import libnx/graphics, libnx/wrapper/hid, libnx/wrapper/applet +import libnx/graphics, libnx/input, libnx/wrapper/applet + +template mainFunction*(code: untyped): untyped = + proc main() = + try: + code + except: + let e = getCurrentException() + echo "" + echo e.getStackTrace() + echo getCurrentExceptionMsg() + echo "" + echo "Your program has crashed. Press + on Controller 1 to exit safely." + echo "" + + while appletMainLoop(): + scanInput() + + let keysDown = keysDown(Controller.P1_AUTO) + + if ControllerKey.Plus in keysDown: + break + + flushBuffers() + swapBuffers() + waitForVSync() + try: + graphics.exit() + quit(0) + except: + quit(0) + + main() template mainLoop*(code: untyped): untyped = while appletMainLoop(): - hidScanInput() + scanInput() code diff --git a/src/libnx/config.nims b/src/libnx/config.nims deleted file mode 100644 index b83d14a..0000000 --- a/src/libnx/config.nims +++ /dev/null @@ -1,4 +0,0 @@ -switch("passC", "-I" & thisDir() & "/wrapper/nx/include") -switch("passL", "-specs=" & thisDir() & "/wrapper/nx/switch.specs -L" & thisDir() & "/wrapper/nx/lib -lnx") -#switch("passC", "-I$DEVKITPRO/libnx/include") -#switch("passL", "-specs=$DEVKITPRO/libnx/switch.specs -L$DEVKITPRO/libnx/lib -lnx") diff --git a/src/libnx/console.nim b/src/libnx/console.nim index 3747d88..b075146 100644 --- a/src/libnx/console.nim +++ b/src/libnx/console.nim @@ -1,6 +1,6 @@ -import libnx/wrapper/con +import macros, strutils, sets +import libnx/wrapper/cons import libnx/utils -import macros, strutils type @@ -37,18 +37,19 @@ type tabSize*: int fg*: int bg*: int - flags*: set[Style] + flags*: HashSet[Style] printCharCallback*: PrintCallback initialised*: bool DebugDevice* {.size: sizeof(cint), pure.} = enum Null, Service, Console, ThreeDMOO +var currentConsole {.threadvar.}: Console + proc toConsole(pconsole: ptr PrintConsole): Console = result = new(Console) result.pcon = pconsole result.font = pconsole.font - result.cursorX = pconsole.cursorX result.frameBuffer = cast[ptr UncheckedArray[uint32]](pconsole.frameBuffer) result.frameBuffer2 = cast[ptr UncheckedArray[uint32]](pconsole.frameBuffer2) result.cursorX = pconsole.cursorX @@ -64,7 +65,7 @@ proc toConsole(pconsole: ptr PrintConsole): Console = result.tabSize = pconsole.tabSize result.fg = pconsole.fg result.bg = pconsole.bg - result.flags = {} + result.flags = initSet[Style]() result.pcon.PrintChar = proc (con: pointer, c: cint): bool {.cdecl.} = let console = cast[ptr PrintConsole](con).toConsole() @@ -86,20 +87,21 @@ proc setWindow*(console: Console, x, y, width, height: int) = console.windowY = console.pcon.windowY.int proc getDefault*(): Console = + ## Gets the default console with default values let pcon = consoleGetDefault() result = pcon.toConsole() proc select*(console: Console): Console = - consoleSelect(console.pcon).toConsole() + currentConsole = consoleInit(console.pcon).toConsole() + return currentConsole -proc init*(console: Console = nil): Console {.discardable.} = - var newCon = console - if newCon.isNil: - newCon = new(Console) +proc init*(console: Console): Console {.discardable.} = + currentConsole = consoleInit(console.pcon).toConsole() + return currentConsole - let pcon = consoleInit(newCon.pcon) - newCon = pcon.toConsole() - return newCon +proc init*(): Console {.discardable.} = + currentConsole = consoleInit(nil).toConsole() + return currentConsole proc debugInit*(device: DebugDevice) = if device == ThreeDMOO: @@ -110,17 +112,17 @@ proc debugInit*(device: DebugDevice) = proc clear*() = consoleClear() -var printPos: tuple[row: int, col: int] = (0, 0) - -proc setPrintPos*(pos: tuple[row: int, col: int]) = - printPos = pos - proc printAt*(pos: tuple[row: int, col: int], args: varargs[string, `$`]) = - setPrintPos(pos) - echo ("\x1b[$#;$#H" % [$pos[0], $pos[1]]), args.join("") + echo CONSOLE_ESC("2K"), (CONSOLE_ESC("$#;$#H") % [$pos.row, $pos.col]), args.join("") + currentConsole.pcon.cursorX = pos.col.int32 + currentConsole.pcon.cursorY = pos.row.int32 + currentConsole.cursorX = pos.col + currentConsole.cursorY = pos.row proc print*(args: varargs[string, `$`]) = - ## Will print at the previously set printPos using ``printAt`` or ``setPrintPos`` + ## Will print at the previously set printPos using ``printAt`` ## and then increment the row by one + let + pcon = currentConsole.pcon + printPos = (pcon.cursorY.int+1, pcon.cursorX.int) printAt printPos, args - printPos.row += 1 diff --git a/src/libnx/graphics.nim b/src/libnx/graphics.nim index 668ab0f..eedc9a2 100644 --- a/src/libnx/graphics.nim +++ b/src/libnx/graphics.nim @@ -2,10 +2,12 @@ import strutils import libnx/wrapper/types, libnx/wrapper/gfx, + libnx/results, libnx/utils type GraphicsError* = object of Exception + GraphicsInitError* = object of GraphicsError InitResolutionError* = object of GraphicsError CropBoundsError* = object of GraphicsError @@ -53,7 +55,12 @@ var enabled = false ## proc initDefault*() = if not enabled: - gfxInitDefault() + let code = gfxInitDefault().newResult + if code.failed: + raiseEx( + GraphicsInitError, + "Error, graphics could not be initialized", code + ) enabled = true ## * @@ -184,10 +191,6 @@ proc getFramebuffer*(): Framebuffer = ## / Sets the \ref GfxMode. proc setMode*(mode: GfxMode) = gfxSetMode(gfx.GfxMode(mode)) -## / Controls whether a vertical-flip is done when determining the pixel-offset within -## the actual framebuffer. By default this is enabled. -proc setDrawFlip*(enabled: bool) = gfxSetDrawFlip(enabled) - ## / Configures transform. See the NATIVE_WINDOW_TRANSFORM_* enums in buffer_producer.h. ## The default is NATIVE_WINDOW_TRANSFORM_FLIP_V. proc configureTransform*(transform: BufferTransform) = diff --git a/src/libnx/input.nim b/src/libnx/input.nim index af28149..68f5916 100644 --- a/src/libnx/input.nim +++ b/src/libnx/input.nim @@ -26,136 +26,6 @@ type VibrationInitError* = object of InputError ControllerMergeError* = object of InputError - ####################### Shared memory data ################################ - TouchScreenHeader* = ref object - timestampTicks*: uint64 - numEntries*: uint64 - latestEntry*: uint64 - maxEntryIndex*: uint64 - timestamp*: uint64 - - TouchScreenEntryHeader* = ref object - timestamp*: uint64 - numTouches*: uint64 - - TouchScreenEntryTouch* = ref object - timestamp*: uint64 - padding*: uint32 - touchIndex*: uint32 - x*: uint32 - y*: uint32 - diameterX*: uint32 - diameterY*: uint32 - angle*: uint32 - padding2*: uint32 - - TouchScreenEntry* = ref object - header*: TouchScreenEntryHeader - touches*: Buffer[HidTouchScreenEntryTouch] - unk*: uint64 - - TouchScreen* = ref object - header*: TouchScreenHeader - entries*: Buffer[HidTouchScreenEntry] - padding*: Buffer[uint8] - - MouseHeader* = ref object - timestampTicks*: uint64 - numEntries*: uint64 - latestEntry*: uint64 - maxEntryIndex*: uint64 - - -type - MouseEntry* = ref object - timestamp*: uint64 - timestamp2*: uint64 - position*: MousePosition - buttons*: uint64 - - -type - Mouse* = ref object - header*: MouseHeader - entries*: Buffer[MouseEntry] - padding*: Buffer[uint8] - - KeyboardHeader* = ref object - timestampTicks*: uint64 - numEntries*: uint64 - latestEntry*: uint64 - maxEntryIndex*: uint64 - - KeyboardEntry* = ref object - timestamp*: uint64 - timestamp2*: uint64 - modifier*: uint64 - keys*: Buffer[uint32] - - - KeyboardSection* = ref object - header*: KeyboardHeader - entries*: array[17, KeyboardEntry] - padding*: array[0x00000028, uint8] - - ControllerMAC* = object - timestamp*: uint64 - mac*: array[0x00000008, uint8] - unk*: uint64 - timestamp2*: uint64 - - ControllerHeader* = object - `type`* {.importc: "type".}: uint32 - isHalf* {.importc: "isHalf".}: uint32 - singleColorsDescriptor* {.importc: "singleColorsDescriptor".}: uint32 - singleColorBody* {.importc: "singleColorBody".}: uint32 - singleColorButtons* {.importc: "singleColorButtons".}: uint32 - splitColorsDescriptor* {.importc: "splitColorsDescriptor".}: uint32 - leftColorBody* {.importc: "leftColorBody".}: uint32 - leftColorButtons* {.importc: "leftColorButtons".}: uint32 - rightColorBody* {.importc: "rightColorBody".}: uint32 - rightColorbuttons* {.importc: "rightColorbuttons".}: uint32 - - - ControllerLayoutHeader* = object - timestampTicks* {.importc: "timestampTicks".}: uint64 - numEntries* {.importc: "numEntries".}: uint64 - latestEntry* {.importc: "latestEntry".}: uint64 - maxEntryIndex* {.importc: "maxEntryIndex".}: uint64 - - - HidControllerInputEntry* = object - timestamp* {.importc: "timestamp".}: uint64 - timestamp_2* {.importc: "timestamp_2".}: uint64 - buttons* {.importc: "buttons".}: uint64 - joysticks* {.importc: "joysticks".}: array[JOYSTICK_NUM_STICKS, JoystickPosition] - connectionState* {.importc: "connectionState".}: uint64 - - - ControllerLayoutSection* = ref object - header*: ControllerLayoutHeader - entries* {.importc: "entries".}: array[17, HidControllerInputEntry] - - - ControllerSection* = ref object - header* {.importc: "header".}: ControllerHeader - layouts* {.importc: "layouts".}: Buffer[ControllerLayoutSection] - unk_1*: Buffer[uint8] - macLeft*: HidControllerMAC - macRight*: HidControllerMAC - unk_2* {.importc: "unk_2".}: array[0x00000DF8, uint8] - - - InputSharedMemory* = ref object - header*: Buffer[uint8] - touchscreen*: TouchScreen - mouse*: Mouse - keyboard*: KeyboardSection - controllerSerials*: Buffer[uint8] - controllers*: Buffer[ControllerSection] - - ####################### END Shared memory data ################################ - VibrationDeviceInfo* = HidVibrationDeviceInfo VibrationValue* = HidVibrationValue @@ -165,7 +35,6 @@ type JoyconMode {.pure.} = enum Single, Dual - proc init*(): Result = hidInitialize().newResult proc exit*() = hidExit() proc reset*() = hidReset() @@ -421,7 +290,7 @@ proc initializeVibrationDevices*( if rc.failed: raiseEx( VibrationInitError, - "Could not init vibration for controller #$ with type #$" % + "Could not init vibration for controller $# with type $#" % [$controller, $ctype] ) for i in 0 ..< numDevices: diff --git a/src/libnx/results.nim b/src/libnx/results.nim index af76ef6..3c1ae26 100644 --- a/src/libnx/results.nim +++ b/src/libnx/results.nim @@ -1,3 +1,4 @@ +import strutils import libnx/wrapper/result, libnx/wrapper/types @@ -5,7 +6,7 @@ import type Module {.pure.} = enum - Invalid = 0, # This is just so the nim compiler is happy + Success = 0, Kernel = 1, Libnx = 345, LibnxNvidia = 348 @@ -13,16 +14,8 @@ type Result* = ref object code*: uint32 module*: string - description*: string - case kind*: Module - of Module.Kernel: - kernelError*: KernelError - of Module.Libnx: - libnxError*: LibnxError - of Module.LibnxNvidia: - libnxNvidiaError*: LibnxNvidiaError - else: - discard + kind*: Module + error*: string KernelError* {.pure.} = enum Timeout = 117 @@ -98,8 +91,6 @@ proc newResult*(code: uint32): Result = result = new(Result) result.code = code - if code.R_SUCCEEDED: - return let moduleCode = code.R_MODULE let module = Module(moduleCode) @@ -108,20 +99,18 @@ proc newResult*(code: uint32): Result = let descCode = code.R_DESCRIPTION - var description = "" + var error = "Unknown error: module: $# description: $#" % + [$moduleCode, $descCode] try: case module - of Module.Invalid: - discard + of Module.Success: + return of Module.Kernel: - result.kernelError = KernelError(descCode) - description = $result.kernelError + error = $KernelError(descCode) of Module.Libnx: - result.libnxError = LibnxError(descCode) - description = $result.libnxError + error = $LibnxError(descCode) of Module.LibnxNvidia: - result.libnxNvidiaError = LibnxNvidiaError(descCode) - description = $result.libnxNvidiaError + error = $LibnxNvidiaError(descCode) except: echo "Converting to result failed: " & getCurrentExceptionMsg() echo "Code: " & $code @@ -130,4 +119,4 @@ proc newResult*(code: uint32): Result = echo "DescCode: " & $descCode result.module = $module - result.description = description + result.error = error diff --git a/src/libnx/utils.nim b/src/libnx/utils.nim index d18b135..dc11285 100644 --- a/src/libnx/utils.nim +++ b/src/libnx/utils.nim @@ -1,6 +1,11 @@ -import macros, strutils, math +import macros, strutils, math, hashes import libnx/results + +proc hash*(obj: SomeOrdinal): Hash = + ## Allow hashing of enums with holes + result = cast[int](obj) + proc size*(enumTy: typedesc): int = # Returns the number of items in a bit set enum log2(float64(enumTy.high)).int + 1 @@ -90,8 +95,8 @@ type data*: ptr UncheckedArray[T] template raiseEx*(ty: untyped, message: string, rc: Result): untyped = - ## Raise an exception with a result description - raise newException(ty, message & ": " & rc.description) + ## Raise an exception with a result error + raise newException(ty, message & ": " & rc.error) template raiseEx*(ty: untyped, message: string): untyped = ## Raise an exception diff --git a/src/nim.cfg b/src/nim.cfg deleted file mode 100644 index 72c20da..0000000 --- a/src/nim.cfg +++ /dev/null @@ -1,2 +0,0 @@ - ---path="../ext"