Add friendly graphics implementation
This commit is contained in:
parent
5c252fdd6e
commit
459787fd36
10 changed files with 269 additions and 23 deletions
|
|
@ -1,12 +1,12 @@
|
|||
import libnx/wrapper/gfx
|
||||
import libnx/graphics
|
||||
import libnx/wrapper/hid
|
||||
import libnx/wrapper/console
|
||||
import libnx/ext/integer128
|
||||
import libnx/account
|
||||
import libnx/utils
|
||||
import libnx/wrapper/types
|
||||
import libnx/app
|
||||
|
||||
proc main() =
|
||||
gfxInitDefault()
|
||||
initDefault()
|
||||
discard consoleInit(nil)
|
||||
|
||||
echo "\x1b[5;2H" & "Account info:"
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import libnx/wrapper/gfx
|
||||
import libnx/graphics
|
||||
import libnx/wrapper/console
|
||||
import libnx/wrapper/hid
|
||||
import libnx/utils
|
||||
import libnx/app
|
||||
|
||||
proc main() =
|
||||
gfxInitDefault()
|
||||
initDefault()
|
||||
discard consoleInit(nil)
|
||||
|
||||
echo "\x1b[17;20HHELLO FROM NIM"
|
||||
|
|
|
|||
14
libnxGen.cfg
14
libnxGen.cfg
|
|
@ -164,7 +164,7 @@ replace.uint64 = "uint64_t* = uint64"
|
|||
|
||||
search.import = "type\n"
|
||||
prepend.import = """
|
||||
include libnx/ext/integer128
|
||||
import libnx/ext/integer128
|
||||
template BIT*(n): auto = (1.uint shl n)
|
||||
"""
|
||||
|
||||
|
|
@ -299,3 +299,15 @@ import libnx/wrapper/binder
|
|||
[nxlink.nim]
|
||||
search.o = "var __nxlink"
|
||||
replace.o = "var DUnxlink"
|
||||
|
||||
[fs.nim]
|
||||
search.o = "import libnx"
|
||||
prepend.o = """
|
||||
import libnx/ext/integer128
|
||||
"""
|
||||
|
||||
[acc.nim]
|
||||
search.o = "import libnx"
|
||||
prepend.o = """
|
||||
import libnx/ext/integer128
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@ import strutils
|
|||
import libnx/wrapper/acc
|
||||
import libnx/results
|
||||
import libnx/wrapper/types
|
||||
import libnx/ext/integer128
|
||||
import libnx/service
|
||||
import libnx/utils
|
||||
|
||||
type
|
||||
AccountError* = object of Exception
|
||||
|
|
@ -32,9 +34,6 @@ type
|
|||
|
||||
var enabled = false
|
||||
|
||||
template raiseEx(ty: untyped, message: string) =
|
||||
raise newException(ty, message)
|
||||
|
||||
proc getService*(): Service =
|
||||
let serv = accountGetService()[]
|
||||
result = newService(serv)
|
||||
|
|
@ -46,7 +45,10 @@ proc init*() =
|
|||
|
||||
let code = accountInitialize().newResult
|
||||
if code.failed:
|
||||
raiseEx(AccountInitError, "Error, account api could not be initialized: " & code.description)
|
||||
raiseEx(
|
||||
AccountInitError,
|
||||
"Error, account api could not be initialized: " & code.description
|
||||
)
|
||||
enabled = true
|
||||
|
||||
proc exit*() =
|
||||
|
|
@ -59,7 +61,7 @@ proc exit*() =
|
|||
proc close*(profile: AccountProfile) =
|
||||
accountProfileClose(profile.unsafeAddr)
|
||||
|
||||
template withAccountService*(code: typed): typed =
|
||||
template withAccountService*(code: untyped): typed =
|
||||
init()
|
||||
code
|
||||
exit()
|
||||
|
|
|
|||
13
src/libnx/app.nim
Normal file
13
src/libnx/app.nim
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import libnx/graphics, libnx/wrapper/hid, libnx/wrapper/applet
|
||||
|
||||
template mainLoop*(code: untyped): untyped =
|
||||
while appletMainLoop():
|
||||
hidScanInput()
|
||||
|
||||
code
|
||||
|
||||
flushBuffers()
|
||||
swapBuffers()
|
||||
waitForVSync()
|
||||
|
||||
graphics.exit()
|
||||
200
src/libnx/graphics.nim
Normal file
200
src/libnx/graphics.nim
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
import strutils
|
||||
import
|
||||
libnx/wrapper/types,
|
||||
libnx/wrapper/gfx,
|
||||
libnx/utils
|
||||
|
||||
type
|
||||
GraphicsError* = object of Exception
|
||||
InitResolutionError* = object of GraphicsError
|
||||
CropBoundsError* = object of GraphicsError
|
||||
|
||||
RGBA8* = ref object
|
||||
red*: int
|
||||
green*: int
|
||||
blue*: int
|
||||
alpha*: int
|
||||
|
||||
Framebuffer* = ref object
|
||||
width*: uint32
|
||||
height*: uint32
|
||||
data*: Buffer[uint8]
|
||||
|
||||
BufferTransform* {.pure, size: sizeof(cint).} = enum
|
||||
FlipHorizontal = 0x1
|
||||
FlipVertical = 0x2
|
||||
Rotate180 = 0x3
|
||||
Rotate90 = 0x4
|
||||
Rotate270 = 0x7
|
||||
|
||||
## / Converts red, green, blue, and alpha components to packed RGBA8.
|
||||
proc packed*(rgba: RGBA8): int =
|
||||
gfx.RGBA8(rgba.red, rgba.green, rgba.blue, rgba.alpha)
|
||||
|
||||
## / Same as \ref RGBA8 except with alpha=0xff.
|
||||
proc maxAlpha*(r, g, b: int): RGBA8 =
|
||||
RGBA8(red:r, green:g, blue:b, alpha:0xFF)
|
||||
|
||||
## / GfxMode set by \ref gfxSetMode. The default is GfxMode_LinearDouble. Note that the
|
||||
## text-console (see console.h) sets this to GfxMode_TiledDouble.
|
||||
type
|
||||
GfxMode* {.size: sizeof(cint), pure.} = enum
|
||||
TiledSingle, ## /< Single-buffering with raw tiled (block-linear) framebuffer.
|
||||
TiledDouble, ## /< Double-buffering with raw tiled (block-linear) framebuffer.
|
||||
LinearDouble ## /< Double-buffering with linear framebuffer, which is
|
||||
## transferred to the actual framebuffer by \ref gfxFlushBuffers().
|
||||
|
||||
var enabled = false
|
||||
|
||||
## / Framebuffer pixel-format is RGBA8888, there's no known way to change this.
|
||||
## *
|
||||
## @brief Initializes the graphics subsystem.
|
||||
## @warning Do not use \ref viInitialize when using this function.
|
||||
##
|
||||
proc initDefault*() =
|
||||
if not enabled:
|
||||
gfxInitDefault()
|
||||
enabled = true
|
||||
|
||||
## *
|
||||
## @brief Uninitializes the graphics subsystem.
|
||||
## @warning Do not use \ref viExit when using this function.
|
||||
##
|
||||
proc exit*() =
|
||||
if enabled:
|
||||
gfxExit()
|
||||
enabled = false
|
||||
|
||||
## / Get the framebuffer width/height without crop.
|
||||
proc getFramebufferResolution*(): tuple[width: uint32, height: uint32] =
|
||||
var
|
||||
width: uint32
|
||||
height: uint32
|
||||
gfxGetFramebufferResolution(width.addr, height.addr)
|
||||
return (width: width, height: height)
|
||||
|
||||
## *
|
||||
## @brief Sets the resolution to be used when initializing the graphics subsystem.
|
||||
## @param[in] width Horizontal resolution, in pixels.
|
||||
## @param[in] height Vertical resolution, in pixels.
|
||||
## @note The default resolution is 720p.
|
||||
## @note This can only be used before calling \ref gfxInitDefault, this will use \ref
|
||||
## fatalSimple otherwise. If the input is 0, the default resolution will be used during
|
||||
## \ref gfxInitDefault. This sets the maximum resolution for the framebuffer, used
|
||||
## during \ref gfxInitDefault. This is also used as the current resolution when crop
|
||||
## isn't set. The width/height are reset to the default when \ref gfxExit is used.
|
||||
## @note Normally you should only use this when you need a maximum resolution larger
|
||||
## than the default, see above.
|
||||
## @note The width and height are aligned to 4.
|
||||
##
|
||||
proc initResolution*(width: uint32; height: uint32) =
|
||||
if not enabled:
|
||||
gfxInitResolution(width, height)
|
||||
else:
|
||||
raiseEx(InitResolutionError, "Cannot init resolution after graphics.initDefault!")
|
||||
|
||||
## / Wrapper for \ref gfxInitResolution with resolution=1080p. Use this if you want to
|
||||
## support 1080p or >720p in docked-mode.
|
||||
proc initResolution1080p*() =
|
||||
if not enabled:
|
||||
gfxInitResolutionDefault()
|
||||
else:
|
||||
raiseEx(InitResolutionError, "Cannot init resolution after graphics.initDefault!")
|
||||
|
||||
proc cropBoundsValid(left, top, right, bottom: uint32, width, height: uint32): bool =
|
||||
|
||||
if left < right and top > bottom:
|
||||
if left <= width and right <= width:
|
||||
if top <= height and bottom <= height:
|
||||
return true
|
||||
return false
|
||||
|
||||
## / Configure framebuffer crop, by default crop is all-zero. Use all-zero input to
|
||||
## reset to default. \ref gfxExit resets this to the default.
|
||||
## / When the input is invalid this returns without changing the crop data, this
|
||||
## includes the input values being larger than the framebuf width/height.
|
||||
## / This will update the display width/height returned by \ref gfxGetFramebuffer, with
|
||||
## that width/height being reset to the default when required.
|
||||
## / \ref gfxGetFramebufferDisplayOffset uses absolute x/y, it will not adjust for
|
||||
## non-zero crop left/top.
|
||||
## / The new crop config will not take affect with double-buffering disabled. When used
|
||||
## during frame-drawing, this should be called before \ref gfxGetFramebuffer.
|
||||
## / The right and bottom params are aligned to 4.
|
||||
proc setCrop*(left, top, right, bottom: uint32) =
|
||||
let (width, height) = getFramebufferResolution()
|
||||
if not cropBoundsValid(left, top, right, bottom, width, height):
|
||||
raiseEx(
|
||||
CropBoundsError,
|
||||
"The crop bounds are outside the frame buffer limits of w: $#, h:$#" %
|
||||
[$width, $height]
|
||||
)
|
||||
gfxConfigureCrop(left.s32, top.s32, right.s32, bottom.s32)
|
||||
|
||||
proc resetCrop*() =
|
||||
setCrop(0, 0, 0, 0)
|
||||
|
||||
## / Wrapper for \ref gfxConfigureCrop. Use this to set the resolution, within the
|
||||
## bounds of the maximum resolution. Use all-zero input to reset to default.
|
||||
proc setCropResolution*(width, height: uint32) =
|
||||
gfxConfigureResolution(width.s32, height.s32)
|
||||
|
||||
## / If enabled, \ref gfxConfigureResolution will be used with the input resolution for
|
||||
## the current OperationMode. Then \ref gfxConfigureResolution will automatically be
|
||||
## used with the specified resolution each time OperationMode changes.
|
||||
proc setAutoResolution*(enable: bool, handheldWidth,
|
||||
handheldHeight, dockedWidth,
|
||||
dockedHeight: uint32) =
|
||||
gfxConfigureAutoResolution(
|
||||
enable, handheldWidth.s32, handheldHeight.s32, dockedWidth.s32, dockedHeight.s32
|
||||
)
|
||||
|
||||
## / Wrapper for \ref gfxConfigureAutoResolution. handheld_resolution=720p,
|
||||
## docked_resolution={all-zero for using current maximum resolution}.
|
||||
proc setAutoResolutionDefault*(enable: bool) =
|
||||
gfxConfigureAutoResolutionDefault(enable)
|
||||
|
||||
## / Waits for vertical sync.
|
||||
proc waitForVsync*() = gfxWaitForVSync()
|
||||
|
||||
## / Swaps the framebuffers (for double-buffering).
|
||||
proc swapBuffers*() = gfxSwapBuffers()
|
||||
|
||||
## / Use this to get the actual byte-size of the framebuffer for use with memset/etc.
|
||||
proc getFramebufferSize*(): int = gfxGetFramebufferSize().int
|
||||
|
||||
## / Get the current framebuffer address, with optional output ptrs for the display
|
||||
## framebuffer width/height. The display width/height is adjusted by \ref
|
||||
## gfxConfigureCrop and \ref gfxConfigureResolution.
|
||||
proc getFramebuffer*(): Framebuffer =
|
||||
result = new(Framebuffer)
|
||||
let size = getFramebufferSize()
|
||||
let frameBuf = gfxGetFrameBuffer(
|
||||
result.width.addr,
|
||||
result.height.addr
|
||||
)
|
||||
let arr = cast[ptr UncheckedArray[uint8]](frameBuf)
|
||||
result.data = Buffer[uint8](len: size, data: arr)
|
||||
|
||||
## / 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) =
|
||||
gfxConfigureTransform(transform.uint32)
|
||||
|
||||
## / Flushes the framebuffer in the data cache. When \ref GfxMode is
|
||||
## GfxMode_LinearDouble, this also transfers the linear-framebuffer to the actual
|
||||
## framebuffer.
|
||||
proc flushBuffers*() = gfxFlushBuffers()
|
||||
|
||||
## / Use this to get the pixel-offset in the framebuffer. Returned value is in pixels,
|
||||
## not bytes.
|
||||
## / This implements tegra blocklinear, with hard-coded constants etc.
|
||||
## / Do not use this when \ref GfxMode is GfxMode_LinearDouble.
|
||||
proc getFramebufferDisplayOffset*(x: uint32; y: uint32): uint32 =
|
||||
gfxGetFrameBufferDisplayOffset(x, y)
|
||||
|
|
@ -1,13 +1,30 @@
|
|||
import libnx/wrapper/gfx, libnx/wrapper/hid, libnx/wrapper/applet
|
||||
|
||||
template mainLoop*(code: untyped): untyped =
|
||||
while appletMainLoop():
|
||||
hidScanInput()
|
||||
|
||||
code
|
||||
type
|
||||
BufferError* = object of Exception
|
||||
BufferIndexError* = object of BufferError
|
||||
|
||||
gfxFlushBuffers()
|
||||
gfxSwapBuffers()
|
||||
gfxWaitForVSync()
|
||||
Buffer*[T] = ref object
|
||||
len*: int
|
||||
data*: ptr UncheckedArray[T]
|
||||
|
||||
gfxExit()
|
||||
template raiseEx*(ty: untyped, message: string): untyped =
|
||||
raise newException(ty, message)
|
||||
|
||||
proc `[]`[T](buff: Buffer[T], index: int): T =
|
||||
if index > (buff.len - 1):
|
||||
raiseEx(
|
||||
BufferIndexError,
|
||||
"Index: $# is greater than buffer length: $#!" % [$index, $buff.len]
|
||||
)
|
||||
|
||||
result = buff.data[][index]
|
||||
|
||||
proc `[]=`[T](buff: Buffer[T], index: int, value: T) =
|
||||
if index > (buff.len - 1):
|
||||
raiseEx(
|
||||
BufferIndexError,
|
||||
"Index: $# is greater than buffer length: $#!" % [$index, $buff.len]
|
||||
)
|
||||
|
||||
buff.data[][index] = value
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import strutils
|
||||
import ospaths
|
||||
const headeracc = currentSourcePath().splitPath().head & "/nx/include/switch/services/acc.h"
|
||||
import libnx/ext/integer128
|
||||
import libnx/wrapper/types
|
||||
import libnx/wrapper/sm
|
||||
type
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import strutils
|
||||
import ospaths
|
||||
const headerfs = currentSourcePath().splitPath().head & "/nx/include/switch/services/fs.h"
|
||||
import libnx/ext/integer128
|
||||
import libnx/wrapper/types
|
||||
import libnx/wrapper/sm
|
||||
const
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import strutils
|
||||
import ospaths
|
||||
const headertypes = currentSourcePath().splitPath().head & "/nx/include/switch/types.h"
|
||||
include libnx/ext/integer128
|
||||
import libnx/ext/integer128
|
||||
template BIT*(n): auto = (1.uint shl n)
|
||||
type
|
||||
u8* = uint8
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue