From: ljsebald <ljs...@us...> - 2023-08-23 04:36:32
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via a3fc2fe314f2ed27e177a2404a071367bb2cb92b (commit) via e3fcd675a1cdc1cf85404c7d206be23855a40921 (commit) from 2e1153d508fe7f7fbf9ed6d2746d50792e2373d2 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit a3fc2fe314f2ed27e177a2404a071367bb2cb92b Author: Falco Girgis <gyr...@gm...> Date: Tue Aug 22 23:34:45 2023 -0500 VMU driver support for date/time and buttons + documentation update (#207) * Added support for VMU time, buttons, and buzzer. 1) vmu_beep(): convenience high-level buzzer API - This function is provided for convenience around vmu_beep_raw(), and actually understands the alarm values represented by the arguments, ignoring unsupported values, naming them appropriately and then delegating back to vmu_beep_raw(). - We should keep vmu_beep_raw(), though, in case some 3rd party controller comes around which does have support for two sets of alarms. 2) vmu_get_time(), vmu_set_time(): time management - These two functions along with a corresponding structure were added for querying and setting the times and dates on the VMU. The structure's format and expected value ranges were commented. 3) vmu_get_btns(): query for button states - The VMU's button states are actually still accessible via the Maple BUS while attached to the controller. The "Retro Fighters" Dreamcast controller is currently the only known controller that allows you to leverage this, but being able to support a few extra buttons could be a nice thing to have in a game or app. * Cleanup + periodic driver polling for button state - Cleaned up VMU button macros to match controller buttons - Implemented periodic polling mechanism for querying button state * conditional: disabled by default, enabled via vmu_set_buttons_enabled(..) * only queries for button input on first unit, which should be the front-facing one to save maple frames * Stylistic fixes for VMU driver additions - BlueCrab pointed out a variety of ways in which the code was not adhering to the coding standards already established by KOS. Fixed. * Added (void) to empty arg lists in API * VMU Cleanup, documentation, beep waveform diagram - added top-level VMU module - fleshed out function documentation - added documentation + ACII diagram for new beep routine - changed VMU time functions from taking custom VMU-centric date/time struct to taking standard C time_t types - fixed some styling to be consistent - fixed const-correctness on 1 or 2 function args - added documentation for VMU icons in bios font - renamed vmu_set/get_date to vmu_set/get_datetime - reorganized functions by Maple function type - fixed a bunch of formatting - changed everything from uints to uint_ts - Removed magic numbers for VMU screen sizes and added public #define to API - Added #define for # of ms to sleep before retrying when writing a block fails * Docs work, vmu_get_icon_color, vmu_get_icon_shape - Minor formatting changes - Continued adding documentation - Added prototypes and header documetnation for - vmu_get_custom_color - vmu_get_icon_shape * More API + Documentation work on buzzer waveforms - Tweaked new, high-level buzzer API - Documented the living crap out of the buzzer's characteristics based on all of our analysis of the VMU BIOS and buzzer hardware testing. - Added todo list to keep myself on-track and make notes for driver additions/changes that are needed for full feature coverage and complete documentation * SOOOO much documenting for Maple feature modules. * Tiny bit more documentation update. * VMU date/time support fully tested and working * VMU button input support is done and tested! - Finished up VMU button input querying - Had one bug that was an assertion that had to be removed - Tested it with multiple controller types - Had to implement the intelligence to automatically reorient dpad buttons based on connector direction - The standard VMUs apparently do not query for MODE or SLEEP presses * Entire module's Doxygen documentation done! * Apply suggestions from code review Co-authored-by: Lawrence Sebald <ljs...@us...> * Resolved beep/settime issues with lots of traffic - Under a high load with button polling, the calls to vmu_set_datetime() and vmu_beep_raw() were failing intermittently with MAPLE_EAGAIN. It looks like this same issue must've been seen and resolved with vmu_block_read(), as it contains the fix, which is to yield the thread until the frame is unlocked - Removed a few trailing spaces introduced into biosfont.h --------- Co-authored-by: Lawrence Sebald <ljs...@us...> commit e3fcd675a1cdc1cf85404c7d206be23855a40921 Author: Falco Girgis <gyr...@gm...> Date: Tue Aug 22 23:30:12 2023 -0500 Controller refactor, documentation, capability queries (#212) * Controller cleanup, docs, capability categories - moved cont_cond_t to .c file as a private structure, since nothing is using it publically, and it just confuses people - added top-level "Controller" doxygen module for grouping everything related to the API - added an anonymous union with button state bitfields to the cont_state_t structure, to simplify checking button states while also maintaining backwards compatibility - fixed miscellaneous formatting issues - reorganized controller.h to group things logically - created "capability category" #defines (pending definitions) for grouping together button capability masks into logical units - added prototypes for high-level API used to check for 1) right analog stick support 2) right dpad support 3) any extended buttons 4) standard controller configuration - changed uintN types to uintN_t types * More Controller API documentation cleanup * Revert cb userdata, controller capabilities, types - Changed Doxyfile to alphabetize modules - Added queryable aggregate controller capability groups - Added queryable controller types - Removed userdata pointer from callbacks, because it was argued a bad idea for a context in which interrupts are disabled - Added a warning to the controller button callback mechanism to clearly describe this side effect - Modified a few C++ examples which were doing raw casts on the button callback to the expected type, not even matching exact arguments, which is sketchy... Better example which is more robust is to teach people to use the typedef provided by KOS. * More API documentation, maple connector_dir * Finished documenting and testing API * Fixed a typo in racing controller type macro * Added final comments to aggregate capabilities. * Forgot to update the changelog! * Tiny typo in documentation. * Fixed comment for maple_devinfo's connector_dir * Undid joystick axis translation change - UINT8_MAX != 128, accidentally screwed that up. * Controller cleanup, docs, capability categories - moved cont_cond_t to .c file as a private structure, since nothing is using it publically, and it just confuses people - added top-level "Controller" doxygen module for grouping everything related to the API - added an anonymous union with button state bitfields to the cont_state_t structure, to simplify checking button states while also maintaining backwards compatibility - fixed miscellaneous formatting issues - reorganized controller.h to group things logically - created "capability category" #defines (pending definitions) for grouping together button capability masks into logical units - added prototypes for high-level API used to check for 1) right analog stick support 2) right dpad support 3) any extended buttons 4) standard controller configuration - changed uintN types to uintN_t types * More Controller API documentation cleanup * Revert cb userdata, controller capabilities, types - Changed Doxyfile to alphabetize modules - Added queryable aggregate controller capability groups - Added queryable controller types - Removed userdata pointer from callbacks, because it was argued a bad idea for a context in which interrupts are disabled - Added a warning to the controller button callback mechanism to clearly describe this side effect - Modified a few C++ examples which were doing raw casts on the button callback to the expected type, not even matching exact arguments, which is sketchy... Better example which is more robust is to teach people to use the typedef provided by KOS. * More API documentation, maple connector_dir * Finished documenting and testing API * Fixed a typo in racing controller type macro * Added final comments to aggregate capabilities. * Master rebase, CHANGELOG update, cont state update - Rebased on mast to pick up everybody's changes - Added zcrc's VMU FB stuff to CHANGELOG cuz he forgot - changed the padding in the cont_state struct to be unnamed, because apparently that's a thing I never knew you could do in C * Tiny typo in documentation. * Fixed comment for maple_devinfo's connector_dir * Undid joystick axis translation change - UINT8_MAX != 128, accidentally screwed that up. * Clean up Makefiles (#220) Clean up Makefiles for examples. * Move vector.h from addons to core. (#218) * Move vector.h from addons to core. The core matrix API depends on the typedefs in vector.h, which currently lives in the addons tree. This change moves these typed back to the core kernel tree so that we don't have a dependency from addons back to the kernel. Signed-off-by: James Peach <jp...@ap...> * Update Doxygen comments for dc/vector.h. Signed-off-by: James Peach <jp...@ap...> --------- Signed-off-by: James Peach <jp...@ap...> * Update AUTHORS (#221) Add Paul Cercueil, aka "zcrc" to AUTHORS. * Added fast math CFlags to environ.sh.sample - Added fasth math KOS_CFLAGS to environ.sh.sample, defaulting to commented out, with a description of when and why you'd want to enable them - Removed -fno-builtin from the environ_base.sh script * Added -fno-builtin to environ.sh.sample - Removed -fno-builtin from environ_base.sh - Added it back to environ.sh.sample with a comment on how to disable it and an explanation of the implications of doing so * Add optimized ASM bit-reverse function This function can be used to bit-reverse a 32-bit value (where the MSB becomes the LSB and vice-versa). Signed-off-by: Paul Cercueil <pa...@cr...> * vmu: constify bitmap argument to vmu_draw_lcd() The data pointed by the bitmap argument is never modified by the function. Therefore, it should be marked const. Signed-off-by: Paul Cercueil <pa...@cr...> * vmu: Add function vmu_draw_lcd_rotated() This function is equivalent to vmu_draw_lcd, but the image is rotated 180° so that the first byte of the bitmap corresponds to the top-left corner, instead of the bottom-right one. Signed-off-by: Paul Cercueil <pa...@cr...> * Update kernel/arch/dreamcast/include/dc/maple/controller.h Quzarifying ASCII art Co-authored-by: Donald Haase <qu...@ya...> * Added a bunch of controller types. Thanks TChan0! * Addressed a few points from code review (Quzar's) * Update kernel/arch/dreamcast/include/dc/maple/controller.h Co-authored-by: Donald Haase <qu...@ya...> * Addressing more review feedback from Quzar * Fixed changelog: DC-specific changes, not common. * Apply suggestions from code review Co-authored-by: Lawrence Sebald <ljs...@us...> --------- Signed-off-by: James Peach <jp...@ap...> Signed-off-by: Paul Cercueil <pa...@cr...> Co-authored-by: Andress Barajas <and...@gm...> Co-authored-by: James Peach <jp...@ap...> Co-authored-by: Paul Cercueil <pa...@cr...> Co-authored-by: Donald Haase <qu...@ya...> Co-authored-by: Lawrence Sebald <ljs...@us...> ----------------------------------------------------------------------- Summary of changes: doc/CHANGELOG | 1 + doc/Doxyfile | 4 +- kernel/arch/dreamcast/hardware/maple/controller.c | 49 +- kernel/arch/dreamcast/hardware/maple/vmu.c | 363 ++++++++++--- kernel/arch/dreamcast/include/dc/biosfont.h | 14 +- kernel/arch/dreamcast/include/dc/maple.h | 2 +- .../arch/dreamcast/include/dc/maple/controller.h | 566 +++++++++++++++++---- kernel/arch/dreamcast/include/dc/maple/vmu.h | 528 ++++++++++++++++--- 8 files changed, 1282 insertions(+), 245 deletions(-) diff --git a/doc/CHANGELOG b/doc/CHANGELOG index 70f838c..203eaed 100644 --- a/doc/CHANGELOG +++ b/doc/CHANGELOG @@ -180,6 +180,7 @@ KallistiOS version 2.1.0 ----------------------------------------------- - *** Split init flags from <arch/arch.h> into <kos/init.h> [LS] - *** Implemented posix_memalign() from stdlib.h [FG] - *** Added clock_gettime(), clock_settime(), clock_getres() [FG] +- DC Refactored controller API, added capability groups and types [FG] KallistiOS version 2.0.0 ----------------------------------------------- - DC Broadband Adapter driver fixes [Megan Potter == MP] diff --git a/doc/Doxyfile b/doc/Doxyfile index 7df6ccd..fcff64c 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -679,7 +679,7 @@ SORT_MEMBERS_CTORS_1ST = NO # appear in their defined order. # The default value is: NO. -SORT_GROUP_NAMES = NO +SORT_GROUP_NAMES = YES # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by # fully-qualified names, including namespaces. If set to NO, the class list will @@ -2303,7 +2303,7 @@ EXPAND_AS_DEFINED = __BEGIN_DECLS \ # The default value is: YES. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -SKIP_FUNCTION_MACROS = YES +SKIP_FUNCTION_MACROS = NO #--------------------------------------------------------------------------- # Configuration options related to external references diff --git a/kernel/arch/dreamcast/hardware/maple/controller.c b/kernel/arch/dreamcast/hardware/maple/controller.c index 8d92c1d..02a677d 100644 --- a/kernel/arch/dreamcast/hardware/maple/controller.c +++ b/kernel/arch/dreamcast/hardware/maple/controller.c @@ -11,22 +11,49 @@ #include <string.h> #include <assert.h> +/* Location of controller capabilities within function_data array */ +#define CONT_FUNCTION_DATA_INDEX 0 + +/* Raw controller condition structure */ +typedef struct cont_cond { + uint16_t buttons; /* buttons bitfield */ + uint8_t rtrig; /* right trigger */ + uint8_t ltrig; /* left trigger */ + uint8_t joyx; /* joystick X */ + uint8_t joyy; /* joystick Y */ + uint8_t joy2x; /* second joystick X */ + uint8_t joy2y; /* second joystick Y */ +} cont_cond_t; + static cont_btn_callback_t btn_callback = NULL; -static uint8 btn_callback_addr = 0; -static uint32 btn_callback_btns = 0; +static uint8_t btn_callback_addr = 0; +static uint32_t btn_callback_btns = 0; + +/* Check whether the controller has EXACTLY the given capabilties. */ +int cont_is_type(const maple_device_t *cont, uint32_t type) { + return cont ? cont->info.function_data[CONT_FUNCTION_DATA_INDEX] == type : + -1; +} + +/* Check whether the controller has at LEAST the given capabilities. */ +int cont_has_capabilities(const maple_device_t *cont, uint32_t capabilities) { + return cont ? ((cont->info.function_data[CONT_FUNCTION_DATA_INDEX] + & capabilities) == capabilities) : -1; +} /* Set a controller callback for a button combo; set addr=0 for any controller */ -void cont_btn_callback(uint8 addr, uint32 btns, cont_btn_callback_t cb) { +void cont_btn_callback(uint8_t addr, uint32_t btns, cont_btn_callback_t cb) { btn_callback_addr = addr; btn_callback_btns = btns; btn_callback = cb; } +/* Response callback for the GETCOND Maple command. */ static void cont_reply(maple_frame_t *frm) { - maple_response_t *resp; - uint32 *respbuf; - cont_cond_t *raw; - cont_state_t *cooked; + maple_response_t *resp; + uint32_t *respbuf; + cont_cond_t *raw; + cont_state_t *cooked; /* Unlock the frame now (it's ok, we're in an IRQ) */ maple_frame_unlock(frm); @@ -37,7 +64,7 @@ static void cont_reply(maple_frame_t *frm) { if(resp->response != MAPLE_RESPONSE_DATATRF) return; - respbuf = (uint32 *)resp->data; + respbuf = (uint32_t *)resp->data; if(respbuf[0] != MAPLE_FUNC_CONTROLLER) return; @@ -45,7 +72,7 @@ static void cont_reply(maple_frame_t *frm) { /* Update the status area from the response */ if(frm->dev) { /* Verify the size of the frame and grab a pointer to it */ - assert(sizeof(cont_cond_t) == ((resp->data_len - 1) * 4)); + assert(sizeof(cont_cond_t) == ((resp->data_len - 1) * sizeof(uint32_t))); raw = (cont_cond_t *)(respbuf + 1); /* Fill the "nice" struct from the raw data */ @@ -74,13 +101,13 @@ static void cont_reply(maple_frame_t *frm) { } static int cont_poll(maple_device_t *dev) { - uint32 * send_buf; + uint32_t *send_buf; if(maple_frame_lock(&dev->frame) < 0) return 0; maple_frame_init(&dev->frame); - send_buf = (uint32 *)dev->frame.recv_buf; + send_buf = (uint32_t *)dev->frame.recv_buf; send_buf[0] = MAPLE_FUNC_CONTROLLER; dev->frame.cmd = MAPLE_COMMAND_GETCOND; dev->frame.dst_port = dev->port; diff --git a/kernel/arch/dreamcast/hardware/maple/vmu.c b/kernel/arch/dreamcast/hardware/maple/vmu.c index 3267479..fb6a0f0 100644 --- a/kernel/arch/dreamcast/hardware/maple/vmu.c +++ b/kernel/arch/dreamcast/hardware/maple/vmu.c @@ -1,8 +1,16 @@ /* KallistiOS ##version## vmu.c - Copyright (C)2002,2003 Megan Potter - Copyright (C)2008 Donald Haase + Copyright (C) 2002, 2003 Megan Potter + Copyright (C) 2008 Donald Haase + Copyright (C) 2023 Falco Girgis + */ + +/* + This module deals with the VMU. It provides functionality for + filesystem, LCD screen, buzzer, and date/time access. + + Thanks to Marcus Comstedt for VMU/Maple information. */ #include <assert.h> @@ -17,12 +25,37 @@ #include <dc/vmufs.h> #include <arch/timer.h> -/* - This module deals with the VMU. It provides functionality for - memorycard access, and for access to the lcd screen. +#define VMU_BLOCK_WRITE_RETRY_TIME 100 /* time to sleep until retrying a failed write */ + +typedef struct vmu_datetime { + uint16_t year; /* 0 - 9999 */ + uint8_t month; /* 1 - 12 */ + uint8_t day; /* 1 - 31 */ + uint8_t hour; /* 0 - 23 */ + uint8_t minute; /* 0 - 59 */ + uint8_t second; /* 0 - 59 */ + uint8_t weekday; /* 0 - 6 (Starting with Monday) */ +} vmu_datetime_t; + +static void vmu_datetime_to_tm(const vmu_datetime_t *dt, struct tm *bt) { + bt->tm_sec = dt->second; + bt->tm_min = dt->minute; + bt->tm_hour = dt->hour; + bt->tm_mday = dt->day; + bt->tm_mon = dt->month - 1; + bt->tm_year = dt->year - 1900; + bt->tm_wday = dt->weekday != 6? dt->weekday + 1 : 0; +} - Thanks to Marcus Comstedt for VMU/Maple information. - */ +static void vmu_datetime_from_tm(vmu_datetime_t *dt, const struct tm *bt) { + dt->second = bt->tm_sec; + dt->minute = bt->tm_min; + dt->hour = bt->tm_hour; + dt->day = bt->tm_mday; + dt->month = bt->tm_mon + 1; + dt->year = bt->tm_year + 1900; + dt->weekday = bt->tm_wday? dt->weekday - 1 : 6; +} static int vmu_attach(maple_driver_t *drv, maple_device_t *dev) { (void)drv; @@ -30,6 +63,83 @@ static int vmu_attach(maple_driver_t *drv, maple_device_t *dev) { return 0; } +static void vmu_poll_reply(maple_frame_t *frm) { + maple_response_t *resp; + uint32_t *respbuf; + vmu_cond_t *raw; + vmu_state_t *cooked; + + /* Unlock the frame now (it's ok, we're in an IRQ) */ + maple_frame_unlock(frm); + + /* Make sure we got a valid response */ + resp = (maple_response_t *)frm->recv_buf; + + if(resp->response != MAPLE_RESPONSE_DATATRF) + return; + + respbuf = (uint32_t *)resp->data; + + if(respbuf[0] != MAPLE_FUNC_CLOCK) + return; + + /* Update the status area from the response */ + if(frm->dev) { + const maple_device_t *cont = maple_enum_dev(frm->dev->port, 0); + + /* Verify the size of the frame and grab a pointer to it */ + //assert(resp->data_len == 7); + raw = (vmu_cond_t *)(respbuf + 1); + + /* Fill the "nice" struct from the raw data */ + cooked = (vmu_state_t *)(frm->dev->status); + /* Invert raw struct as nice struct */ + cooked->buttons = ~(*raw); + + /* Check to see if the VMU is upside-down in the controller and readjust + its directional buttons accordingly. */ + if(cont && (cont->info.functions & MAPLE_FUNC_CONTROLLER) && + (frm->dev->info.connector_direction == cont->info.connector_direction)) { + cooked->buttons = (cooked->buttons & 0xf0) | + (cooked->dpad_up << 1) | /* down */ + (cooked->dpad_down << 0) | /* up */ + (cooked->dpad_left << 3) | /* right */ + (cooked->dpad_right << 2); /* left */ + + } + + frm->dev->status_valid = 1; + } +} + +static int vmu_poll(maple_device_t *dev) { + uint32_t *send_buf; + + /* Only query for button input on the front VMU of each controller. */ + if(dev->unit == 1) { + if(maple_frame_lock(&dev->frame) < 0) + return 0; + + maple_frame_init(&dev->frame); + send_buf = (uint32_t *)dev->frame.recv_buf; + send_buf[0] = MAPLE_FUNC_CLOCK; + dev->frame.cmd = MAPLE_COMMAND_GETCOND; + dev->frame.dst_port = dev->port; + dev->frame.dst_unit = dev->unit; + dev->frame.length = 1; + dev->frame.callback = vmu_poll_reply; + dev->frame.send_buf = send_buf; + maple_queue_frame(&dev->frame); + + } + + return 0; +} + +static void vmu_periodic(maple_driver_t *drv) { + maple_driver_foreach(drv, vmu_poll); +} + /* Device Driver Struct */ static maple_driver_t vmu_drv = { .functions = MAPLE_FUNC_MEMCARD | MAPLE_FUNC_LCD | MAPLE_FUNC_CLOCK, @@ -50,7 +160,17 @@ void vmu_shutdown(void) { maple_driver_unreg(&vmu_drv); } -int vmu_use_custom_color(maple_device_t * dev, int enable) { +/* Dynamically add the periodic polling callback to the driver when button input is enabled. */ +void vmu_set_buttons_enabled(int enable) { + vmu_drv.periodic = enable ? vmu_periodic : NULL; +} + +/* Determine whether polling for button input is enabled or not by presence of periodic callback. */ +int vmu_get_buttons_enabled(void) { + return !!vmu_drv.periodic; +} + +int vmu_use_custom_color(maple_device_t *dev, int enable) { vmu_root_t root; if(vmufs_root_read(dev, &root) < 0) @@ -67,7 +187,7 @@ int vmu_use_custom_color(maple_device_t * dev, int enable) { /* The custom color is used while navigating the Dreamcast's file manager. You set the RGBA parameters, each with valid range of 0-255 */ -int vmu_set_custom_color(maple_device_t * dev, uint8 red, uint8 green, uint8 blue, uint8 alpha) { +int vmu_set_custom_color(maple_device_t *dev, uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha) { vmu_root_t root; if(vmufs_root_read(dev, &root) < 0) @@ -89,7 +209,7 @@ int vmu_set_custom_color(maple_device_t * dev, uint8 red, uint8 green, uint8 blu /* The icon shape is used while navigating the BIOS menu. The values for icon_shape are listed in the biosfont.h and start with BFONT_ICON_VMUICON. */ -int vmu_set_icon_shape(maple_device_t * dev, uint8 icon_shape) { +int vmu_set_icon_shape(maple_device_t *dev, uint8_t icon_shape) { #ifdef _arch_sub_naomi vmu_root_t root; @@ -119,7 +239,7 @@ int vmu_set_icon_shape(maple_device_t * dev, uint8 icon_shape) { can stay the same */ /* Callback that unlocks the frame, general use */ -static void vmu_gen_callback(maple_frame_t * frame) { +static void vmu_gen_callback(maple_frame_t *frame) { /* Unlock the frame for the next usage */ maple_frame_unlock(frame); @@ -128,22 +248,21 @@ static void vmu_gen_callback(maple_frame_t * frame) { } /* Set the tone to be generated by the VMU's speaker. - Only last two bytes are used. Actual parameters unknown - except that the last byte must be larger than the second - to last byte. This might necessitate refactoring as the - clock is a seperate device from the screen and storage. */ -int vmu_beep_raw(maple_device_t * dev, uint32 beep) { - uint32 * send_buf; + Only last two bytes are used. This might necessitate + refactoring as the clock is a seperate device from + the screen and storage. */ +int vmu_beep_raw(maple_device_t *dev, uint32_t beep) { + uint32_t *send_buf; - assert(dev != NULL); + assert(dev); - /* Lock the frame */ - if(maple_frame_lock(&dev->frame) < 0) - return MAPLE_EAGAIN; + /* Lock the frame. XXX: Priority inversion issues here. */ + while(maple_frame_lock(&dev->frame) < 0) + thd_pass(); /* Reset the frame */ maple_frame_init(&dev->frame); - send_buf = (uint32 *)dev->frame.recv_buf; + send_buf = (uint32_t *)dev->frame.recv_buf; send_buf[0] = MAPLE_FUNC_CLOCK; send_buf[1] = beep; dev->frame.cmd = MAPLE_COMMAND_SETCOND; @@ -168,10 +287,15 @@ int vmu_beep_raw(maple_device_t * dev, uint32 beep) { return MAPLE_EOK; } +int vmu_beep(maple_device_t *dev, uint8_t period, uint8_t duty) { + const uint32_t raw_beep = ((period << 24) | ((period - duty)) << 16); + return vmu_beep_raw(dev, raw_beep); +} + /* Draw a 1-bit bitmap on the LCD screen (48x32). return a -1 if an error occurs */ -int vmu_draw_lcd(maple_device_t * dev, const void *bitmap) { - uint32 * send_buf; +int vmu_draw_lcd(maple_device_t *dev, const void *bitmap) { + uint32_t *send_buf; assert(dev != NULL); @@ -181,14 +305,14 @@ int vmu_draw_lcd(maple_device_t * dev, const void *bitmap) { /* Reset the frame */ maple_frame_init(&dev->frame); - send_buf = (uint32 *)dev->frame.recv_buf; + send_buf = (uint32_t *)dev->frame.recv_buf; send_buf[0] = MAPLE_FUNC_LCD; send_buf[1] = 0; /* Block / phase / partition */ - memcpy(send_buf + 2, bitmap, 48 * 4); + memcpy(send_buf + 2, bitmap, VMU_SCREEN_WIDTH * 4); dev->frame.cmd = MAPLE_COMMAND_BWRITE; dev->frame.dst_port = dev->port; dev->frame.dst_unit = dev->unit; - dev->frame.length = 2 + 48; + dev->frame.length = 2 + VMU_SCREEN_WIDTH; dev->frame.callback = vmu_gen_callback; dev->frame.send_buf = send_buf; maple_queue_frame(&dev->frame); @@ -208,7 +332,7 @@ int vmu_draw_lcd(maple_device_t * dev, const void *bitmap) { } int vmu_draw_lcd_rotated(maple_device_t *dev, const void *bitmap) { - uint32 bitmap_inverted[48]; + uint32_t bitmap_inverted[48]; unsigned int i; for (i = 0; i < 48; i++) { @@ -220,29 +344,44 @@ int vmu_draw_lcd_rotated(maple_device_t *dev, const void *bitmap) { /* This function converts a xbm image to a 1-bit bitmap that can be displayed on LCD screen of VMU */ -static void vmu_xbm_to_bitmap(uint8 *bitmap, const char *vmu_icon) { +static void vmu_xbm_to_bitmap(uint8_t *bitmap, const char *vmu_icon) { int x, y, xi, xb; - memset(bitmap, 0, 48 * 32 / 8); + memset(bitmap, 0, VMU_SCREEN_WIDTH * VMU_SCREEN_HEIGHT / 8); if(vmu_icon) { - for(y = 0; y < 32; y++) - for(x = 0; x < 48; x++) { + for(y = 0; y < VMU_SCREEN_HEIGHT; y++) + for(x = 0; x < VMU_SCREEN_WIDTH; x++) { xi = x / 8; xb = 0x80 >> (x % 8); - if(vmu_icon[(31 - y) * 48 + (47 - x)] == '.') - bitmap[y * (48 / 8) + xi] |= xb; + if(vmu_icon[((VMU_SCREEN_HEIGHT - 1) - y) * VMU_SCREEN_WIDTH + + ((VMU_SCREEN_WIDTH - 1) - x)] == '.') + bitmap[y * (VMU_SCREEN_WIDTH / 8) + xi] |= xb; } } } -int vmu_draw_lcd_xbm(maple_device_t * dev, const char *vmu_icon) { - uint8 bitmap[48 * 32 / 8]; +int vmu_draw_lcd_xbm(maple_device_t *dev, const char *vmu_icon) { + uint8_t bitmap[VMU_SCREEN_WIDTH * VMU_SCREEN_HEIGHT / 8]; vmu_xbm_to_bitmap(bitmap, vmu_icon); return vmu_draw_lcd(dev, bitmap); } +/* Utility function which sets the icon on all available VMUs + from an Xwindows XBM. Imported from libdcutils. */ +void vmu_set_icon(const char *vmu_icon) { + int i = 0; + maple_device_t *dev; + uint8_t bitmap[VMU_SCREEN_WIDTH * VMU_SCREEN_HEIGHT / 8]; + + vmu_xbm_to_bitmap(bitmap, vmu_icon); + + while((dev = maple_enum_type(i++, MAPLE_FUNC_LCD))) { + vmu_draw_lcd(dev, bitmap); + } +} + /* Read the data in block blocknum into buffer, return a -1 if an error occurs, for now we ignore MAPLE_RESPONSE_FILEERR, which will be changed shortly */ @@ -251,11 +390,11 @@ static void vmu_block_read_callback(maple_frame_t *frm) { genwait_wake_all(frm); } -int vmu_block_read(maple_device_t * dev, uint16 blocknum, uint8 *buffer) { - maple_response_t *resp; - int rv; - uint32 *send_buf; - uint32 blkid; +int vmu_block_read(maple_device_t *dev, uint16_t blocknum, uint8_t *buffer) { + maple_response_t *resp; + int rv; + uint32_t *send_buf; + uint32_t blkid; assert(dev != NULL); @@ -268,7 +407,7 @@ int vmu_block_read(maple_device_t * dev, uint16 blocknum, uint8 *buffer) { /* Reset the frame */ maple_frame_init(&dev->frame); - send_buf = (uint32 *)dev->frame.recv_buf; + send_buf = (uint32_t *)dev->frame.recv_buf; send_buf[0] = MAPLE_FUNC_MEMCARD; send_buf[1] = blkid; dev->frame.cmd = MAPLE_COMMAND_BREAD; @@ -299,7 +438,7 @@ int vmu_block_read(maple_device_t * dev, uint16 blocknum, uint8 *buffer) { /* Copy out the response */ resp = (maple_response_t *)dev->frame.recv_buf; - send_buf = (uint32 *)resp->data; + send_buf = (uint32_t *)resp->data; if(resp->response != MAPLE_RESPONSE_DATATRF || send_buf[0] != MAPLE_FUNC_MEMCARD @@ -327,11 +466,12 @@ static void vmu_block_write_callback(maple_frame_t *frm) { /* Wakey, wakey! */ genwait_wake_all(frm); } -static int vmu_block_write_internal(maple_device_t * dev, uint16 blocknum, uint8 *buffer) { - maple_response_t *resp; - int rv, phase, r; - uint32 *send_buf; - uint32 blkid; + +static int vmu_block_write_internal(maple_device_t *dev, uint16_t blocknum, const uint8_t *buffer) { ...<truncated>... hooks/post-receive -- A pseudo Operating System for the Dreamcast. |