From f11006b4dd7d7986692cb1b23d3643bf9e8df036 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Fri, 9 Dec 2022 20:58:14 -0700 Subject: [PATCH] Make results, account, service compile --- .gitignore | 4 + src/libnx/account.nim | 49 ++++---- src/libnx/results.nim | 11 +- src/libnx/service.nim | 31 ++--- src/libnx/wrapper/switch/services/acc.nim | 45 ++++--- src/libnx/wrapper/switch/sf/service.nim | 147 +++++++++++----------- 6 files changed, 132 insertions(+), 155 deletions(-) diff --git a/.gitignore b/.gitignore index 754a011..5d7a326 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ +* +!*/ +!*.* + nimcache/ # Swap [._]*.s[a-v][a-z] diff --git a/src/libnx/account.nim b/src/libnx/account.nim index aa46b36..bbada5c 100644 --- a/src/libnx/account.nim +++ b/src/libnx/account.nim @@ -1,7 +1,7 @@ import strutils -import libnx/wrapper/acc +import libnx/wrapper/switch/services/acc import libnx/results -import libnx/wrapper/types +import libnx/wrapper/switch/types import libnx/ext/integer128 import libnx/service import libnx/utils @@ -19,7 +19,7 @@ type AccountImageLoadError* = object of AccountError User* = ref object - id*: u128 + id*: AccountUid selected*: bool username*: string lastEdited*: uint64 @@ -32,24 +32,28 @@ type AccountImage* = ref object data: seq[uint8] - imageSize: int + imageSize: U32 + + +export AccountUid +export AccountServiceType var enabled = false proc getService*(): Service = - let serv = accountGetService()[] + let serv = accountGetServiceSession()[] result = newService(serv) -proc init() = +proc init(ty: AccountServiceType) = ## Initializes the account service. Should not ## be used in client code let service = getService() if service.isActive: return - let code = accountInitialize().newResult + let code = accountInitialize(ty).newResult if code.failed: raiseEx( AccountInitError, @@ -84,7 +88,7 @@ proc ensureEnabled() = proc getImageSize*(profile: AccountProfile): int = ensureEnabled() - var res = 0.csize + var res = 0.U32 result = 0 let code = accountProfileGetImageSize(profile.unsafeAddr, res.addr).newResult if code.failed: @@ -92,19 +96,19 @@ proc getImageSize*(profile: AccountProfile): int = result = res.int -proc imageSize*(user: User): int = +proc imageSize*(user: User): csize_t = ensureEnabled() var prof: AccountProfile - var size: csize + var size: U32 let res = accountProfileGetImageSize(prof.addr, size.addr).newResult if res.failed: raiseEx(AccountImageSizeError, "Error, could not get image size", res) - result = size.int + result = size.csize_t -proc getProfileHelper(userID: u128): AccountProfile = +proc getProfileHelper(userID: AccountUid): AccountProfile = let res = accountGetProfile(result.addr, userID).newResult if res.failed: @@ -115,7 +119,6 @@ proc loadImage*(user: User): AccountImage = ensureEnabled() result = new(AccountImage) let imSize = user.imageSize() - var size: csize var prof = getProfileHelper(user.id) @@ -137,7 +140,7 @@ proc userID*(user: User): string = $user.id -proc getUser*(userID: u128): User = +proc getUser*(userID: AccountUid): User = ensureEnabled() result = new(User) @@ -154,7 +157,7 @@ proc getUser*(userID: u128): User = if res.failed: raiseEx(AccountUserDataError, "Error, could not get user data", res) - result.username = profBase.username.join("") + result.username = profBase.nickname.join("") result.lastEdited = profBase.lastEditTimestamp result.iconID = userData.iconID result.iconBgColorID = userData.iconBackgroundColorID @@ -167,19 +170,15 @@ proc getActiveUser*(): User = ensureEnabled() result = new(User) var - userID: u128 = newUInt128(0,0) - selected: bool + userID: AccountUid - var res = accountGetActiveUser(userID.addr, selected.addr).newResult + var res = accountGetPreselectedUser(userID.addr).newResult if res.failed: raiseEx(AccountActiveUserError, "Error, could not get active user ID", res) - if not selected: - raiseEx(AccountUserNotSelectedError, "No user currently selected!") - result.id = userID - result.selected = selected + result.selected = true var prof: AccountProfile = getProfileHelper(userID) @@ -191,7 +190,7 @@ proc getActiveUser*(): User = if res.failed: raiseEx(AccountUserDataError, "Error, could not get user data", res) - result.username = profBase.username.join("") + result.username = profBase.nickname.join("") result.lastEdited = profBase.lastEditTimestamp result.iconID = userData.iconID result.iconBgColorID = userData.iconBackgroundColorID @@ -235,8 +234,8 @@ proc listAllUsers*(): seq[User] = result = @[] var - userIDs: array[ACC_USER_LIST_SIZE, u128] - usersReturned: csize + userIDs: array[ACC_USER_LIST_SIZE, AccountUid] + usersReturned: S32 let res = accountListAllUsers( userIDs[0].addr, diff --git a/src/libnx/results.nim b/src/libnx/results.nim index 3c1ae26..94469b3 100644 --- a/src/libnx/results.nim +++ b/src/libnx/results.nim @@ -1,7 +1,6 @@ import strutils import - libnx/wrapper/result, - libnx/wrapper/types + libnx/wrapper/switch/result type @@ -83,8 +82,8 @@ type IoctlFailed #///< Maps to Nvidia: 0x3000F -proc succeeded*(res: Result): bool = res.code.R_SUCCEEDED -proc failed*(res: Result): bool = res.code.R_FAILED +proc succeeded*(res: Result): bool {.inline.} = res.code.r_SUCCEEDED +proc failed*(res: Result): bool {.inline.} = res.code.r_FAILED proc newResult*(code: uint32): Result = ## Create a result from a libnx error code for friendlier syntax. @@ -92,12 +91,12 @@ proc newResult*(code: uint32): Result = result.code = code - let moduleCode = code.R_MODULE + let moduleCode = code.r_MODULE let module = Module(moduleCode) result.kind = module - let descCode = code.R_DESCRIPTION + let descCode = code.r_DESCRIPTION var error = "Unknown error: module: $# description: $#" % [$moduleCode, $descCode] diff --git a/src/libnx/service.nim b/src/libnx/service.nim index 8db2692..db370c9 100644 --- a/src/libnx/service.nim +++ b/src/libnx/service.nim @@ -1,17 +1,18 @@ import libnx/results, - libnx/wrapper/sm + libnx/wrapper/switch/services/sm, + libnx/wrapper/switch/sf/service, + libnx/wrapper/switch/types -from libnx/wrapper/types import Handle type Service* = ref object - serv: sm.Service + serv: service.Service -proc getSmService*(serv: Service): sm.Service = +proc getSmService*(serv: Service): service.Service = serv.serv -proc newService*(serv: sm.Service): Service = +proc newService*(serv: service.Service): Service = result = Service(serv: serv) proc isOverride*(service: Service): bool = @@ -54,24 +55,6 @@ proc objectId*(service: Service): uint32 = ## serviceGetObjectId(service.serv.addr) -proc close*(service: Service; objectId: uint32): Result = - ## * - ## @brief Closes a domain object by ID. - ## @param[in] s Service object, necessarily a domain or domain subservice. - ## @param object_id ID of the object to close. - ## @return Result code. - ## - serviceCloseObjectById(service.serv.addr, objectId).newResult - - -proc ipcDispatch*(service: Service): Result = - ## * - ## @brief Dispatches an IPC request to a service. - ## @param[in] s Service object. - ## @return Result code. - ## - serviceIpcDispatch(service.serv.addr).newResult - proc createService*(handle: Handle): Service = ## * ## @brief Creates a service object from an IPC session handle. @@ -91,7 +74,7 @@ proc createDomainSubservice*(parent: Service; objectId: uint32): Service = result = new(Service) serviceCreateDomainSubservice(result.serv.addr, parent.serv.addr, objectId) -proc convertToDomain*(service: Service): Result = +proc convertToDomain*(service: Service): results.Result = ## * ## @brief Converts a regular service to a domain. ## @param[in] s Service object. diff --git a/src/libnx/wrapper/switch/services/acc.nim b/src/libnx/wrapper/switch/services/acc.nim index 5bd9629..b3fd380 100644 --- a/src/libnx/wrapper/switch/services/acc.nim +++ b/src/libnx/wrapper/switch/services/acc.nim @@ -59,22 +59,23 @@ type AccountNetworkServiceAccountId* {.bycopy.} = object id*: U64 ## /< Id. - -## / Initialize account. - proc accountInitialize*(serviceType: AccountServiceType): Result {.cdecl, importc: "accountInitialize".} -## / Exit account. +## / Initialize account. proc accountExit*() {.cdecl, importc: "accountExit".} -## / Gets the Service object for the actual account service session. +## / Exit account. proc accountGetServiceSession*(): ptr Service {.cdecl, importc: "accountGetServiceSession".} -## / Get the total number of user profiles. +## / Gets the Service object for the actual account service session. proc accountGetUserCount*(userCount: ptr S32): Result {.cdecl, importc: "accountGetUserCount".} +## / Get the total number of user profiles. + +proc accountListAllUsers*(uids: ptr AccountUid; maxUids: S32; actualTotal: ptr S32): Result {. + cdecl, importc: "accountListAllUsers".} ## * ## @brief Get a list of all userIds. The returned list will never be larger than ACC_USER_LIST_SIZE. ## @param uids Pointer to array of userIds. @@ -82,52 +83,50 @@ proc accountGetUserCount*(userCount: ptr S32): Result {.cdecl, ## @param actual_total The actual total number of userIds found. ## -proc accountListAllUsers*(uids: ptr AccountUid; maxUids: S32; actualTotal: ptr S32): Result {. - cdecl, importc: "accountListAllUsers".} -## / Get the userId for the last opened user. - proc accountGetLastOpenedUser*(uid: ptr AccountUid): Result {.cdecl, importc: "accountGetLastOpenedUser".} -## / Get an AccountProfile for the specified userId. +## / Get the userId for the last opened user. proc accountGetProfile*(`out`: ptr AccountProfile; uid: AccountUid): Result {.cdecl, importc: "accountGetProfile".} -## / IsUserRegistrationRequestPermitted +## / Get an AccountProfile for the specified userId. proc accountIsUserRegistrationRequestPermitted*(`out`: ptr bool): Result {.cdecl, importc: "accountIsUserRegistrationRequestPermitted".} -## / TrySelectUserWithoutInteraction +## / IsUserRegistrationRequestPermitted proc accountTrySelectUserWithoutInteraction*(uid: ptr AccountUid; isNetworkServiceAccountRequired: bool): Result {.cdecl, importc: "accountTrySelectUserWithoutInteraction".} -## / Close the AccountProfile. +## / TrySelectUserWithoutInteraction proc accountProfileClose*(profile: ptr AccountProfile) {.cdecl, importc: "accountProfileClose".} -## / Get \ref AccountUserData and \ref AccountProfileBase for the specified profile, userdata is optional (can be NULL). +## / Close the AccountProfile. proc accountProfileGet*(profile: ptr AccountProfile; userdata: ptr AccountUserData; profilebase: ptr AccountProfileBase): Result {.cdecl, importc: "accountProfileGet".} -## / Get the icon image size. +## / Get \ref AccountUserData and \ref AccountProfileBase for the specified profile, userdata is optional (can be NULL). proc accountProfileGetImageSize*(profile: ptr AccountProfile; imageSize: ptr U32): Result {. cdecl, importc: "accountProfileGetImageSize".} -## / Load the JPEG profile icon, valid for both Miis and character icons. The output image_size is the same as the one from \ref accountProfileGetImageSize. +## / Get the icon image size. proc accountProfileLoadImage*(profile: ptr AccountProfile; buf: pointer; len: csize_t; imageSize: ptr U32): Result {.cdecl, importc: "accountProfileLoadImage".} -## / Gets the userId which was selected by the profile-selector applet (if any), prior to launching the currently running Application. -## / This gets the cached PreselectedUser loaded during accountInitialize, when PreselectedUser is available. +## / Load the JPEG profile icon, valid for both Miis and character icons. The output image_size is the same as the one from \ref accountProfileGetImageSize. proc accountGetPreselectedUser*(uid: ptr AccountUid): Result {.cdecl, importc: "accountGetPreselectedUser".} -## * -## @brief Checks whether the specified \ref AccountUid is valid/set (non-zero). -## @param[in] Uid \ref AccountUid -## +## / Gets the userId which was selected by the profile-selector applet (if any), prior to launching the currently running Application. +## / This gets the cached PreselectedUser loaded during accountInitialize, when PreselectedUser is available. proc accountUidIsValid*(uid: ptr AccountUid): bool {.inline, cdecl.} = + ## * + ## @brief Checks whether the specified \ref AccountUid is valid/set (non-zero). + ## @param[in] Uid \ref AccountUid + ## + return uid.uid[0] != 0 or uid.uid[1] != 0 diff --git a/src/libnx/wrapper/switch/sf/service.nim b/src/libnx/wrapper/switch/sf/service.nim index 373d02b..86c67f5 100644 --- a/src/libnx/wrapper/switch/sf/service.nim +++ b/src/libnx/wrapper/switch/sf/service.nim @@ -72,74 +72,68 @@ type outHandles*: ptr Handle - -## * -## @brief Returns whether a service has been initialized. -## @param[in] s Service object. -## @return true if initialized. -## - proc serviceIsActive*(s: ptr Service): bool {.inline, cdecl.} = + ## * + ## @brief Returns whether a service has been initialized. + ## @param[in] s Service object. + ## @return true if initialized. + ## return s.session != Invalid_Handle -## * -## @brief Returns whether a service is overriden in the homebrew environment. -## @param[in] s Service object. -## @return true if overriden. -## - proc serviceIsOverride*(s: ptr Service): bool {.inline, cdecl.} = + ## * + ## @brief Returns whether a service is overriden in the homebrew environment. + ## @param[in] s Service object. + ## @return true if overriden. + ## return serviceIsActive(s) and not s.ownHandle.bool and not s.objectId.bool -## * -## @brief Returns whether a service is a domain. -## @param[in] s Service object. -## @return true if a domain. -## - proc serviceIsDomain*(s: ptr Service): bool {.inline, cdecl.} = + ## * + ## @brief Returns whether a service is a domain. + ## @param[in] s Service object. + ## @return true if a domain. + ## return serviceIsActive(s) and s.ownHandle.bool and s.objectId.bool -## * -## @brief Returns whether a service is a domain subservice. -## @param[in] s Service object. -## @return true if a domain subservice. -## - proc serviceIsDomainSubservice*(s: ptr Service): bool {.inline, cdecl.} = + ## * + ## @brief Returns whether a service is a domain subservice. + ## @param[in] s Service object. + ## @return true if a domain subservice. + ## return serviceIsActive(s) and not s.ownHandle.bool and s.objectId.bool -## * -## @brief For a domain/domain subservice, return the associated object ID. -## @param[in] s Service object, necessarily a domain or domain subservice. -## @return The object ID. -## - proc serviceGetObjectId*(s: ptr Service): U32 {.inline, cdecl.} = + ## * + ## @brief For a domain/domain subservice, return the associated object ID. + ## @param[in] s Service object, necessarily a domain or domain subservice. + ## @return The object ID. + ## return s.objectId -## * -## @brief Creates a service object from an IPC session handle. -## @param[out] s Service object. -## @param[in] h IPC session handle. -## - proc serviceCreate*(s: ptr Service; h: Handle) {.inline, cdecl.} = + ## * + ## @brief Creates a service object from an IPC session handle. + ## @param[out] s Service object. + ## @param[in] h IPC session handle. + ## + s.session = h s.ownHandle = 1 s.objectId = 0 s.pointerBufferSize = 0 discard cmifQueryPointerBufferSize(h, addr(s.pointerBufferSize)) -## * -## @brief Creates a non-domain subservice object from a parent service. -## @param[out] s Service object. -## @param[in] parent Parent service. -## @param[in] h IPC session handle for this subservice. -## - proc serviceCreateNonDomainSubservice*(s: ptr Service; parent: ptr Service; h: Handle) {. inline, cdecl.} = + ## * + ## @brief Creates a non-domain subservice object from a parent service. + ## @param[out] s Service object. + ## @param[in] parent Parent service. + ## @param[in] h IPC session handle for this subservice. + ## + if h != Invalid_Handle: s.session = h s.ownHandle = 1 @@ -148,15 +142,15 @@ proc serviceCreateNonDomainSubservice*(s: ptr Service; parent: ptr Service; h: H else: s[] = Service() -## * -## @brief Creates a domain subservice object from a parent service. -## @param[out] s Service object. -## @param[in] parent Parent service, necessarily a domain or domain subservice. -## @param[in] object_id Object ID for this subservice. -## - proc serviceCreateDomainSubservice*(s: ptr Service; parent: ptr Service; objectId: U32) {. inline, cdecl.} = + ## * + ## @brief Creates a domain subservice object from a parent service. + ## @param[out] s Service object. + ## @param[in] parent Parent service, necessarily a domain or domain subservice. + ## @param[in] object_id Object ID for this subservice. + ## + if objectId != 0: s.session = parent.session s.ownHandle = 0 @@ -165,24 +159,24 @@ proc serviceCreateDomainSubservice*(s: ptr Service; parent: ptr Service; objectI else: s[] = Service() -## * -## @brief Hints the compiler that a service will always contain a domain object. -## @param[in] _s Service object. -## - template serviceAssumeDomain*(s: untyped): void = + ## * + ## @brief Hints the compiler that a service will always contain a domain object. + ## @param[in] _s Service object. + ## + while true: if not (s).objectId.bool: builtinUnreachable() if not 0: break -## * -## @brief Closes a service. -## @param[in] s Service object. -## proc serviceClose*(s: ptr Service) {.inline, cdecl.} = + ## * + ## @brief Closes a service. + ## @param[in] s Service object. + ## {.emit: "#if defined(NX_SERVICE_ASSUME_NON_DOMAIN)".} {.emit: " if (`s`->object_id)".} {.emit: " __builtin_unreachable();".} @@ -195,13 +189,12 @@ proc serviceClose*(s: ptr Service) {.inline, cdecl.} = {.emit: " }".} {.emit: " *`s` = (Service){};".} -## * -## @brief Clones a service. -## @param[in] s Service object. -## @param[out] out_s Output service object. -## - proc serviceClone*(s: ptr Service; outS: ptr Service): Result {.inline, cdecl.} = + ## * + ## @brief Clones a service. + ## @param[in] s Service object. + ## @param[out] out_s Output service object. + ## {.emit: "#if defined(NX_SERVICE_ASSUME_NON_DOMAIN)".} {.emit: " if (`s`->object_id)".} {.emit: " __builtin_unreachable();".} @@ -212,14 +205,14 @@ proc serviceClone*(s: ptr Service; outS: ptr Service): Result {.inline, cdecl.} {.emit: " `outS`->pointer_buffer_size = `s`->pointer_buffer_size;".} {.emit: " `result` = cmifCloneCurrentObject(`s`->session, &`outS`->session);".} -## * -## @brief Clones a service with a session manager tag. -## @param[in] s Service object. -## @param[in] tag Session manager tag (unused in current official server code) -## @param[out] out_s Output service object. -## proc serviceCloneEx*(s: ptr Service; tag: U32; outS: ptr Service): Result {.inline, cdecl.} = + ## * + ## @brief Clones a service with a session manager tag. + ## @param[in] s Service object. + ## @param[in] tag Session manager tag (unused in current official server code) + ## @param[out] out_s Output service object. + ## {.emit: "#if defined(NX_SERVICE_ASSUME_NON_DOMAIN)".} {.emit: " if (`s`->object_id)".} {.emit: " __builtin_unreachable();".} @@ -230,13 +223,13 @@ proc serviceCloneEx*(s: ptr Service; tag: U32; outS: ptr Service): Result {.inli {.emit: " `outS`->pointer_buffer_size = `s`->pointer_buffer_size;".} {.emit: " `result` = cmifCloneCurrentObjectEx(`s`->session, `tag`, &`outS`->session);".} -## * -## @brief Converts a regular service to a domain. -## @param[in] s Service object. -## @return Result code. -## proc serviceConvertToDomain*(s: ptr Service): Result {.inline, cdecl.} = + ## * + ## @brief Converts a regular service to a domain. + ## @param[in] s Service object. + ## @return Result code. + ## if not s.ownHandle.bool: ## For overridden services, create a clone first. var rc: Result = cmifCloneCurrentObjectEx(s.session, 0, addr(s.session))