johannes-fetz / joengine Goto Github PK
View Code? Open in Web Editor NEWJo Engine is an open source 2D and 3D game engine for the Sega Saturn written in C under MIT license
Home Page: http://jo-engine.org/
License: MIT License
Jo Engine is an open source 2D and 3D game engine for the Sega Saturn written in C under MIT license
Home Page: http://jo-engine.org/
License: MIT License
I'll stop annoying you now, just wanted to file another bug report.
For my next project I want to use palette swaps for my characters and use 480i mode. "demo - hardcoded image" sets a palette for an 8bit sprite. When compiled for standard resolution the demo works. When I added "JO_480p = 1" to the makefile the 8 bit image still displays, but it is no longer using the palette.
Is this an issue with Jo Engine or with SGL?
It looks like the engine doesn't currently compile if SGL is disabled. I had quite a few errors and a lot of VDP2 code calls sl* functions without an ifdef and alternative definition. Also, removing JO_COMPILE_USING_SGL from a project still ends up defining it because the code will set it to 1 if it doesn't exist.
Low priority stuff, just wanted to document and provide some feedback.
I'm working through the audio demo, trying to understand how to play CD tracks.
There is no longer a sl_coff.cue. Instead there is a game.cue. Game.cue references track 01 and track 02 so I'm stumped as to why the jo_audio_play_cd_track(3, 3, true) specifies track 3. The other thing I don't understand is that the demo works as is even though there is no track 03 in the cue file. The CD tracks plays. My game.cue for reference:
FILE "game.iso" BINARY TRACK 01 MODE1/2048 INDEX 01 00:00:00 POSTGAP 00:02:00 FILE "track1.wav" WAVE TRACK 02 AUDIO PREGAP 00:02:00 INDEX 01 00:00:00
2) There isn't any documentation that I could see regarding how to add a CD track. Eventually I figured out that you have to add additional wav files into the source code directory and after compiling the game.cue is made.
3) I would suggest moving the tracks into a separate folder ("TRACKS") or something similar so it doesn't clutter up the main directory. I can imagine a game with 20+ tracks getting messy.
4) It's not obvious to me how the tracks are listed in the game.cue. It is not alphabetical as I would assume. I had a TRACK1.WAV, TRACK2.WAV, TRACK3.WAV and in the game.cue they were listed in reverse order. Perhaps the cue generator is looking at the timestamps? I would suggest alphabetizing the tracks. Also this should be documented somewhere.
5) The outputted cue + iso is an obscure format and does not play in Yabause. I'm struggling to figure out how to burn/convert this on Linux. Is it possible to use another format such as bin/cue? What about a single iso file somehow?
I'll stop spamming you now ;)
Hi Johannes,
I was looking at different resolutions for Jo Engine and I just wanted to document my thoughts, I don't expect you to change anything. I am not an expert on this so I could very well be completely wrong.
Hi Johannes,
I would like to request the addition of a function that restarts the Saturn. I grepped through Jo's source and found jo_core_disable_reset() and jo_core_enable_reset() but that's not quite what I'm looking for.
Someone from the SX discord recommended the following code to reboot: ((volatile void()(void))0x600026C)();.
Hi Johannes,
For my newest project I am making use of Jo Engine's backup functions. I would like to request the addition of a wrapper to BUP_Dir() so I can list the saves on the backup medium.
BUP_Dir's prototype is: Sint32 BUP_Dir(Uint32 device,Uint8 *fname,Uint16 dirsize, BupDir *dir). On success the dir array is filled out a list of filenames on the save medium. Thanks in advance.
Hi Johannes,
Players 1-6 are working with "static __jo_force_inline bool jo_is_input_key_down(const int port, const jo_gamepad_keys) however players 7-12 are broken.
These work:
jo_is_input_key_down(0, JO_KEY_LEFT)) // player 1
jo_is_input_key_down(1, JO_KEY_LEFT)) // player 2
jo_is_input_key_down(2, JO_KEY_LEFT)) // player 3
jo_is_input_key_down(3, JO_KEY_LEFT)) // player 4
jo_is_input_key_down(4, JO_KEY_LEFT)) // player 5
jo_is_input_key_down(5, JO_KEY_LEFT)) // player 6
These do not work:
jo_is_input_key_down(6, JO_KEY_LEFT)) // player 7
jo_is_input_key_down(7, JO_KEY_LEFT)) // player 8
jo_is_input_key_down(8, JO_KEY_LEFT)) // player 9
jo_is_input_key_down(9, JO_KEY_LEFT)) // player 10
jo_is_input_key_down(10, JO_KEY_LEFT)) // player 11
jo_is_input_key_down(11, JO_KEY_LEFT)) // player 12
The fix is to add 9 to the port number if the port >= 6.
Fix:
#define SECOND_MULTITAP_OFFSET 9
jo_is_input_key_down(6 + SECOND_MULTITAP_OFFSET, JO_KEY_LEFT)) // player 7
jo_is_input_key_down(7 + SECOND_MULTITAP_OFFSET, JO_KEY_LEFT)) // player 8
jo_is_input_key_down(8 + SECOND_MULTITAP_OFFSET, JO_KEY_LEFT)) // player 9
jo_is_input_key_down(9 + SECOND_MULTITAP_OFFSET, JO_KEY_LEFT)) // player 10
jo_is_input_key_down(10 + SECOND_MULTITAP_OFFSET, JO_KEY_LEFT)) // player 11
jo_is_input_key_down(11 + SECOND_MULTITAP_OFFSET, JO_KEY_LEFT)) // player 12
I've glanced at input.h and input.c and there are a lot of functions that need to be fixed. Basically any function that takes in a "const int port" needs to have this fix implemented. I prototyped a fix for jo_is_input_available() as follows:
`#define SECOND_MULTITAP_OFFSET 9
static __jo_force_inline bool jo_is_input_available(const int port)
{
int adjustedPort = port;
if(adjustedPort >= 6)
{
adjustedPort += SECOND_MULTITAP_OFFSET;
}
#if JO_COMPILE_USING_SGL
return (Smpc_Peripheral[adjustedPort].id != PER_ID_NotConnect);
#else
return (jo_inputs[adjustedPort].id != PER_ID_NotConnect);
#endif
}
`
I have pulled the latest joengine trunk. When I try to compile any of the Samples they no longer work. I am on Linux.
make: execvp: ../../Compiler/LINUX/bin/sh-none-elf-gcc-8.2.0: Permission denied
../../Compiler/COMMON/jo_engine_makefile:294: recipe for target 'main.o' failed
make: *** [main.o] Error 127
make: *** Waiting for unfinished jobs....
../../Compiler/COMMON/jo_engine_makefile:294: recipe for target 'sonic.o' failed
make: *** [sonic.o] Error 127
Steps to repro:
Hi Johannes,
I don't expect you to change anything, just wanted to document. Jo Engine doesn't appear to support setting the sample rate for PCM files. As per your comments in "demo - audio\main.c" the Saturn can support both 8000 and 44100 sample rates. However there does not appear to be a place to change the sample rates anywhere.
jo_audio_load_pcm() does not take a sample rate, the jo_sound struct does not contain the sample rate, and jo_audio_play_sound_on_channel() takes an index into the PCM _jo_internal_pcm[JO_SOUND_MAX_CHANNEL] array. This structure contains the sample rate (via some computation in pitch, see Ponut's code: https://github.com/ponut64/68k/blob/47e56ede2ee5bb4979ce85dffc5446ec44f81dd7/jo_demo/pcmsys.c#L207). The pitch doesn't appear to ever be set.
So here are the issues that should be considered:
Thanks as always.
I'm not 100% sure what is happening here but after enabling VDP2 planes, the palette used by jo_printf seems to get corrupted but this is not present in the sample
HI, it would be great to have the latest stable version tagged.
DEGtoANG() is too slow. In my game I call jo_sprite_draw3D_and_rotate() which calls jo_sprite_draw_rotate() which calls slDispSprite(). Before calling slDispSprite the int angle parameter is converted into a degree by calling the DEGtoANG() function. Unfortunately this function is very slow and was introducing frame skips in my program. This is with one sprite being rotated every frame.
DEGtoANG(d) is defined as ((ANGLE)((65536.0 * (d)) / 360.0)).
Swapping it to:
((ANGLE)((182 * (d))
I received a significant speed improvement and my game was no longer experiencing frame skips. The obvious downside is that this is less accurate than what you are currently doing. Credit to @ponut64 for the suggested fix.
On the console or with an emulator that checks that VDP2's cycle pattern allow the display of an NBG, the line scroll demo displays nothing.
The graphics is initialized on NBG1 with a 16 bpp bitmap when jo_core_init
calls jo_core_init_vdp
that calls __jo_init_vdp2
.
NBG1 is then set to an 8bpp tilemap when jo_set_background_8bits_sprite
calls jo_vdp2_set_nbg1_8bits_image
.
The problem is that jo_vdp2_set_nbg1_8bits_image
doesn't update VDP2's cycle pattern that remains set to the value that allows the display of NBG1 as a 16 bpp bitmap. Cycle pattern value displayed by Kronos v2.6.1 in VDP2 debug screen :
A0 = 5555FEEE
A1 = 5555FEEE
B0 = FFFFEEEE
B1 = 044FEEEE
What prevents the display of NBG1 8bpp tilemap is that there's no access for its pattern name (it would show as a nibble set to1).
Adding a call to slScrAutoDisp
at the end of jo_vdp2_set_nbg1_8bits_image
in vdp2.c solves that issue :
void jo_vdp2_set_nbg1_8bits_image(jo_img_8bits *img, int palette_id, bool vertical_flip)
{
__jo_switch_to_8bits_mode();
if (nbg1_cell != JO_NULL)
jo_vdp2_free(nbg1_cell);
slPlaneNbg1(PL_SIZE_1x1);
slCharNbg1(COL_TYPE_256, CHAR_SIZE_1x1);
if (nbg1_map == JO_NULL)
nbg1_map = (unsigned short *)jo_vdp2_malloc(JO_VDP2_RAM_MAP_NBG1, JO_VDP2_MAP_SIZE);
slMapNbg1(nbg1_map, nbg1_map, nbg1_map, nbg1_map);
nbg1_cell = (unsigned char *)jo_vdp2_malloc(JO_VDP2_RAM_CELL_NBG1, img->width * img->height);
slPageNbg1(nbg1_cell, 0, PNB_1WORD | CN_12BIT);
jo_img_to_vdp2_cells(img, vertical_flip, nbg1_cell);
__jo_create_map(img, nbg1_map, palette_id, JO_VDP2_CELL_TO_MAP_OFFSET(nbg1_cell));
JO_ADD_FLAG(screen_flags, NBG1ON);
slScrAutoDisp(screen_flags); // Ensures that NBG1 displays with correct cycle pattern.
}
Resulting cycle pattern :
A0 = 55FEEEEE
A1 = FFFEEEEE
B0 = 1FFFEEEE
B1 = 044FEEEE
In fact, slScrAutoDisp
should be called each time screen_flags
is modified, which isn't the case in NBG1 related functions in vdp2.c.
Hi,
Would be possible to add a new demo to teach us how to create the "rotating the camera" algorithm using joengine ?
Something like using L & R on Burning Rangers, Sonic World (Jam) etc....
Thanks in advance
In jo_engine_makefile
, MKISOFS_FLAGS
contains the flag-sectype 2352
for ISOs . However this appears to not be working.
After compiling with ./compile.sh, the file command is reporting 2048-byte sectors:
game.iso: Sega Saturn disc image: "JO ENGINE " ( , V1.000) (2048-byte sectors)
Expected behavior is 2352-byte sectors. Could this be a Linux only issue?
Hi Johannes,
Hope all is well. I have been working on libslinga. It is an MIT licensed library that attempts to support as many Saturn save backup devices as possible. I would like to make the library as easy to use for Jo Engine and Libyaul users. Please let me know if there's anything you recommend I change for easier integration. Thanks again.
Hi Johannes,
For my Save Game Copier a user is reporting an issue with the Saturn Floppy Disk Drive attachment. The Saturn FDD saves to two partitions (0 and 1). Currently the Jo Engine backup functions do not have a way to select the partition to use. I have created a branch of Save Game Copier which manually sets the device and partition for the floppy drive to use partition 1. See here: https://github.com/slinga-homebrew/Save-Game-Copier/tree/fdd-partition.
It looks like the device id and partition are accessible in the jo_backup_config struct. So one option would be for the jo_backup functions to loop through each of the partitions when doing any read, write, or delete operation. For example something like:
for(int i = 0; i <= backupConfig.partitions; i++)
{
// do bup operation ...
}
What are your thoughts? It would trigger a jo_core_error() if you try to delete a file that is on the device but not correct partition.
Thank you for developing Jo Engine. It has greatly simplified creating Saturn homebrew games.
I would like to request that jo_random() have the ability to take in a seed so that different random numbers are created. From what I have seen jo_random() returns the same numbers in the same order even after you restart the system. I am testing in Yabause.
Looking through the Jo Engine docs there does not appear to be a function to seed the random number generator. I would like to request the addition of "jo_srandom(int seed)" be added to the API. If the seed == 0, then jo_engine should use the Saturn's clock (or another method to generate a random number).
In "Twelve Snakes" I am using rand()\srand() and seeding it with the number of seconds. See https://github.com/slinga-homebrew/Twelve-Snakes/blob/master/main.c#L2018 for reference. I would prefer to use a Jo Engine function to do the equivalent.
Thank you again.
I have tried many things to access NBG0 and NBG3, using the line scroll demo I changed it to jo_vdp2_set_nbg3_8bits_image and changed the make file to disable printf. This worked but when I enable other screens, I am getting corruption.
I would like to simply change the colour of another background other than NBG1 for now, is there an alternative function I can use?
Hi Johannes,
Hope all is well. See attached screenshot.
jo_printf_with_color(0, 0, JO_COLOR_INDEX_White, "JO_COLOR_INDEX_White");
jo_printf_with_color(0, 1, JO_COLOR_INDEX_Black, "JO_COLOR_INDEX_Black");
jo_printf_with_color(0, 2, JO_COLOR_INDEX_Red, "JO_COLOR_INDEX_Red");
jo_printf_with_color(0, 3, JO_COLOR_INDEX_Green, "JO_COLOR_INDEX_Green");
jo_printf_with_color(0, 4, JO_COLOR_INDEX_Yellow, "JO_COLOR_INDEX_Yellow");
jo_printf_with_color(0, 5, JO_COLOR_INDEX_Blue, "JO_COLOR_INDEX_Blue");
jo_printf_with_color(0, 6, JO_COLOR_INDEX_Purple, "JO_COLOR_INDEX_Purple");
As you can see Black text is not printing correctly. I tested the sample ("demo - printf") and I verified that Black is working there. So it's something to do with the fact that I am running in 480i mode + 8bpp palette mode I guess. Weird that all the other colors work though right?
Mostly documenting, not expecting a fix. Thanks again.
Currently, the 8bits tga demo only enables transparent pixels on the Sonic sprite if its transparent color is set to 1 instead of 0.
If the bricks are drawn behind Sonic, they are completely overwritten if Sonic's transparent color is set at 0 :
The modified demo with Sonic transparent pixels working :
demo - 8bits tga transparent color test.zip
This is due to 2 things in tga.c :
Hello,
I am trying to use Jo-Engine on macOS. I have cloned the repository and set up a project but upon running make
I get the following output:
./Compiler/SH_NONE_ELF/bin/sh-none-elf-gcc-8.2.0 main.c -DJO_FRAMERATE=1 -DJO_COMPILE_USING_SGL -DJO_COMPILE_WITH_TGA_SUPPORT -DJO_COMPILE_WITH_FS_SUPPORT -DJO_GLOBAL_MEMORY_SIZE_FOR_MALLOC=524288 -DJO_MAX_SPRITE=255 -DJO_MAX_FILE_IN_IMAGE_PACK=32 -DJO_MAP_MAX_LAYER=8 -DJO_MAX_SPRITE_ANIM=16 -DJO_MAX_FS_BACKGROUND_JOBS=4 -DJO_DEBUG -DJO_PAL_VERSION -fkeep-inline-functions -W -Wall -Wshadow -Wbad-function-cast -Winline -Wcomment -Winline -Wlong-long -Wsign-compare -Wextra -Wno-strict-aliasing --param max-inline-insns-single=50 -fms-extensions -std=gnu99 -fmerge-all-constants -fno-ident -fno-unwind-tables -fno-asynchronous-unwind-tables -fomit-frame-pointer -fstrength-reduce -frerun-loop-opt -Os -nodefaultlibs -nostdlib -fno-builtin -m2 -c -I./jo_engine -flto -I./Compiler/SGL_302j/INC -o main.o
./Compiler/SH_NONE_ELF/bin/sh-none-elf-gcc-8.2.0: ./Compiler/SH_NONE_ELF/bin/sh-none-elf-gcc-8.2.0: cannot execute binary file
I appreciate any help or guidance with resolving this as I would very much like to develop using Jo-Engine on macOS.
Hi Johannes,
Hope all is well. In jo_3d
. in the void jo_3d_set_mesh_polygon_color(jo_3d_mesh * const mesh, const jo_color color, const unsigned int index)
function is hardcoded to always use sprPolygon
. I would like the ability to use sprPolyLine
as well. Thanks in advance.
Hi Johannes,
I'm trying to understand the 8bit TGA demo. What tool did you use to create the TGA? I am trying with GIMP and it's creating 256 color indexes. Is it possible to use 8bpp and have transparencies?
66 // Load a 8 bits ▲ 255 colors (MAX) NOT 256 or it will glitch! ▲ TGA
67 // Instead of JO_COLOR_Transparent, you can pass an index on your palette
68 jo_sprite_add_tga("TEX", "SON8.TGA", JO_COLOR_Transparent);
I was experimenting with the makefile for Jo Engine projects (COMMON/jo_engine_makefile
) and I discovered that removing the flags -ffunction-sections
and -fdata-sections
reduced the size of the compiled executable (sl_coff.bin
) by 75% -- in my case, from 700 kB to 175 kB.
I researched these two flags, and it looks like their intended purpose is to be used with the linker flag -gc-sections
, which strips out unused code. I wasn't able to get this to work. If section GC could be made to work, it might result in an even smaller binary, which would be nice.
However, the way things work now, removing the flags saves a lot of space. If I understand the Saturn hardware correctly, the 500 kB saved represents a quarter of the general-purpose RAM!
Please let me know if my analysis is correct, and if this would be a useful change. I can submit a pull request if you like, but the change is very simple.
jo_clear_screen() doesn't appear to clear the entire screen text in 480i mode. It stops around 40 characters on the X axis (e.g. jo_printf(40, 0, "12345") will not be erased but text prior to will be.
Using jo_clear_background() with JO_COLOR_Magenta, JO_COLOR_SemiMagenta, JO_COLOR_MediumMagenta, or JO_COLOR_DarkMagenta all result in Cyan shades rather than the expected Magenta.
If could suggest a fix, just rename the Magentas to Cyans, since Purple is already close to expected Magenta.
Current image maker only supports 2048 bins. For better MODE support, 2352 with ECC bin is requested. Potentially addressable by updating mkisofs.
I updated to trunk just now, debug builds compile (JO_DEBUG = 1) but release builds (JO_DEBUG = 1) fail to compile.
Here is the compiler error:
../jo_engine/vdp2_malloc.o ../../jo_engine/vdp2_malloc.c: In function 'jo_vdp2_malloc': ../../jo_engine/vdp2_malloc.c:164:13: warning: implicit declaration of function 'jo_core_error'; did you mean 'jo_core_tv_on'? [-Wimplicit-function-declaration] jo_core_error("Out of VDP2 memory"); ^~~~~~~~~~~~~ jo_core_tv_on
Hi Johannes,
I want to catch the ABC+Start key press such that it exits back out to the title screen. Currently when player 1 hits ABC+Start the game freezes. I tried adding an input callback but it looks like the game freezes before it gets there.
How can I handle ABC+Start key press? Thanks in advance.
Hi Johannes,
The start addresses and sizes for the expansion RAM banks appear to be incorrect. In core.c:
static bool jo_init_memory(void)
{
static unsigned char global_memory[JO_GLOBAL_MEMORY_SIZE_FOR_MALLOC];
jo_add_memory_zone(global_memory, sizeof(global_memory));
#ifdef JO_COMPILE_WITH_RAM_CARD_SUPPORT
if (jo_get_extended_ram_cartridge_type() == CART_8MBits)
{
jo_enable_extended_ram_cartridge_support();
jo_set_a_bus_register();
jo_add_memory_zone((unsigned char *)0x2247ffff, 0x180000);
jo_add_memory_zone((unsigned char *)0x2267ffff, 0x180000);
}
else if (jo_get_extended_ram_cartridge_type() == CART_32MBits)
{
jo_enable_extended_ram_cartridge_support();
jo_set_a_bus_register();
jo_add_memory_zone((unsigned char *)0x2247ffff, 0x180000);
jo_add_memory_zone((unsigned char *)0x2267ffff, 0x180000);
jo_add_memory_zone((unsigned char *)0x2287ffff, 0x180000);
jo_add_memory_zone((unsigned char *)0x22a7ffff, 0x180000);
jo_add_memory_zone((unsigned char *)0x22c7ffff, 0x180000);
jo_add_memory_zone((unsigned char *)0x22e7ffff, 0x180000);
jo_add_memory_zone((unsigned char *)0x2307ffff, 0x180000);
}
#endif
#ifdef JO_DEBUG
// We check if the Work RAM for malloc is on the user RAM area
// It's not perfect but better than nothing
if (!JO_IS_ARRAY_INSIDE_USER_RAM_AREA(global_memory))
return (false);
#endif
return (true);
}
For the 8Mbit cartridge the total ram should equal 1 MB. The size of each bank should be 0x80000 (512k) not 0x180000 (1.5MB). The start address should be 0x22400000. The RAM appears to be in two separate non-adjacent banks so it requires two calls:
jo_add_memory_zone((unsigned char *)0x22400000, 0x80000);
jo_add_memory_zone((unsigned char *)0x22600000, 0x80000);
For the 32 Mbit cartridge the total RAM should equal 4 MB. As the RAM appears to be adjacent it should be able to do a single call:
jo_add_memory_zone((unsigned char *)0x22400000, 0x200000);
Thanks in advance.
Thanks to Knight0fDragon for spotting.
With Jo's built-in input sampling functions, the inputs are sampled within the frame (between vblank).
However, in order to properly sample inputs on Saturn, you should check for them in time with vblank.
This problem sometimes causes inputs to be dropped, because the state change of input was false when checked. We checked for it within the frame but its period of being pressed or not passed on the next vblank, so we missed the key being pressed (if it was only checked or held for 1 frame).
jo_add_memory_zone() allows the user to increase the size of the heap. I have used it in multiple projects and think others would find it useful. I would recommend adding the prototype to malloc.h and adding doxygen information for the function.
Hi Johannes,
jo_sprite_enable_horiontal_flip() and jo_sprite_enable_vertical_flip() no longer appear to be working. I have tried testing within "demo - shooter". "demo - sonic" also appears to have similar issues.
Thanks.
as the title states, thank you!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.