GithubHelp home page GithubHelp logo

dragonminded / libnaomi Goto Github PK

View Code? Open in Web Editor NEW
31.0 4.0 4.0 21.12 MB

Toolchain and system library enabling hobby/homebrew software to be developed for the Sega Naomi platform.

License: The Unlicense

Python 7.33% Makefile 2.06% C 88.20% Assembly 1.62% Shell 0.75% C++ 0.04%

libnaomi's Introduction

Naomi Toolchain & Libraries

A minimal Naomi homebrew environment, very loosely based off of KallistiOS toolchain work but bare metal and implemented from the ground up on the Naomi. This assumes that you have a Linux computer with standard prerequisites for compiling gcc/newlib/binutils already installed as well as a working Python 3.6+ installation available. On Ubuntu that means having build-essential, texinfo and autoconf installed at minimum. In order to compile 3rd party libraries, you will also need standard archive utilities installed. At minimum, this includes unzip. The Naomi system library is minimal, but includes support for many POSIX features such as filesystems and basic pthreads. Support for all major built-in hardware is included, including JVS, EEPROM reading/writing, PowerVR 2D and 3D operations, built-in matrix and vector operations, reading and writing from the DIMM cartridge and communication with an external host through the net dimm. Additionally, a 3rdparty repository has been setup and a few ports are available. Both the system libraries and the 3rdparty repo will continue to get fleshed out.

Getting Started

To get started, create a directory named /opt/toolchains/naomi and copy the contents of the setup/ directory to it. This directory and the copied contents should be user-owned and user-writeable. Then, cd to /opt/toolchains/naomi and in order run ./download.sh (downloads toolchain sources), ./unpack.sh (unpacks the toolchain to be built), make (builds the toolchain and installs it in the correct directories), make gdb (builds gdb for SH-4 only) and finally ./cleanup.sh. If everything is successful, you should have a working compiler and C standard library as well as debugging tools. Now, every time you wish to use the toolchain, you should run source /opt/toolchains/naomi/env.sh to set up your local environment to use the tools you just build.

Next, you will need to set up the python virtualenv and compile the system libraries. For convenience the python virtualenv, libnaomi, libnaomimessage, libnaomisprite, libnaomisramfs, the on-target tests and the examples will all be built if you run make in the root directory of the repo. If you receive error messages about "Command not found", you have not activated your Naomi enviornment by running source /opt/toolchains/naomi/env.sh. Note that by default there are no 3rd party libraries installed and thus libnaomi support for things like font rendering and compressed messages is disabled. To enable 3rd party libraries, first run the above make to ensure that the base libraries are compiled properly and then run make -C 3rdparty install in the root directory which will fetch, configure, make and install all of the 3rd party libraries. Once that finishes, run make clean in the root of the repo and then re-run make in the root of the repo to rebuild libnaomi and the examples with 3rd party support. The resulting binary files in the various example directories as well as the on-target tests can be loaded in Demul or net booted to a Naomi to execute them.

Finally, once you are happy with everything, run make install from the root of the repository which will install libnaomi into the toolchain directory from the first paragraph. After doing this, you can create a project by basing off of the minimal/ example which will compile to the Naomi platform. Remember, if you get "Command not found" errors when trying to build your project, run source /opt/toolchains/naomi/env.sh to activate the environment.

Updating libnaomi

When libnaomi changes, you'll most likely want to pull those changes so you can use them in your project. Once you've gotten your toolchain setup and isntalled its an easy process. First, make sure that you've activated the Naomi enviornment with source /opt/toolchains/naomi/env.sh. Then, at the root of the repository, run git pull followed by make install. This should fetch everything that changed and rebuild the libraries for you to use. Note that if the compiler itself changes, you should follow the entire getting started section again. However, under most circumstances (such as new features, bugfixes to libnaomi or documentation improvements) you can simply make install to compile and update your toolchain.

Developing With libnaomi

It is recommended to base your project off of the the minimal hello world example in the minimal/ directory. You are free to write your own makefiles from scratch. However, lots of features are provided for you automatically when you base off of the minimal example. These include automatic dependency tracking (for source, header and library files used in your project), available tools for converting resources to includes, tools for converting images to texture and sprite formats, tools for building a ROMFS and the crucial ROM header creation tool. It also includes proper CFLAGS and LDFLAGS which ensures that your code actually compiles and links against libnaomi to create a working binary that can execute on a Naomi. Note that anything which is done in an example's makefile can also be done in your own makefile, so be sure to look at the examples for how to do just about everything.

Homebrew is welcome to make use of additional facilities that allow for redirecting stdout/stderr to the host console for debugging. Notably, the test executable that is generated out of the tests/ directory makes use of this to display the test results both on the Naomi and on the host's console. To intercept such messages, you can run /opt/toolchains/naomi/tools/stdioredirect and it will handle displaying anything that the target is sending to stdout or stderr using printf(...) or fprintf(stderr, ...) calls. Note that the homebrew program must link against libnaomimessage.a and initialize the console redirect hook for this to work properly. See the debugprint example for how to do this properly. If GDB debugging is too advanced for you this might be adequate for debugging your program when it is running on target.

For ease of tracking down program bugs, an exception handler is present which prints out the system registers, stack address and PC at the point of exception. For further convenience, debugging information is left in an elf file that resides in the build/ directory of an example you might be building or of any project based off of the minimal example discussed above. To locate the offending line of code when an exception is displayed, you can run /opt/toolchains/naomi/sh-elf/bin/sh-elf-addr2line --exe=build/naomi.elf <displayed PC address> and the function and line of code where the exception occurred will be displayed for you.

Additionally, libnaomi has GDB remote debugging support allowing you to attach to a program running on the Naomi and step through as well as debug the program. To debug your program, first activate the GDB server by running /opt/toolchains/naomi/tools/gdbserver and then run GDB with /opt/toolchains/naomi/sh-elf/bin/sh-elf-gdb build/naomi.elf. To attach to the target once GDB is running and has read symbols from your compiled program, type target remote :2345. If all is successful, your program will halt and you can examine your program in real-time on the target. If you are trying to track down an intermittent problem, you can connect and then continue. If your program crashes on the Naomi and displays an invariant or exception screen, GDB will be interrupted and you can examine stack traces and the locals of all threads. You can also connect and halt the execution of the program with Ctrl+C inside the GDB console and then single-step through code while examining locals. Note that you do not noeed to compile any support for this as GDB support is built into libnaomi.

Developing libnaomi Itself

libnaomi and the associated examples and tests are self-contained in the repo. You do not need to make install in order to test libnaomi inside the tests/ directory or in any of the examples. When adding a new feature to libnaomi you should consider whether that feature is critial to the operation of the Naomi itself. If it is, then the feature should go into libnaomi directly. If it is not, then a new library should be created much like libnaomimessage and libnaomisprite in order to keep the code somewhat clean. Note that in either case it is highly recommended to either create a new example showing how to use the code or augment an existing example to include use of the code you are adding. Also, whenever possible a test should be written in the tests/ directory to exercise the feature. These tests get run often in Demul and on a real Naomi so it is a good way to ensure that your code does not regress due to unrelated changes.

Extent of Support

libnaomi is the system library and assocated headers which provides all of the below features. It includes all the hardware drivers as well as the POSIX compatibility layer and C runtime support functions necessary to compile modern C or C++ code for the Naomi platform. The majority of the C stdlib is provided by a combination of GCC and newlib and the POSIX compatibility layer is provided by a combination of newlib and libnaomi. The C++ stdlib is provided by GCC and is bridged to various low-level libraries under the hood.

The audio system is robust and fairly complete. The AICA driver allows for up to 62 sounds to be registered and played back at-will, and two channels are reserved for a stereo ringbuffer which is writeable from the SH-4 side. This can be used to stream audio from a library that is decoding it, or for mixing your own sounds. If you wish, you can load your own AICA binary and use that instead but if you do this then the normal audio system in libnaomi will not be available. The audiotest example will show you the basics for how to use the audio system.

The cart system allows for full reading and writing to/from the cart. This works in tandem with any net dimm plugged into the system, so you can write data to the cart from the net dimm and read it on the Naomi and vice versa. This is used in the GDB driver to provide reliable bulk transfer of data. A small library for reading the cart header and parsing out the program's main and test entrypoint from it is also available. The carttest example will show you the basics for how to use the cart system.

The DIMM communication system implements the DIMM communication protocol that is used by the net dimm and the BIOS to peek/poke memory. By default, no handler for reading/writing system memory is installed but a default one can be installed. Alternatively, your own set of read/write callbacks can be implemented which are called in interrupt context when the net dimm is used to peek or poke memory. This is used both in the GDB driver to provide external interrupts and by thet message subsystem to pass small messages between the host and Naomi. The netdimm example will show you the basics for how to use the DIMM communication module, and the debugprint example shows how to use the include libnaomimessage library which sits on top of the DIMM communication system.

The EEPROM system is robust and complete, supporting full system and game section settings, automatic recovery of partially-written EEPROMs and full compatibility with the BIOS. The eepromtest example shows how to read and write the full EEPROM and the tests/test_eeprom.c test file shows how to use the high-level EEPROM library.

The GDB system is robust and fairly complete. It allows breakpoints to be set, single-stepping of code as well as memory and register reading and modification. It is fully integrated with the libnaomi thread system (and consequently pthreads) which allows you to inspect the stack, locals and running state of all active threads in realtime. This can be used in conjunction with the leftover naomi.elf file in the build/ directory of any example or any homebrew based off of the minimal makefile example to achieve source-level on-target debugging. It does not support memory watchpoints or some esoteric GDB features. There is no example for this as GDB is built into all examples.

The interrupt system is robust and fairly complete, supporting most critical HOLLY and system interrupts. This is mostly used by the microkernel to provide support for other systems such as the video, TA, GDB and thread systems. You will usually not interact directly with this system outside of the ATOMIC macros and then irq_disable() and irq_restore() in order to gain temporary exclusive access to the SH-4. There is no example for this as the microkernel is used by all examples.

The maple system is fairly complete but relies on the BIOS to initialize both the maple chip as well as the JVS interface. Because the BIOS (and commercial games) load their own code stub to the maple chip after a reset, libnaomi relies on the BIOS so as not to include a copyrighted binary blob in its distribution. In practice, this does not matter much since only the H BIOS allows for net booting and this is the only current method of achieving code execution on the system. Support is provided through the EEPROM system for accessing the maple-attached EEPROM, and a library is provided for polling for JVS controls. Only one player and two player setups have been tested with this approach and there are some reports of partial failure with some JVS devices, namely OpenJVS. The inputtest example will show you the basics for how to use the maple system.

Drivers for the built-in SH-4 matrix and vector instructions are provided in the matrix and vector subsystem. These together provide a set of libraries for manipulating the system matrix to perform affine and perspective transformations of sets of coordinates as well as calculating normals. While this system is complete, it is fairly barebones and quite low level. There is no higher-level 3D library available. The pvrtest example shows using these libraries for 3D and the tests/test_matrix.c and tests/test_vector.c test files show a variety of basic uses.

The POSIX system is fairly robust and includes a ROMFS as well as full filesystem and directory support. It also includes a partial pthreads implementation which is fully integrated with the thread system. Expect that if a POSIX function is defined it conforms to the POSIX spec. Several 3rdparty libraries have been ported successfully to the Naomi using this POSIX compatibility system. Note that the microkernel is much simpler than the Linux kernel and only supports system-level threads. As such, there is no support for the MMU and you should not expect more complex or esoteric features of pthreads to work. The carttest example shows how to initialize and use the ROMFS through standard file operations and the debugprint example shows how to use the stdio system from a host.

The RTC system is robust and complete and supports both reading and writing the system clock. This is also integrated into the POSIX system. Assuming you have your time set correctly in the BIOS, you should be able to read it from code using the RTC or the POSIX modules. The rtctest example will show you the basics for how to use the RTC system and the tests/test_rtc.c test shows how to use the low-level functions.

The video system is robust and fairly well-featured but quite low level. There is full support for software framebuffers including several helpful functions. There is also support for the TA/PowerVR system including several functions for setting up and managing displaylists as well as helper functions for rendering quads and triangle strips. In conjunction with the matrix and vector drivers this can be used to implement a full 3D game with textures and dynamic lighting. There is also helper code tied into the optionally-compiled freetype 3rdparty library which allows for both software and hardware-accelerated rendering of truetype fonts. Note that the PowerVR is very particular in how it wishes to receive displaylists so not all orders of operation between the framebuffer and PowerVR are possible. In general, it is recommended to draw your scene using the TA and then augment with any debugging console after the fact. The hellonaomi example shows off various software framebuffer functions, the pvrtest example shows off basic 3D support and the spritetest example shows off basic 2D support using the include libnaomisprite library which sits on top of the video system. The advancedpvrtest example shows off mixing multiple texture types as well as mixing hardware and software rendering for the same frame.

The thread system is robust and provides support for threading, mutexes, semaphores and global counters. It also supports high-priority RTOS-like waiting for things such as vblank, TA displaylist fill and rendering complete triggers. The basic threading support is also integrated with pthreads. Basic support for things like priority bands, recursive mutexes and priority bumping for critical events is included. The thread system is also integrated with GDB so you can look at the state of each thread when debugging or single-stepping. The included pthreads wrapper includes support for thread creation/updating/cancellation/destruction, mutexes, spinlocks, one-time init and thread-local storage. The threadtest example shows off the various features of the threading system and the pvrtest shows how to wait for PowerVR and vblank events to successfully render without screen tearing.

The timer system is robust and complete, supporting the three hardware timers that the SH-4 provides. This is mostly used by the microkernel to provide profiling and task preemption. You will generally not interact directly with this system outside of the profile_start() and profile_end() functions and the timer_wait() spinloop function. Because the SH-4 is so limited in hardware timers, they are multiplexed in software so that you can start many more of them for things such as key repeats or waiting for particular durations before updating animations. There is no example for the timer system but various examples such as hellonaomi use the timer system to calculate framerate and draw time per-frame.

Additional Docs

If you are looking for a great resource for programming, the first thing I would recommend is https://github.com/Kochise/dreamcast-docs which is mostly relevant to the Naomi. For memory maps and general low-level stuff, Mame's https://github.com/mamedev/mame/blob/master/src/mame/drivers/naomi.cpp is extremely valuable. Also the headers for various libnaomi modules contain descriptions for how to use the functions found within. And of course, you can look at the source code to the various examples to see some actual code.

libnaomi's People

Contributors

dragonminded avatar softdrink117 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

libnaomi's Issues

libmissing

before install lib
in Makfile.shared
libmissing failed on non english envroment

I changed
libmissing = $(shell LANG=C ${LD} -l$(1) 2>&1 | grep "cannot find" | wc -l)

or better ?

Best Practices for Adding Tools to Build Process

I've created a utility derived from your existing tools/sprite.py called palette.py, which is designed to ingest .gpl or .pal format palette files and construct color arrays that can be directly memcopied into the TA palette banks. .gpl and .pal are plaintext file formats that can be imported or exported from various graphics programs (GIMP, Aseprite, GraphicsGale, etc.), and there are also some online resources (such as lospec.com) that host palettes in these formats for download.

It does not require any additional Python dependencies, and I've tested it standalone using the libnaomi pyenv without any issues. It works in both RGBA1555 and RGBA8888 modes, and supports 16 or 256-color palettes.

However, I'm running into a lot of trouble trying to integrate it into the actual build chain for my project. I tried to follow the example of the other tools (added to the libnoami/tools and /opt/toolchains/naomi/tools/ directories, added PAL2C_FILE and PAL2C entries, added a PALOBJS patsubst to Makefile.shared, created build rules that call the program in the same style as those used in examples for sprite.py, etc.), but haven't had much luck; make keeps treating the files as if they are linker scripts.

If I manually run the tool to build palettes prior to running a build, everything works fine. It's just the actual automation and integration with make that seems to be the problem, and I'll admit the complexity of the build chain for this project is a bit beyond my current understanding.

It isn't clear to me if this is within the scope of libnaomi itself, so I didn't want to issue a PR (especially since there are still automation issues to sort out). But I've included the tool itself and the not-yet-functioning Makefile adjustments below.

Once again, thanks very much for any help you can provide!


palette.py

#! /usr/bin/env python3
import argparse
import io
import os
import os.path
import sys
import textwrap
from enum import Enum

# Converts a .GPL or .PAL palette file into a .c file that defines the palette as a uint32_t array.
# This can then be memcpy'd into a TA palette bank directly
# Adapted from https://github.com/DragonMinded/libnaomi/blob/main/tools/sprite.py
def main() -> int:
    parser = argparse.ArgumentParser(
        description="Utility for converting .GPL Palette files to C include style."
    )
    parser.add_argument(
        'file',
        metavar='FILE',
        type=str,
        help='The output file we should generate.',
    )
    parser.add_argument(
        'palette',
        metavar='PALETTE',
        type=str,
        help='The palette file we should use to generate the output file.',
    )
    parser.add_argument(
        '--mode',
        metavar='MODE',
        type=str,
        help=(
            'The mode of the palette data to construct. Should match the video mode you are initializing.'
            'Options are "RGBA1555" and "RGBA8888".'
        ),
    )
    parser.add_argument(
        '--trans',
        nargs='?',
        const=0,
        default=0,
        metavar='TRANS',
        type=int,
        help=( 
            'The index of the transparent color in the palette. GPL and PAL palettes do not record transparency,'
            'so this must be passed as an option when converting. Default is 0 if not specified.'
        ),
    )
    args = parser.parse_args()

    PaletteType = Enum('PaletteType', ['Unknown', 'GPL', 'PAL'])

    paletteColors = []
    paletteName = ""
    colorCount = -1

    paletteType = PaletteType.Unknown

    with open(args.palette, "rt") as f:
        lines = f.readlines()

        for index, line in enumerate(lines, start=0):
            line = line.strip()
            
            # Make sure this is a valid GPL or PAL format file
            if index == 0:
                if line.lower().find("gimp palette") == 0:
                    paletteType = PaletteType.GPL
                    # print("Valid palette file")
                    continue
                elif line.lower().find("jasc-pal") == 0:
                    paletteType = PaletteType.PAL
                    continue
                else:
                    Exception(f"ERROR: Invalid or malformed palette file passed to palette.py! {args.plt}")

            # Parse GPL
            if paletteType == PaletteType.GPL:
                if line.find("Name:") != -1:
                    nameSplit = line.split(":")
                    paletteName = nameSplit[-1]
                    continue

                if line.find("Colors:") != -1:
                    colorCountSplit = line.split(":")
                    colorCount = int(colorCountSplit[-1])
                    continue

                # Ignore other commented lines
                if line.find("#") != -1:
                    continue
            
            # Parse PAL
            else:
                if index == 1:
                    continue
                if index == 2:
                    colorCount = int(line)
                    continue

            # Validate color count is either 16 or 256
            if colorCount != 16 and colorCount != 256:
                Exception(f"ERROR: Parsed color count does not align with supported NAOMI palette sizes! {colorCount} != 16 or 256")
            
            columns = line.split()
            if len(columns) >= 3:
                paletteColors.append([int(columns[0]), int(columns[1]), int(columns[2])])
                
    if colorCount != -1 and len(paletteColors) != colorCount:
        Exception(f"ERROR: Parsed color count does not match file declaration! {len(paletteColors)} != {colorCount}")

    # DEBUG: Print palette info
    # debug = "Parsed the following palette:\n"
    # debug += "Name: {0}\n".format(paletteName)
    # debug += "Colors: {0}\n".format(colorCount)
    # for pc in paletteColors:
    #     debug += "{0}\n".format(pc)
    # print(debug)

    # Convert the data to uint32 format, following the RGB1555 or RGB8888 macros:
    # #define RGB1555(r, g, b, a) ((((b) >> 3) & (0x1F << 0)) | (((g) << 2) & (0x1F << 5)) | (((r) << 7) & (0x1F << 10)) | (((a) << 8) & 0x8000))
    # #define RGB0888(r, g, b) (((b) & 0xFF) | (((g) << 8) & 0xFF00) | (((r) << 16) & 0xFF0000) | 0xFF000000)
    outColors = []
    mode = args.mode.lower()
    
    for index, pc in enumerate(paletteColors, start=0):
        alpha = 255
        if args.trans == index:
            alpha = 0
            
        if mode == "rgba1555": 
            outColors.append( (((pc[2] >> 3) & (0x1F << 0)) | ((pc[1] << 2) & (0x1F << 5)) | ((pc[0] << 7) & (0x1F << 10)) | ((alpha << 8) & 0x8000)) & 0xFFFFFFFF)
        elif mode == "rgba8888":
            outColors.append( (((pc[2] & 0xFF) << 0) | ((pc[1] & 0xFF) << 8) | ((pc[0] & 0xFF) << 16) | ((alpha & 0xFF) << 24)) & 0xFFFFFFFF)
        else:
            raise Exception(f"Unsupported depth {args.mode}!")
        

    rawSource = "".join(lines)

    name = os.path.basename(args.palette).replace('.', '_').replace('-', '_')

    outStr = [str(oc) for oc in outColors]

    cfile = f"""#include <stdint.h>

uint32_t __{name}_palette[{len(outStr)}] = {{
    {", ".join(outStr)}
}};
uint32_t *{name}_palette = __{name}_palette;

// Original {paletteType.name} file:
/*
{rawSource}
*/
    """

    with open(args.file, "w") as sfp:
        sfp.write(textwrap.dedent(cfile))

    return 0


if __name__ == "__main__":
    sys.exit(main())

Adjustments to Makefile.shared

... line 105:
# Set up various toolchain utilities.
PAL2C_FILE := ${TOOLS_DIR}palette.py
PAL2C := ${VENV_PYTHON3} ${PAL2C_FILE}

... line 169:
# Auto-compute objects based on sources we recognize. The rest of the sources will
# be assumed to be objects that we want to include.
CODEOBJS = $(patsubst %.cpp, build/%.o, $(patsubst %.s, build/%.o, $(patsubst %.c, build/%.o, ${SRCS})))
RAWOBJS = $(patsubst %.raw, build/%.o, ${CODEOBJS})
FONTOBJS = $(patsubst %.ttf, build/%.o, ${RAWOBJS})
IMGOBJS = $(patsubst %.jpg, build/%.o, $(patsubst %.png, build/%.o, ${FONTOBJS}))
PALOBJS = $(patsubst %.gpl, build/%.o, $(patsubst %.pal, build/%.o, ${IMGOBJS}))
OBJS = ${PALOBJS}

Buildrules for a project-specific Makefile

# Buildrules for Palette files for this project
build/%.o: %.gpl ${PAL2C_FILE}
	@mkdir -p $(dir $@)
	${PAL2C} build/$<.c --mode RGBA1555 $<
	${CC} -c build/$<.c -o $@

build/%.o: %.pal ${PAL2C_FILE}
	@mkdir -p $(dir $@)
	${PAL2C} build/$<.c --mode RGBA1555 $<
	${CC} -c build/$<.c -o $@

Trouble with `TA_PALETTE_CLUT4` Paletted Sprites

Hiya,

I wanted to try the paletted sprites feature, but I'm having trouble getting any functional results with the 16-color palette bank and TA_PALETTE_CLUT4 mode.

I've tried various permutations of manually defining palettes, INTENSITY4 and INTENSITY8 image encoding, and even exporting graphics from different tools and working in different color modes.

At best, I've managed to get a single color from my manually defined palette to display, without respecting alpha or the gradation of the graphic asset.

There is an example of paletted textures and sprites in pvrtest and advancedpvrtest, but they only show the 256-color TA_PALETTE_CLUT8 mode - and I have been able to reproduce that use case with my own sprites and palettes.

I've looked through some of the linked docs in the repo, but haven't found anything useful yet.

I'd really appreciate anything to point me in the right direction.

Thanks very much!

maple.c - Expanding JVS Functionality (add Coin support, etc.)

I'm working on expanding the JVS functionality (EG: to add Coin input and decrement support), and ran into a few issues that I want to discuss before I continue, since I am proposing several significant changes (though I believe none of them would break existing APIs):

  1. The __outstanding_request flags can cause unexpected behavior when mixed with other JVS functions. Once maple_request_jvs_buttons has been called at least once, that function will cease to work if another JVS message is sent without unsetting (or re-requesting) the __outstanding_request flags. My current workaround for this is to simply retry any outstanding request, if one exists, as part of other JVS functions, EG:
if(__outstanding_request || __outstanding_request_addr != 0)
    {
        __outstanding_request = __maple_request_jvs_send_buttons_packet(__outstanding_request_addr, 1);
    }

But I'm wondering if you have any thoughts about a better way to handle this process, since this is rather wasteful (the original __outstanding_request is not used, burning maple bus cycles and time).

  1. The existing _maple_request_send_jvs() function limits the usability of JVS features (such as concatenated multi-command Requests) because of the small send buffer size. I'd like to propose expanding the subcommand buffer size, and passing the payload length to _maple_swap_data (right now it is hardcoded as 3 bytes, regardless of the len passed to _maple_request_send_jvs). Is there a specific reason why these limits are in place, or can they be larger?

  2. The current implementation does not expose lower-level JVS functionality outside of what libnaomi offers in maple.h. While this is probably more than adequate for many homebrew use cases, there are quite a few additional JVS functions (coins, alternative input devices, controllable cabinet hardware, etc.) that are not currently accessible. I'd propose offering lower-level access to those who desire it, by exposing _maple_request_send_jvs, _maple_request_recv_jvs, and some of the related data types and helper functions (jvs_status_t, etc.). It's technically possible to implement some extensions outside of libnaomi using these functions right now using extern, but being able to include them in the maple.h header would be more resilient to future implementation changes in libnaomi.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.