New 32x game in development!

Importante releases or news for the communauty

Moderator: KanedaFr

Post Reply
matthewnimmo
Very interested
Posts: 87
Joined: Thu Jan 07, 2021 8:04 pm

New 32x game in development!

Post by matthewnimmo » Thu Jan 19, 2023 4:53 am

Everyone:

First off, I want to thank everyone who made this place possible for great minds to post and help smaller minds like myself achieve big dreams! Secondly, I want to thank all those great minds who has been helping me thus far and continue to help me in this journey.

For years now I've been wanting to develop a 32x game and many have said, just write a Genesis game instead using the SGDK. While I still may do that in the future, I've decided that I'm going to officially write a 32x game instead. Now, before everyone here reads this and checks out thinking "ok here's another guy who's feeling nostalgia about his game rearing and this isn't going anywhere" I'm a solutions architect by profession that started off as a developer. I've actually launched my own gaming studio in 2016 and have launched 3 games (none of which make me rich, which is not the point. I just enjoy the creating process!) The last game was launch in IOS and Android devices in 2020. So, Lord willing, I'm committed to make this a reality.

Now after establishing some cred I am now going to humble myself. Developing against retro tech is no joke and far removed from my C# and Java development days. There are many more smarter people than I on this forum who have wells of C and ASM knowledge that I hope to glean some wisdom from. I make no claims that I'm God's gift to programming lol. So, I'll be learning on this journey along the way that will dust off my C skills and establish new ASM foundations.

TO THE GAME!

I've always been a fan of the 2D RPG Genre and seeing that the 32x really didn't have one (think some claims that Blackthorne is the closest) that's what I'm going to be making. A lot of my inspiration will come from Dragon Warrior from Nes glory days as well as Shining Force 1 and 2. Plus some oddities that you would find throughout the game such as random game events. I plan on having an open world that your player can roam around like you'd see within Dragon Warrior but encounters to look extremely similar to those from Shining Force. I plan to have Parallax scrolling effects over the world as "events/seasons/map" changes. I plan to use some sprite scaling (mainly with attack animations). I plan to have save state. I plan to have procedural generated items with varing stats. That's a good taste for now!

As for the name of the Game, still considering a few that I'll keep close to the chest for now. How do I plan to launch? I will distribute Roms via download and hopefully partner up with someone(s) to print physical cartridges/32x boxes as well.

Tech that I'll be using for this build

1) Chilly's 32x Toolchain v 12.1.0 as of writing this today (may change if new updates occur)
2) Distilling Vic and Chilly's work from the D32xr project produce a barebones skeleton. This should have a lot of great foundation for me to work with. Unless Vic beats me to it, I'll plan on making that skeleton open for others to download and create as well!
3) Inspiration from Vic's Tilemapper for the open world
4) Inspiration from Ammianus' works
5) Asesprite, GIMP, Tiled, MtPaint from my graphics needs
6) Audio - audacity and sox

Lastly, you all will see all my victories and struggles throughout this process! Hopefully others may see these postings and inspire to develop games as well!

Thank you all!
Last edited by matthewnimmo on Thu Jan 19, 2023 11:28 pm, edited 1 time in total.

matthewnimmo
Very interested
Posts: 87
Joined: Thu Jan 07, 2021 8:04 pm

Re: New 32x game in development!

Post by matthewnimmo » Thu Jan 19, 2023 5:24 am

In a recent post about distilling down the D32xr project into a bare skeleton that I can base my game on. I had asked Chilly what are the core files that I would need that are not specific to the Doom game and below is a quote from Chilly that I think would be extremely helpful for others.
Chilly Willy wrote:
Tue Jan 17, 2023 11:08 pm
src-md folder
-----------------
Makefile - makes the 68000 code/data block used by the game. The binary block of data generate will be included into the 32X side at the proper place.

crt0.s - main start of the 68000 code. The 68000 jumps to _start after the 32X has been started. _start clears the ram, copies the data segment into ram, initializes the MD hardware, and then calls the 68000 _main entry. It contains all the assembly routines needed by the 68000 to handle communication between the 32X and SCD.

main.c - holds the main() entry point. It tries to initialize the CD, if present. It also tries to initialize the MegaSD cart (allows playing CDDA music like the CD) if present. then calls do_main, which is in crt0.s.

cd .s - the code loaded into the SCD program ram that controls the SCD. Currently just checks for an audio CD and waits for commands from the MD to play tracks.

everdrive.c - initializes the MED, if present. This sets a flag that tells the game we can use MED Pro resources for bank selection, save ram, etc.

font.s - the default ASCII font used by the MD side of things.

kos.s - the Kosinski decompression routine used to decompress the SCD BIOS when initializing the SCD.

megasd.c - initializes the MegaSD, if present. Also holds the routines to play CD tracks on the MegaSD instead of the SCD.

vgm.c - some VGM helpers routines. Initializes the lzss decompression used to decompress the compressed VGM files that D32XR uses. Also has a function to fetch the next buffer worth of decompressed VGM data.

vgm_player.s - my VGM player code. Was derived from the player code I wrote for the NeoMyth cart menu. It's aimed at playing v1.60+ VGM files (no individual PCM store commands, instead it uses the new stream commands).

xvprintf.c - a stripped down vprintf() function for faster debug string printing on the MD side.


Main folder
---------------
Makefile - the main makefile. It will make the 68000 block, then make the 32X code (which includes the 68000 block inside it), then concatenate the wad file, then pad the rom to the closest 512KB to keep the size nice and round.

32x.h - most of the 32X hardware includes for the IO and SH2.

crt0.s - this starts the rom. It starts with a standard Sega MD rom header, followed by a vector table for the 68000 that redirects the normal 68000 exceptions to the new location of the 68000 code in the 32X. That is followed by the standard 32X header that tells you things like where the data is at, where the primary and secondary sh2 start vectors are, and where the primary and secondary sh2 exception tables are. This is followed by the 68000 security block, which is merely code that initializes the 32X, then fall into the 68000 _start, which is where the 68000 block is included at. This is then followed by the primary and secondary exception tables. Then follows all the sh2 exception handling code, as well as the startup code. The primary startup code does some initialization, then jumps to main() on the 32X side of things. The secondary startup code does some initialization (less than the primary), and then jumps to secondary().

marshw.c - has much of the low-level 32X functions, like setting up the frame buffers, flipping the frame buffers, polling the mouse, the main 32X initialization routine, and lots of glue routines that interface between 32X C functions, and sending commands to the MD and receiving responses back.

marsnew.c - holds all the system specific functions Doom uses to interface with the specific system Doom is running on. Things like processing the controller input, getting the tick count, setting the palette, doing network functions, etc. This file also holds Mars_Secondary(), which is where the secondary sh2 runs. This initializes any secondary sh2 hardware like the DMA, then enters a loop to process commands sent by the primary sh2.

marsonly.c - this corresponds to jagonly.c - the main entry point of the Doom game. It has the 32X side main() function entry point. This does any system setup, reads the save ram, sets up the video, and calls D_DoomMain(), the start of Doom proper. This file also holds the secondary() function, which just calls Mars_Secondary().

marssave.c - holds the save/load functions used by Doom. Calls lower level load/save functions to do its work. Nothing really 32X specific here.

marssound.c - this holds the Doom sound effects and music function routines, converting them to 32X code to send commands to the MD/CD side to play music, and builds a list of channels for playing sound effects via the 32X PWM. This file has the DMA done interrupt handler function that drives the PWM sound double buffer. It also handles command interrupts sent by the 68000, which are used to send info about PCM streams to play from the VGM file. Those are mixed with the sound effects.

sh2_draw.s - the main hand-tuned assembly for drawing in Doom. This is important for people doing their own drawing as it shows how to place mov commands on the proper boundaries for better speed. Vic and I spent A LOT of time on these routines to wring out every last drop of blood this turnip can offer. :D

sh2_fixed.s - fixed point multiply and divide code. The divide uses the hardware divider in the sh2 rather than the normal divide program code the sh2 uses. Note that the Doom code doesn't call these very often as we made different inline code for doing these. In fact, the divide is normally broken into two pieces - starting the divide, and then a separate function to fetch the result so that you can do other things before fetching the result of the divide.

sh2_mixer.s - the main sound mixing code. It will mix normal 8-bit PCM samples, and 16-bit ADPCM samples, which are decompressed on the fly by the sh2 while mixing. We suggest not trying to mix more than 5 or 6 ADPCM samples at the same time as that can consume some cpu time, slowing the secondary sh2 elsewhere in the game.



And that's pretty much all the 32X specific files and what they handle. The rest is Doom code.

And Another section from Chilly
Chilly Willy wrote:
Tue Jan 17, 2023 11:21 pm
A follow on post of some code from D32XR about some things you may want to do in your own code.

semaphores

Code: Select all

static char seg_lock = 0;

static void R_LockSeg(void)
{
    int res;
    do {
        __asm volatile (\
        "tas.b %1\n\t" \
            "movt %0\n\t" \
            : "=&r" (res) \
            : "m" (seg_lock) \
            );
    } while (res == 0);
}

static void R_UnlockSeg(void)
{
    seg_lock = 0;
}
inline fixed mul and normal integer div

Code: Select all

fixed_t	FixedMul (fixed_t a, fixed_t b);
fixed_t	FixedDiv (fixed_t a, fixed_t b);
#ifdef MARS
#define FixedMul2(c,a,b) do { \
        int32_t t; \
       __asm volatile ( \
            "dmuls.l %2, %3\n\t" \
            "sts mach, %1\n\t" \
            "sts macl, %0\n\t" \
            "xtrct %1, %0\n\t" \
            : "=r" (c), "=&r" (t) \
            : "r" (a), "r" (b) \
            : "mach", "macl"); \
        } while (0)

static inline fixed_t IDiv(fixed_t a, fixed_t b)
{
	fixed_t res;
	uintptr_t div;
	__asm volatile(
		"mov #-128, %1\n\t"
		"add %1,%1\n\t"
		"mov.l %3,@%1 /* set 32-bit divisor */\n\t"
		"mov.l %2,@(4,%1) /* set 32-bit dividend, start divide */\n\t"
		"/* note - overflow returns 0x7FFFFFFF or 0x80000000 after 6 cycles\n\t"
		"no overflow returns the quotient after 39 cycles */\n\t"
		"mov.l @(4,%1),%0 /* return 32-bit quotient */\n\t"
		: "=r" (res), "=&r"(div)
		: "r" (a), "r"(b)
	);
	return res;
}
#else
#define FixedMul2(c,a,b) ((c) = FixedMul(a,b))
#define IDiv(a,b) ((a) / (b))
#endif
starting an integer div

Code: Select all

#ifdef MARS
        volatile int32_t t;
        __asm volatile (
           "mov #-128, r0\n\t"
           "add r0, r0 /* r0 is now 0xFFFFFF00 */ \n\t"
           "mov #0, %0\n\t"
           "mov.l %0, @(16, r0) /* set high bits of the 64-bit dividend */ \n\t"
           "mov.l %1, @(0, r0) /* set 32-bit divisor */ \n\t"
           "mov #-1, %0\n\t"
           "mov.l %0, @(20, r0) /* set low  bits of the 64-bit dividend, start divide */\n\t"
           : "=&r" (t) : "r" (scalefrac) : "r0");
#else
        fixed_t scale = scalefrac;
#endif
ending the div and fetching the result

Code: Select all

#ifdef MARS
        __asm volatile (
            "mov #-128, r0\n\t"
            "add r0, r0 /* r0 is now 0xFFFFFF00 */ \n\t"
            "mov.l @(20, r0), %0 /* get 32-bit quotient */ \n\t"
            : "=r" (iscale) : : "r0");
#else
        iscale = 0xffffffffu / scale;
#endif

cero
Very interested
Posts: 338
Joined: Mon Nov 30, 2015 1:55 pm

Re: New 32x game in development!

Post by cero » Thu Jan 19, 2023 8:28 am

RPGs require a lot of content, basically you have two big projects here (32x port and the game itself on a meta-level). Perhaps do a proto of the game at a higher level first to see if you can create enough & good enough content.

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Re: New 32x game in development!

Post by Chilly Willy » Thu Jan 19, 2023 8:50 pm

This should be interesting. The more 32X games, the better. I was always a big fan of the 32X, and was sad it got short shrifted by Sega back in the day. They could have at least waited until Rayman 32X was released! :lol:

As for audio, I like using audacity and sox. Sox is a small command line converter for audio, while audacity is a big audio editor program. Sox is good if you just need to convert the format or sample rate, while audacity is good if you need to make edits to the audio.

matthewnimmo
Very interested
Posts: 87
Joined: Thu Jan 07, 2021 8:04 pm

Re: New 32x game in development!

Post by matthewnimmo » Thu Jan 19, 2023 11:27 pm

Chilly Willy wrote:
Thu Jan 19, 2023 8:50 pm
This should be interesting. The more 32X games, the better. I was always a big fan of the 32X, and was sad it got short shrifted by Sega back in the day. They could have at least waited until Rayman 32X was released! :lol:

As for audio, I like using audacity and sox. Sox is a small command line converter for audio, while audacity is a big audio editor program. Sox is good if you just need to convert the format or sample rate, while audacity is good if you need to make edits to the audio.
Thanks Chilly! Ill add that to the list (going to edit my OP with that now)

Yes! So much potential with the 32x. They just shot themselves in the foot.

Im combing through the files you mentioned as core adn started compiling. Each attempt to compile showed other files that each one of those depends on (such as sounds) so ive been systematically pulling those in as well. I’ve purposely been commenting out anything in the marsonly that starts calls to doom specifics d_doom main. There is just more dependencies than I originally thought for example (for the time being I’ve commented out about everything in the secondary() as nearly each switch statement lead to more files id have to bring in)

My hope is to get it to compile a rom that produces a blank screen with as little extra files beyond the core brought in. Then draw some simple graphics, start some sounds/music, handle some inputs

Ive done the same with the old 4.5.2 toolchain and that worked well! But I’ve abandoned that for the new 12.1:)

matthewnimmo
Very interested
Posts: 87
Joined: Thu Jan 07, 2021 8:04 pm

Re: New 32x game in development!

Post by matthewnimmo » Fri Jan 20, 2023 9:19 pm

Hey Chilly! Why are there a bunch of dwarves in my compile! :) I noticed these little guys when i build the D32xr project as well, so I can safely say it's nothing i've introduced.
dwarves.png
dwarves.png (63.36 KiB) Viewed 114139 times
So far i've got a distilled version down compiling. So i'm going to do some more cleaning and try to get something to draw on the screen and if i get lucky...some sound!

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Re: New 32x game in development!

Post by Chilly Willy » Sat Jan 21, 2023 11:46 pm

Yeah, the very latest versions of gcc generate a lot of warnings related to debug info. Haven't bothered to look into that as it has no actual bearing on the program itself. 9.x didn't do that from what I remember, but 12.x does. I THINK it's related to moving functions into sdram. Oh yeah! That's probably also something important I should talk about. Certain functions will work better/faster if they're in sdram instead of rom. You can do this with a function attribute. Use the function attribute with the function prototype to declare the function in ram... like this

Code: Select all

#define MARS_ATTR_DATA_CACHE_ALIGN __attribute__((section(".data"), aligned(16), optimize("O1")))


char Mars_UploadPalette(const uint8_t* palette) MARS_ATTR_DATA_CACHE_ALIGN;
You don't HAVE to make a define for attributes, but if you use them a lot, the define helps. In the case above, the function has three attributes:
1 - it's in the .data segment (which is in sdram)
2 - it's 16 byte aligned so that it starts right at the start of a cache line
3 - the optimization level is 1

Attribute 3 is important for any code that directly bangs on the 32X hardware (beyond the communication registers). Gcc will optimize code in such a way that writes to hardware can occur out of order, messing up setting the hardware if order is important (and it usually is). You should probably read up on memory fences. PC code will have memory fences around accesses to hardware, but gcc doesn't define a memory fence for the SH platform. Instead, you need to compile such code at -O1 level to avoid reordering the code. Most game code will not need this, so you can leave out the optimization attribute.

You'll find various Doom functions are moved to sdram to make them faster.

Code: Select all

static fixed_t R_PointToDist(fixed_t x, fixed_t y) ATTR_DATA_CACHE_ALIGN;
We have a number of different function attribute defines depending on what we want.

Code: Select all

#ifdef MARS
#define ATTR_DATA_OPTIMIZE_NONE __attribute__((section(".data"), aligned(16), optimize("O1")))
#define ATTR_DATA_CACHE_ALIGN __attribute__((section(".data"), aligned(16), optimize("Os")))
#define ATTR_OPTIMIZE_SIZE __attribute__((optimize("Os")))
#define ATTR_OPTIMIZE_EXTREME __attribute__((optimize("O3", "no-align-loops", "no-align-functions", "no-align-jumps", "no-align-labels")))
#else
#define ATTR_DATA_OPTIMIZE_NONE
#define ATTR_DATA_CACHE_ALIGN
#define ATTR_OPTIMIZE_SIZE
#define ATTR_OPTIMIZE_EXTREME
#endif
Small optimization is used in some cases so that it uses the least cache space, meaning the code is more likely to always be present in cache. The no-align attributes are used with -O3 level because gcc for the SH will stick alignments in the code that don't copy to ram correctly, making the ram function fault. That's an important part of aligning code in the assembly files. Look at this snippet:

Code: Select all

        and     r4,r0           /* (frac >> 16) & heightmask */

        .p2alignw 2, 0x0009
do_col_loop_low:
        mov.b   @(r0,r5),r0     /* pix = dc_source[(frac >> 16) & heightmask] */
See that .p2alignw command? That pads out to the required alignment inserting 0x0009 words to do so. 0x0009 is the SH nop opcode.

Also in assembly, you use the .data keyword to put code (and data) into the data segment. Look at crt0.s to get an example. The vector tables, exception handlers, and a number of other routines are in sdram. All the assembly drawing routines are in sdram.

matthewnimmo
Very interested
Posts: 87
Joined: Thu Jan 07, 2021 8:04 pm

Re: New 32x game in development!

Post by matthewnimmo » Sun Jan 22, 2023 5:19 pm

Chilly Willy wrote:
Sat Jan 21, 2023 11:46 pm
... Certain functions will work better/faster if they're in sdram instead of rom. You can do this with a function attribute. Use the function attribute with the function prototype to declare the function in ram...
Chilly! This is fantastic and I swear you were reading my mind! I saw these around function attributes and wondered what these were for! So, I have a few questions. First, you mentioned certain functions will work better/faster if they're in sdram? How do I determine which functions are good candidates?

Second question is a little more involved and related to something else. So, I've got the latest code compiled and essentially a "flying tin can" right now. I've created a few more objects to test with one called drawing.o which has a drawsprite function (I don't quite understand all the drawing sprite functionality in the current code as it seems to be heavily built around doom specifics...but maybe i'm missing something there.

Below is my drawsprite function. technically, i didn't write this; but was from another example that worked well in my previous testing.

Code: Select all

void drawSprite(u32* spriteBuffer, u16 x, u16 y, u16 xWidth, u16 yWidth)
{
	vu32* frameBuffer = (vu32*)&MARS_OVERWRITE_IMG;
	// dst frame buffer pointer (X + Y offseted, need to divide by 4 as we have 32 bit pointer here)
	vu32* dst = &frameBuffer[(0x100 + (y * 320) + (x + 256)) / 4];
	// src sprite pointer
	u32* src = spriteBuffer;

	const u16 qwidth = xWidth / 4;
	const int dstStep = 80 - qwidth;

	u16 row = yWidth;

	while (row--)
	{
		u16 col = qwidth;

		while (col--) *dst++ = *src++;

		dst += dstStep;
	}
}
I've I believe I have also successfully pulled out the bitmap image details from my sprites.bmp file with this line of code. Now, it prints it to screen upside down lol, so there's that; but at least it prints.

Code: Select all

extern char sprite[]; //pal is defined in my images.o as sprite.bmp
unsigned short* b = (unsigned short*)((int)sprite+ 0x431);
And now the interesting part that I think i'm still missing. Below is the code that I "believe" should be pulling the palette information from my .bmp file and I pass that into the I_SetPalette() function within marshw.

Code: Select all

extern char sprite[]; //pal is defined in my images.o as sprite.bmp
unsigned short* p = (unsigned short*)((int)sprite+ 0x36);
And here is the code within marshw file takes that palette information and puts into CRAM.

Code: Select all

char Mars_UploadPalette(const uint8_t* palette)
{
	int	i;
	unsigned short* cram = (unsigned short *)&MARS_CRAM;
	int16_t br = mars_brightness;

	if ((MARS_SYS_INTMSK & MARS_SH2_ACCESS_VDP) == 0)
		return 0;

	for (i = 0; i < 256; i++) {
		int16_t r = br + *palette++;
		int16_t g = br + *palette++;
		int16_t b = br + *palette++;

		if (r < 0) r = 0; else if (r > 255) r = 255;
		if (g < 0) g = 0; else if (g > 255) g = 255;
		if (b < 0) b = 0; else if (b > 255) b = 255;

		unsigned short b1 = ((b >> 3) & 0x1f) << 10;
		unsigned short g1 = ((g >> 3) & 0x1f) << 5;
		unsigned short r1 = ((r >> 3) & 0x1f) << 0;
		cram[i] = r1 | g1 | b1;
	}

	return 1;
}
After doing all of that, my sprite on the screen is still messed up with its colors at it should be looking like this below.
9.png
9.png (10.14 KiB) Viewed 114063 times
Instead it looks like this :( when that palette is loaded that I "thought" i extracted from my .bmp file
12.png
12.png (11.23 KiB) Viewed 114063 times
So, my second question is this? What i'm i still doing wrong lol? Am i not pulling the palette info correctly? I thought the palette info started at offset 0036h?

My last question is around the existing drawing functions within the doom code. I see a lot of reference to WAD functionality? I'm guessing that all the image/music/song data is tied up in the WAD file that gets dumped from an actual Doom cart? And that we are pulling that propriatery binary into our code to draw images, play songs and music? If so, how do i generalize those functions to pull from images, sfx, and music that I apply (like i'm doing with images.o with my sprite.bmp)? Or is it best to do what im doing and that is create my own library like drawing.o with my own drawing functions and another one for all my sounds functions?

Thanks again for all the help! hope this makes sense:)

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Re: New 32x game in development!

Post by Chilly Willy » Sun Jan 22, 2023 6:03 pm

matthewnimmo wrote:
Sun Jan 22, 2023 5:19 pm
Chilly! This is fantastic and I swear you were reading my mind! I saw these around function attributes and wondered what these were for! So, I have a few questions. First, you mentioned certain functions will work better/faster if they're in sdram? How do I determine which functions are good candidates?
Time the functions and see where most of the time is spent. In Doom, quite a bit of time is spent in going through the BSP table, so those functions are mostly all in ram. Time the functions in and out of ram to make sure it really makes a difference. Try using high optimization, and then small optimization. Some functions are faster with less-fast small code than with big, unrolled, excessively optimized code due to small caches. Don't put BIG functions in ram - remember that you only have 256KB!
Second question is a little more involved and related to something else. So, I've got the latest code compiled and essentially a "flying tin can" right now. I've created a few more objects to test with one called drawing.o which has a drawsprite function (I don't quite understand all the drawing sprite functionality in the current code as it seems to be heavily built around doom specifics...but maybe i'm missing something there.


I've I believe I have also successfully pulled out the bitmap image details from my sprites.bmp file with this line of code. Now, it prints it to screen upside down lol, so there's that; but at least it prints.


And now the interesting part that I think i'm still missing. Below is the code that I "believe" should be pulling the palette information from my .bmp file and I pass that into the I_SetPalette() function within marshw.


And here is the code within marshw file takes that palette information and puts into CRAM.

Code: Select all

char Mars_UploadPalette(const uint8_t* palette)
{
	int	i;
	unsigned short* cram = (unsigned short *)&MARS_CRAM;
	int16_t br = mars_brightness;

	if ((MARS_SYS_INTMSK & MARS_SH2_ACCESS_VDP) == 0)
		return 0;

	for (i = 0; i < 256; i++) {
		int16_t r = br + *palette++;
		int16_t g = br + *palette++;
		int16_t b = br + *palette++;

		if (r < 0) r = 0; else if (r > 255) r = 255;
		if (g < 0) g = 0; else if (g > 255) g = 255;
		if (b < 0) b = 0; else if (b > 255) b = 255;

		unsigned short b1 = ((b >> 3) & 0x1f) << 10;
		unsigned short g1 = ((g >> 3) & 0x1f) << 5;
		unsigned short r1 = ((r >> 3) & 0x1f) << 0;
		cram[i] = r1 | g1 | b1;
	}

	return 1;
}
After doing all of that, my sprite on the screen is still messed up with its colors at it should be looking like this below.
9.png

Instead it looks like this :( when that palette is loaded that I "thought" i extracted from my .bmp file
12.png

So, my second question is this? What i'm i still doing wrong lol? Am i not pulling the palette info correctly? I thought the palette info started at offset 0036h?
The palette is stored as B, G, R, A (where alpha may be optional). You're reading it backwards and not skipping the A byte. Also, BMP data is stored bottom to top.
My last question is around the existing drawing functions within the doom code. I see a lot of reference to WAD functionality? I'm guessing that all the image/music/song data is tied up in the WAD file that gets dumped from an actual Doom cart? And that we are pulling that propriatery binary into our code to draw images, play songs and music? If so, how do i generalize those functions to pull from images, sfx, and music that I apply (like i'm doing with images.o with my sprite.bmp)? Or is it best to do what im doing and that is create my own library like drawing.o with my own drawing functions and another one for all my sounds functions?
Data assets are stored in the wad file as lumps. If you use your own art and music and sounds, it doesn't matter if it's stored as a wad or not. A lump is merely the data in raw format. A sound effect lump is just raw PCM... or maybe raw WAV file as D32XR understands WAV format for PCM and ADPCM. You don't need to use the wad handling, you just need to know/locate in your own manner where the lumps holding the data are at.

And yes, the sh2_draw.s file is for drawing data in Doom graphic format. I don't expect people to use that directly, I expect them to see how we draw to the 32X in the fastest way possible, and adapt that to their own graphic format. Start with a generic C drawing routine like you mention, then optimize the shit out of it once you have everything working.

matthewnimmo
Very interested
Posts: 87
Joined: Thu Jan 07, 2021 8:04 pm

Re: New 32x game in development!

Post by matthewnimmo » Sun Jan 22, 2023 9:52 pm

Chilly Willy wrote:
Sun Jan 22, 2023 6:03 pm
...

The palette is stored as B, G, R, A (where alpha may be optional). You're reading it backwards and not skipping the A byte. Also, BMP data is stored bottom to top.

...
Chilly, this is great (I'm definitely leveling up!) This one section may I go a little deeper on my questions here? I'm sure others here that read this maybe "OMG" this noob! But hey, I've got to start somewhere :) Learning how to crawl before I can walk. If this was in C# and I had all the memory in the world, this would be a different story. The things we take for granted with higher level languages...

So, would below be how I get to the alpha section? And then I'm guessing I need a means of getting all the bytes in between p and a correct?

Code: Select all

unsigned short* p = (unsigned short*)((int)pal + 0x36);
unsigned short* a = (unsigned short*)((int)pal + 0x42);
Would some loop that starts at one pointer until it reaches the next pointer do the trick? And each step of the way store each value in a new char[]? Something like below (still working on it)

Code: Select all

int len = 0;
	char[] newPal;
	while (p != a)
	{
		len = strlen(newPal);
		newPal[len] = *p++;
		newPal[len + 1] = '\0';
	}
Hopefully my thinking isn't too laughable lol.

Thanks again,

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Re: New 32x game in development!

Post by Chilly Willy » Sun Jan 22, 2023 11:22 pm

The palette code you had was fine, but you need to fetch B first, then fetch G, then fetch R, then skip the next byte for each of the 256 entries.

matthewnimmo
Very interested
Posts: 87
Joined: Thu Jan 07, 2021 8:04 pm

Re: New 32x game in development!

Post by matthewnimmo » Mon Jan 23, 2023 5:02 am

Chilly Willy wrote:
Sun Jan 22, 2023 11:22 pm
The palette code you had was fine, but you need to fetch B first, then fetch G, then fetch R, then skip the next byte for each of the 256 entries.
Thanks Chilly! You are referring to this code block below yes? If so, I didn't write that it was part of the marshw.c and I'll be honest, i'm a little lost on the binary operations that the author is doing (I need to study up more on binary operations and how they related to colors).

Code: Select all

char Mars_UploadPalette(const uint8_t* palette)
{
	int	i;
	unsigned short* cram = (unsigned short *)&MARS_CRAM;
	int16_t br = mars_brightness;

	if ((MARS_SYS_INTMSK & MARS_SH2_ACCESS_VDP) == 0)
		return 0;

	for (i = 0; i < 256; i++) {
		int16_t r = br + *palette++;
		int16_t g = br + *palette++;
		int16_t b = br + *palette++;

		if (r < 0) r = 0; else if (r > 255) r = 255;
		if (g < 0) g = 0; else if (g > 255) g = 255;
		if (b < 0) b = 0; else if (b > 255) b = 255;

		unsigned short b1 = ((b >> 3) & 0x1f) << 10;
		unsigned short g1 = ((g >> 3) & 0x1f) << 5;
		unsigned short r1 = ((r >> 3) & 0x1f) << 0;
		cram[i] = r1 | g1 | b1;
	}

	return 1;
}
I'm more familiar with this loadpalette function from ammianus' work a few years back. He takes a palette and essentially pushes it into CRAM (which makes sense to me). While as the above function (probably a better function) but I just don't understand it ... yet :(

Code: Select all

void loadPalette(const vu16* paletteStart, const vu16* paletteEnd, const int paletteOffset)
{
	int numColors;
	int i;
	vu16* cram16 = &MARS_CRAM;
	vu16* pal16 = (vu16*)paletteStart;

	numColors = ((paletteEnd)-(paletteStart));
	for (i = paletteOffset; i < numColors + paletteOffset; i++)
	{
		cram16[i] = pal16[i - paletteOffset] & 0x7FFF;
	}
}
Hope i'm making sense. Thank you.

cero
Very interested
Posts: 338
Joined: Mon Nov 30, 2015 1:55 pm

Re: New 32x game in development!

Post by cero » Mon Jan 23, 2023 7:11 am

I don't get why you want to fight with BMPs, just save the image in Gimp as a C file and have easy usage. Compression later.

matthewnimmo
Very interested
Posts: 87
Joined: Thu Jan 07, 2021 8:04 pm

Re: New 32x game in development!

Post by matthewnimmo » Mon Jan 23, 2023 1:46 pm

cero wrote:
Mon Jan 23, 2023 7:11 am
I don't get why you want to fight with BMPs, just save the image in Gimp as a C file and have easy usage. Compression later.
I didn’t know you could do that! So export the indexed .bmp as h file or c? Ive done both just to see the differences. From there do they make it pretty easy to pull in the image data to draw and my palette info to load?

cero
Very interested
Posts: 338
Joined: Mon Nov 30, 2015 1:55 pm

Re: New 32x game in development!

Post by cero » Mon Jan 23, 2023 5:37 pm

The files it outputs are very clear. XPM is another format that is meant to be embedded to C.

Post Reply