From: quzar <qu...@us...> - 2024-05-16 13:24:54
|
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 c3ce8d43582762f5224631319e7350168d88f416 (commit) from 635e6aaf63b3144409ebcc806f5ed3edd5df2554 (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 c3ce8d43582762f5224631319e7350168d88f416 Author: Andy Barajas <and...@gm...> Date: Thu May 16 06:24:15 2024 -0700 Improve Screenshot (#575) * Speed up 16bpp => 24bpp by 57%. Moved file creation to the top of the function so it can fail sooner. Print a message when the screenshot has been written * Clean up makefile documentation for video examples. Gitignore some gldc files to mirror ignored files for kgl * Add screenshot example * Added PM_RGB888P support thanks to SWAT * Updated Makefile comment to include Ubuntu on list of OS that require sudo, code cleanup ----------------------------------------------------------------------- Summary of changes: .gitignore | 3 + examples/dreamcast/video/Makefile | 3 + examples/dreamcast/video/bfont/Makefile | 4 +- examples/dreamcast/video/palmenu/Makefile | 5 + examples/dreamcast/video/screenshot/Makefile | 31 ++++++ examples/dreamcast/video/screenshot/screenshot.c | 98 ++++++++++++++++++ kernel/arch/dreamcast/hardware/sq.c | 6 +- kernel/arch/dreamcast/hardware/syscalls.c | 4 +- kernel/arch/dreamcast/util/screenshot.c | 121 ++++++++++++++--------- 9 files changed, 222 insertions(+), 53 deletions(-) create mode 100644 examples/dreamcast/video/screenshot/Makefile create mode 100644 examples/dreamcast/video/screenshot/screenshot.c diff --git a/.gitignore b/.gitignore index e3e4cd17..02d16d33 100644 --- a/.gitignore +++ b/.gitignore @@ -34,6 +34,8 @@ utils/naominetboot/naominetboot examples/dreamcast/basic/exec/romdisk/sub.bin examples/dreamcast/kgl/basic/vq/fruit.vq examples/dreamcast/kgl/nehe/nehe26/data/txt2bin +examples/dreamcast/gldc/basic/vq/fruit.vq +examples/dreamcast/gldc/nehe/nehe26/data/txt2bin examples/dreamcast/conio/adventure/data.c examples/dreamcast/conio/adventure/datagen examples/dreamcast/png/romdisk_boot.img @@ -41,6 +43,7 @@ examples/dreamcast/pvr/bumpmap/romdisk/bricks.kmg examples/dreamcast/pvr/bumpmap/romdisk/bumpmap.raw examples/dreamcast/pvr/modifier_volume_tex/romdisk/fruit.kmg examples/dreamcast/pvr/texture_render/texture_render.bin +examples/dreamcast/video/screenshot/screenshot*.ppm utils/dc-chain/logs utils/dc-chain/*.tar.bz2 utils/dc-chain/*.tar.gz diff --git a/examples/dreamcast/video/Makefile b/examples/dreamcast/video/Makefile index a24bf8b0..f7c4e8aa 100644 --- a/examples/dreamcast/video/Makefile +++ b/examples/dreamcast/video/Makefile @@ -9,15 +9,18 @@ all: $(KOS_MAKE) -C palmenu $(KOS_MAKE) -C minifont $(KOS_MAKE) -C multibuffer + $(KOS_MAKE) -C screenshot clean: $(KOS_MAKE) -C bfont clean $(KOS_MAKE) -C palmenu clean $(KOS_MAKE) -C minifont clean $(KOS_MAKE) -C multibuffer clean + $(KOS_MAKE) -C screenshot clean dist: $(KOS_MAKE) -C bfont dist $(KOS_MAKE) -C palmenu dist $(KOS_MAKE) -C minifont dist $(KOS_MAKE) -C multibuffer dist + $(KOS_MAKE) -C screenshot dist diff --git a/examples/dreamcast/video/bfont/Makefile b/examples/dreamcast/video/bfont/Makefile index 67462aff..82f57ad3 100644 --- a/examples/dreamcast/video/bfont/Makefile +++ b/examples/dreamcast/video/bfont/Makefile @@ -1,7 +1,7 @@ # KallistiOS ##version## # -# basic/bfont/Makefile -# (c)2002 Megan Potter +# video/bfont/Makefile +# Copyright (C) 2002 Megan Potter # TARGET = bfont.elf diff --git a/examples/dreamcast/video/palmenu/Makefile b/examples/dreamcast/video/palmenu/Makefile index d0c54788..befc2048 100644 --- a/examples/dreamcast/video/palmenu/Makefile +++ b/examples/dreamcast/video/palmenu/Makefile @@ -1,3 +1,8 @@ +# KallistiOS ##version## +# +# video/palmenu/Makefile +# + # Put the filename of the output binary here TARGET = palmenu.elf diff --git a/examples/dreamcast/video/screenshot/Makefile b/examples/dreamcast/video/screenshot/Makefile new file mode 100644 index 00000000..51f8dcb4 --- /dev/null +++ b/examples/dreamcast/video/screenshot/Makefile @@ -0,0 +1,31 @@ +# KallistiOS ##version## +# +# video/screenshot/Makefile +# Copyright (C) 2024 Andy Barajas +# + +TARGET = screenshot.elf +OBJS = screenshot.o + +all: rm-elf $(TARGET) + +include $(KOS_BASE)/Makefile.rules + +clean: rm-elf + -rm -f $(OBJS) + -rm -f screenshot*.ppm + +rm-elf: + -rm -f $(TARGET) + +$(TARGET): $(OBJS) + kos-cc -o $(TARGET) $(OBJS) + +# For Mac, Linux, Ubuntu sudo is required with the -c "." command to save data to the PC +# sudo $(KOS_LOADER) $(TARGET) -c "." +run: $(TARGET) + $(KOS_LOADER) $(TARGET) -c "." + +dist: $(TARGET) + -rm -f $(OBJS) + $(KOS_STRIP) $(TARGET) diff --git a/examples/dreamcast/video/screenshot/screenshot.c b/examples/dreamcast/video/screenshot/screenshot.c new file mode 100644 index 00000000..51074b34 --- /dev/null +++ b/examples/dreamcast/video/screenshot/screenshot.c @@ -0,0 +1,98 @@ +/* KallistiOS ##version## + + screenshot.c + Copyright (C) 2024 Andy Barajas + +*/ + +/* + This program demonstrates how to use the vid_screen_shot() function + to capture and save a screenshot in the PPM format to your computer + using the DC Tool. This tool requires the '-c "."' command-line argument + to operate correctly. + + The program cycles through a color gradient background and allows user + interaction to capture screenshots or exit the program. + + Usage: + Ensure the '/pc/' directory path is correctly specified in the vid_screen_shot() + function call so that the screenshot.ppm file is saved in the appropriate + directory on your computer. +*/ + +#include <stdio.h> + +#include <dc/video.h> +#include <dc/fmath.h> +#include <dc/maple.h> +#include <dc/biosfont.h> +#include <dc/maple/controller.h> + +#include <kos/thread.h> + +#define SHOW_BLACK_BG 1 + +/* Keeps track of the amount of screenshots you have taken */ +static int counter = 0; + +int main(int argc, char **argv) { + uint8_t r, g, b; + uint32_t t = 0; + int font_height_offset = 0; + char filename[256]; + + /* Adjust frequency for faster or slower transitions */ + float frequency = 0.01; + + maple_device_t *cont; + cont_state_t *state; + + /* Set the video mode */ + vid_set_mode(DM_640x480, PM_RGB565); + + while(1) { + if((cont = maple_enum_type(0, MAPLE_FUNC_CONTROLLER)) != NULL) { + state = (cont_state_t *)maple_dev_status(cont); + + if(state == NULL) + break; + + if(state->buttons & CONT_START) + break; + + if(state->buttons & CONT_A) { + sprintf(filename, "/pc/screenshot%03d.ppm", counter); + vid_screen_shot(filename); + counter = (counter + 1) % 1000; + } + } + + /* Wait for VBlank */ + vid_waitvbl(); + + /* Calculate next background color */ + r = (uint8_t)((fsin(frequency * t + 0) * 127.5) + 127.5); + g = (uint8_t)((fsin(frequency * t + 2 * F_PI / 3) * 127.5) + 127.5); + b = (uint8_t)((fsin(frequency * t + 4 * F_PI / 3) * 127.5) + 127.5); + + /* Increment t to change color in the next cycle */ + t = (t + 1) % INT32_MAX; + + /* Draw Background */ + vid_clear(r, g, b); + + /* Draw Foreground */ + font_height_offset = (640 * (480 - (BFONT_HEIGHT * 6))) + (BFONT_THIN_WIDTH * 2); + bfont_draw_str(vram_s + font_height_offset, 640, SHOW_BLACK_BG, + "Press Start to exit"); + + font_height_offset += 640 * BFONT_HEIGHT * 2; + bfont_draw_str(vram_s + font_height_offset, 640, SHOW_BLACK_BG, + "Press A to take a screen shot"); + + /* Without this the bfont wont show on the screen */ + thd_sleep(10); + } + + return 0; +} diff --git a/kernel/arch/dreamcast/hardware/sq.c b/kernel/arch/dreamcast/hardware/sq.c index 23d047cb..7f34633a 100644 --- a/kernel/arch/dreamcast/hardware/sq.c +++ b/kernel/arch/dreamcast/hardware/sq.c @@ -93,7 +93,7 @@ __attribute__((noinline)) void *sq_cpy(void *dest, const void *src, size_t n) { } /* Fills n bytes at dest with byte c, dest must be 32-byte aligned */ -void * sq_set(void *dest, uint32_t c, size_t n) { +void *sq_set(void *dest, uint32_t c, size_t n) { /* Duplicate low 8-bits of c into high 24-bits */ c = c & 0xff; c = (c << 24) | (c << 16) | (c << 8) | c; @@ -102,7 +102,7 @@ void * sq_set(void *dest, uint32_t c, size_t n) { } /* Fills n bytes at dest with short c, dest must be 32-byte aligned */ -void * sq_set16(void *dest, uint32_t c, size_t n) { +void *sq_set16(void *dest, uint32_t c, size_t n) { /* Duplicate low 16-bits of c into high 16-bits */ c = c & 0xffff; c = (c << 16) | c; @@ -111,7 +111,7 @@ void * sq_set16(void *dest, uint32_t c, size_t n) { } /* Fills n bytes at dest with int c, dest must be 32-byte aligned */ -void * sq_set32(void *dest, uint32_t c, size_t n) { +void *sq_set32(void *dest, uint32_t c, size_t n) { uint32_t *d = SQ_MASK_DEST(dest); sq_lock(dest); diff --git a/kernel/arch/dreamcast/hardware/syscalls.c b/kernel/arch/dreamcast/hardware/syscalls.c index 476e1e33..60d7cf07 100644 --- a/kernel/arch/dreamcast/hardware/syscalls.c +++ b/kernel/arch/dreamcast/hardware/syscalls.c @@ -73,8 +73,8 @@ #define FUNC_GDROM_PIO_CALLBACK 11 #define FUNC_GDROM_PIO_TRANSFER 12 #define FUNC_GDROM_PIO_CHECK 13 -#define FUNC_GDROM_UNKNOWN1 14 -#define FUNC_GDROM_UNKNOWN2 15 +#define FUNC_GDROM_STUB1 14 +#define FUNC_GDROM_STUB2 15 /* SYSTEM functions */ #define FUNC_SYSTEM_RESET -1 diff --git a/kernel/arch/dreamcast/util/screenshot.c b/kernel/arch/dreamcast/util/screenshot.c index c835c27b..5489c456 100644 --- a/kernel/arch/dreamcast/util/screenshot.c +++ b/kernel/arch/dreamcast/util/screenshot.c @@ -1,8 +1,11 @@ /* KallistiOS ##version## screenshot.c - (c)2002 Megan Potter - (c)2008 Donald Haase + + Copyright (C) 2002 Megan Potter + Copyright (C) 2008 Donald Haase + Copyright (C) 2024 Andy Barajas + */ #include <stdio.h> @@ -12,6 +15,8 @@ #include <kos/fs.h> #include <arch/irq.h> +#include <arch/timer.h> + /* Provides a very simple screen shot facility (dumps raw RGB PPM files from the @@ -24,73 +29,104 @@ This will now work with any of the supported video modes. */ int vid_screen_shot(const char *destfn) { - file_t f; - int i, numpix; - uint8 *buffer; - char header[256]; - uint32 save; - uint32 pixel; /* to fit 888 mode */ - uint8 r, g, b; - uint8 bpp; - + file_t f; + uint8_t *buffer; + uint8_t *vram_b; /* Used for PM_RGB888P(24-bit) */ + char header[256]; + int i, numpix; + uint32_t save; + uint32_t pixel, pixel1, pixel2; + uint8_t bpp; bpp = 3; /* output to ppm is 3 bytes per pixel */ numpix = vid_mode->width * vid_mode->height; /* Allocate a new buffer so we can blast it all at once */ - buffer = (uint8 *)malloc(numpix * bpp); + buffer = (uint8_t *)malloc(numpix * bpp); if(buffer == NULL) { dbglog(DBG_ERROR, "vid_screen_shot: can't allocate ss memory\n"); return -1; } + /* Open output file */ + f = fs_open(destfn, O_WRONLY | O_TRUNC); + + if(!f) { + dbglog(DBG_ERROR, "vid_screen_shot: can't open output file '%s'\n", destfn); + free(buffer); + return -1; + } + /* Disable interrupts */ save = irq_disable(); - /* Write out each pixel as 24 bits */ + /* Write out each pixel as 24-bits */ switch(vid_mode->pm) { - case(PM_RGB555): { - for(i = 0; i < numpix; i++) { - pixel = vram_s[i]; - r = (((pixel >> 10) & 0x1f) << 3); - g = (((pixel >> 5) & 0x1f) << 3); - b = (((pixel >> 0) & 0x1f) << 3); - buffer[i * 3 + 0] = r; - buffer[i * 3 + 1] = g; - buffer[i * 3 + 2] = b; + case(PM_RGB555): { /* (15-bit) */ + /* Process two 16-bit pixels at a time */ + for(i = 0; i < numpix/2; i++) { + pixel = vram_l[i]; + pixel1 = pixel & 0xFFFF; + pixel2 = pixel >> 16; + + /* Process the first pixel */ + buffer[i * 6 + 0] = (((pixel1 >> 10) & 0x1f) << 3); /* R */ + buffer[i * 6 + 1] = (((pixel1 >> 5) & 0x1f) << 3); /* G */ + buffer[i * 6 + 2] = (((pixel1 >> 0) & 0x1f) << 3); /* B */ + + /* Process the second pixel */ + buffer[i * 6 + 3] = (((pixel2 >> 10) & 0x1f) << 3); /* R */ + buffer[i * 6 + 4] = (((pixel2 >> 5) & 0x1f) << 3); /* G */ + buffer[i * 6 + 5] = (((pixel2 >> 0) & 0x1f) << 3); /* B */ + } + + break; + } + case(PM_RGB565): { /* (16-bit) */ + /* Process two 16-bit pixels at a time */ + for(i = 0; i < numpix/2; i++) { + pixel = vram_l[i]; + pixel1 = pixel & 0xFFFF; + pixel2 = pixel >> 16; + + /* Process the first pixel */ + buffer[i * 6 + 0] = (((pixel1 >> 11) & 0x1f) << 3); /* R */ + buffer[i * 6 + 1] = (((pixel1 >> 5) & 0x3f) << 2); /* G */ + buffer[i * 6 + 2] = (((pixel1 >> 0) & 0x1f) << 3); /* B */ + + /* Process the second pixel */ + buffer[i * 6 + 3] = (((pixel2 >> 11) & 0x1f) << 3); /* R */ + buffer[i * 6 + 4] = (((pixel2 >> 5) & 0x3f) << 2); /* G */ + buffer[i * 6 + 5] = (((pixel2 >> 0) & 0x1f) << 3); /* B */ } break; } - case(PM_RGB565): { + case(PM_RGB888P): { /* (24-bit) */ + vram_b = (uint8_t *)vram_l; for(i = 0; i < numpix; i++) { - pixel = vram_s[i]; - r = (((pixel >> 11) & 0x1f) << 3); - g = (((pixel >> 5) & 0x3f) << 2); - b = (((pixel >> 0) & 0x1f) << 3); - buffer[i * 3 + 0] = r; - buffer[i * 3 + 1] = g; - buffer[i * 3 + 2] = b; + buffer[i * 3 + 0] = vram_b[i * 3 + 2]; /* R */ + buffer[i * 3 + 1] = vram_b[i * 3 + 1]; /* G */ + buffer[i * 3 + 2] = vram_b[i * 3 + 0]; /* B */ } break; } - case(PM_RGB888): { + case(PM_RGB0888): { /* (32-bit) */ for(i = 0; i < numpix; i++) { pixel = vram_l[i]; - r = (((pixel >> 16) & 0xff)); - g = (((pixel >> 8) & 0xff)); - b = (((pixel >> 0) & 0xff)); - buffer[i * 3 + 0] = r; - buffer[i * 3 + 1] = g; - buffer[i * 3 + 2] = b; + buffer[i * 3 + 0] = (((pixel >> 16) & 0xff)); /* R */ + buffer[i * 3 + 1] = (((pixel >> 8) & 0xff)); /* G */ + buffer[i * 3 + 2] = (((pixel >> 0) & 0xff)); /* B */ } break; } + default: { dbglog(DBG_ERROR, "vid_screen_shot: can't process pixel mode %d\n", vid_mode->pm); irq_restore(save); + fs_close(f); free(buffer); return -1; } @@ -98,15 +134,6 @@ int vid_screen_shot(const char *destfn) { irq_restore(save); - /* Open output file */ - f = fs_open(destfn, O_WRONLY | O_TRUNC); - - if(!f) { - dbglog(DBG_ERROR, "vid_screen_shot: can't open output file '%s'\n", destfn); - free(buffer); - return -1; - } - /* Write a small header */ sprintf(header, "P6\n#KallistiOS Screen Shot\n%d %d\n255\n", vid_mode->width, vid_mode->height); @@ -128,5 +155,7 @@ int vid_screen_shot(const char *destfn) { fs_close(f); free(buffer); + dbglog(DBG_INFO, "vid_screen_shot: written to output file '%s'\n", destfn); + return 0; } hooks/post-receive -- A pseudo Operating System for the Dreamcast. |