Page 23 of 57

Posted: Mon Jan 23, 2012 8:14 pm
by Mixail
Chilly Willy wrote:You're welcome. If you need the mouse, I can work that in as well.
Later it will be necessary.


What function in SDK 0.9 is similar to function "VDP_setTileRectDma(u16 plan, const u16 *data, u16 x, u16 y, u16 w, u16 h);"?

Posted: Mon Jan 23, 2012 8:49 pm
by Stef
Mixail wrote: What function in SDK 0.9 is similar to function "VDP_setTileRectDma(u16 plan, const u16 *data, u16 x, u16 y, u16 w, u16 h);"?
There is not as you cannot use DMA efficiently with VDP_setTileRect(...).
As we are modifying VRAM in a no contiguous nor regular way DMA is almost useless here.
Do you have some performance issues with that method ?

Posted: Tue Jan 24, 2012 12:47 am
by Chilly Willy
Speaking of DMA, one thing I wanted to ask about. Look at the vblank handler in base.c:

Code: Select all

// VBlank Callback
void _vblank_callback()
{
    vtimer++;

    // joy state refresh
    JOY_update();

    // palette fading processing
    if (VBlankProcess & PROCESS_PALETTE_FADING)
    {
        if (!VDP_doStepFading()) VBlankProcess &= ~PROCESS_PALETTE_FADING;
    }

    // bitmap process
//        if (VBlankProcess & PROCESS_BITMAP_TASK)
//        {
//            if (!BMP_doBlankProcess()) VBlankProcess &= ~PROCESS_BITMAP_TASK;
//        }

    // ...

    // then call user's callback
    if (VBlankCB) VBlankCB();
}
Notice how it does the joypad update before calling the callback. Everyone knows that the only free time for vram update is the vblank, so it's quite likely that someone will setup a vblank callback to trigger pending DMA operations during the vblank. However, reading the pads takes a significant amount of time due to banging on the ports - even more so for six button pads, or especially the mouse. Given that, maybe the JOY_update() should be AFTER the callback instead of before. After all, the joy ports can be banged on at any time equally, while the DMA is best done in the vblank.

Posted: Tue Jan 24, 2012 9:36 am
by Stef
Chilly Willy wrote:Speaking of DMA, one thing I wanted to ask about.
...
Notice how it does the joypad update before calling the callback. Everyone knows that the only free time for vram update is the vblank, so it's quite likely that someone will setup a vblank callback to trigger pending DMA operations during the vblank. However, reading the pads takes a significant amount of time due to banging on the ports - even more so for six button pads, or especially the mouse. Given that, maybe the JOY_update() should be AFTER the callback instead of before. After all, the joy ports can be banged on at any time equally, while the DMA is best done in the vblank.
Yeah you're right, every spare cycle is important during VBlank.
I initially put the JOY_Update() here because i wanted joypad state to be updated before the user callback process but actually that doesn't mind even if user put its logic code in vblank...
I need to modify that, thanks for pointing it.

Posted: Tue Jan 24, 2012 4:36 pm
by Chilly Willy
Stef wrote:
Chilly Willy wrote:Speaking of DMA, one thing I wanted to ask about.
...
Notice how it does the joypad update before calling the callback. Everyone knows that the only free time for vram update is the vblank, so it's quite likely that someone will setup a vblank callback to trigger pending DMA operations during the vblank. However, reading the pads takes a significant amount of time due to banging on the ports - even more so for six button pads, or especially the mouse. Given that, maybe the JOY_update() should be AFTER the callback instead of before. After all, the joy ports can be banged on at any time equally, while the DMA is best done in the vblank.
Yeah you're right, every spare cycle is important during VBlank.
I initially put the JOY_Update() here because i wanted joypad state to be updated before the user callback process but actually that doesn't mind even if user put its logic code in vblank...
I need to modify that, thanks for pointing it.
Actually, I thought of that too, and it's still valid reasoning. What you REALLY need here is TWO vblank callbacks: a pre and post CB. The pre callback would be first allowing the user to start DMA if need be, then all the heavy vblank stuff like JOY_update() occurs, then you call the post callback where the user can check the just-updated controllers.

That would probably be the easiest way to handle this. A more flexible approach would be to do like the Amiga - have a priority based list of callbacks where the normal vblank code is inserted at a set priority, then tasks add vblank callbacks at a priority that would go before or after the system callback. Let's say the JOY_update() was in a callback added at priority 0; then you would add a callback for DMA at a priority of like 1 or 2, and reading the pads at -1 or -2.

Are there other places in sgdk where that would make sense? A place where a system routine is done before calling the user callback. Perhaps callback lists could replace plain callbacks in general.

Posted: Tue Jan 24, 2012 8:41 pm
by Stef
Chilly Willy wrote: Actually, I thought of that too, and it's still valid reasoning. What you REALLY need here is TWO vblank callbacks: a pre and post CB. The pre callback would be first allowing the user to start DMA if need be, then all the heavy vblank stuff like JOY_update() occurs, then you call the post callback where the user can check the just-updated controllers.

That would probably be the easiest way to handle this. A more flexible approach would be to do like the Amiga - have a priority based list of callbacks where the normal vblank code is inserted at a set priority, then tasks add vblank callbacks at a priority that would go before or after the system callback. Let's say the JOY_update() was in a callback added at priority 0; then you would add a callback for DMA at a priority of like 1 or 2, and reading the pads at -1 or -2.
I could use a pre / post callback, and even a priority list system as you mention but i want to keep stuff simple for user and fast in implementation. Having a priority callback list on V-Int would probably gives a minor drawback in performance but this is another story for the H-Int...

Also for the joypad status, handle them one frame too late is not problematic. And generally you should not handle game logic in VBlank, just VDP upload stuff and set some flags to indicate we can process the next frame :) At least this is how i see it.
Are there other places in sgdk where that would make sense? A place where a system routine is done before calling the user callback. Perhaps callback lists could replace plain callbacks in general.
yep : H-Int :)
but because of the small amount of time you have, you can't use something as complex than a callback list.

Posted: Tue Jan 24, 2012 8:44 pm
by Chilly Willy
Ah, makes sense... keep it as fast as possible for those things. Well, if you want the pad state "fresh" - there's always the joypad callback - that's called immediately after reading the pad from the update function. That will do for folks that need lower lag.

Posted: Tue Jan 24, 2012 8:47 pm
by Stef
Chilly Willy wrote:Ah, makes sense... keep it as fast as possible for those things. Well, if you want the pad state "fresh" - there's always the joypad callback - that's called immediately after reading the pad from the update function. That will do for folks that need lower lag.
Indeed, you can always do that if you need it :)

Posted: Thu Jan 26, 2012 12:41 am
by Chilly Willy
Okay, here's my latest on the joy handling. The archive includes new joy.c, joy.h, and main.c files, along with the joytest binary rom. The main.c is the joytest program source.

I also changed base.c to move the JOY_update to AFTER the callback in the vertical blank, but I hardly need to include the whole file just for that change. :D

http://www.mediafire.com/?rrq1148961g1446

I made some changes compared to the old code to make it easier to use. Now the JOY_init() determines what kind of controller you have plugged into both ports and sets the support type accordingly. If you have a 3 button, it's set to 3 button; if you have a 6 button, it's set to 6 button. If you have a mouse, it's set to mouse (yes, mice are now supported). The type of controller can be found in the upper nibble of the button info:

Code: Select all

    jtype = JOY_readJoypad(JOY_1) >> 12;
for example. The types are defined in joy.h as

Code: Select all

#define JOY_TYPE_PAD3           0x00
#define JOY_TYPE_PAD6           0x01
#define JOY_TYPE_MOUSE          0x02
#define JOY_TYPE_UNKNOWN        0x0F
Unknown means either unsupported or no controller. This is valid for all eight joypads, but since the tap isn't yet supported, JOY_3 to JOY_8 will always return JOY_TYPE_UNKNOWN.

Note that the mouse code emulates a 3 button pad: LMB = A, MMB = B, RMB = C, and START = START. You can either use the regular button defines, or the new mouse button defines if it helps the readability of the code. Moving the mouse up sets BUTTON_UP, moving the mouse down sets BUTTON_DOWN, and left and right similarly. So you can actually just pretend it's not a mouse and use it like a regular 3 button pad.

To get the mouse counters, you call JOY_readJoypad(pad) like normal, but OR a flag with the pad index to tell the function to return the X counter or the Y counter. For example:

Code: Select all

    mx = JOY_readJoypad(JOY_MOUSEX + i);
    my = JOY_readJoypad(JOY_MOUSEY + i);
The mouse counters are unsigned shorts which are updated when the mouse moves. The mouse uses "Cartesian" coordinates: negative values (which decrease the counters) are left and down, while positive values are right and up. The counters wrap around from 0xFFFF to 0x0000 or the reverse. To get a delta, merely subtract the previous counter value from the current value.

So things are very simple now - you can ignore everything and just treat all controllers like 3 button pads; if you need six buttons, just check if the MSN of the pad data is JOY_TYPE_PAD6, then use the extra buttons; if you need a mouse, you can check the MSN for JOY_TYPE_MOUSE and use the JOY_MOUSEX/Y to get the mouse counters. No need to set the port support or wait or any of that.

Note: For many folks, the above is fine - just leave everything alone and let SGDK take care of the details. However, you occasionally need every last bit of speed possible. Reading the controllers takes time - the mouse in particular.

If your game uses a single 3 button pad for control and you NEED the max time, you should turn off the unused port. Check for a 3 button pad on either port and turn off the other port via JOY_setSupport(port, JOY_SUPPORT_OFF);

If you only find a 6 button pad, change the support to three button for faster handling - it takes more time to read the 6 button fully. So do a JOY_setSupport(port, JOY_SUPPORT_3BTN); to make it faster.

In particular, if you need every last cycle and do NOT use a mouse, turn the port support OFF! The mouse takes MUCH longer to read than either the 3 button or 6 button pads.

Again, that's only a consideration for people trying to get more speed out of their game. Most games won't need to worry about this. So, give it a try and let me know what you think... is this a good way to handle the controllers, or can you think of something better? 8)

Posted: Mon Feb 20, 2012 1:40 pm
by ammianus
I haven't read the entire thread, but I briefly looked at the SGDK documentation in your google code site and did a forum search and didn't see this discussed.

Would any of the SGDK functions be useful for 32X development? If you wanted to use the MD to draw somethings in a 32X game, would it be wise to include parts or all of the SGDK for this? Or maybe for sound effects or something else?

Posted: Mon Feb 20, 2012 4:58 pm
by Mixail
There was such problem.
That it is possible to use from musical engine with sound engine PCM_ENV. What music and a sound played in common.

Posted: Mon Feb 20, 2012 7:21 pm
by Chilly Willy
ammianus wrote:I haven't read the entire thread, but I briefly looked at the SGDK documentation in your google code site and did a forum search and didn't see this discussed.

Would any of the SGDK functions be useful for 32X development? If you wanted to use the MD to draw somethings in a 32X game, would it be wise to include parts or all of the SGDK for this? Or maybe for sound effects or something else?
My current method of making 32X programs just uses a small assembly loop for the 68000. You COULD modify it to include some C, but you can't directly use sgdk with it. That's probably one of the things I'll work in support for now that I have write access to the repo.

Right now, you mostly do everything with the 32X on the 32X side, with only a little support for the extra MD hardware. If you look at the hw_32x.c file, you'll see where certain commands to change the MD display are passed from the 32X to the MD in the comm registers. Look in md_crt1.s for the main loop where the comm registers are handled.

If you do any drawing with the SH2, you shouldn't try to draw into the 32X framebuffer with the 68000. You have to set a flag in the 32X hardware saying who has access to the 32X VDP resources (palette, frame buffer, and associated registers in the 32X). Only one side or the other can use resources at any one time. My example gives control of the 32X video to the SH2s.

Posted: Mon Feb 20, 2012 7:24 pm
by Stef
Basically SGDK is only for MD development, i mean you have only methods for the megadrive, but you can mix with 32X dev. I believe Chilly Willy do it in some ways :)

Posted: Tue Feb 21, 2012 11:17 am
by Mixail
Mixail wrote:There was such problem.
That it is possible to use from musical engine with sound engine PCM_ENV. What music and a sound played in common.
help me!

Posted: Tue Feb 21, 2012 4:31 pm
by Stef
Mixail wrote:
Mixail wrote:There was such problem.
That it is possible to use from musical engine with sound engine PCM_ENV. What music and a sound played in common.
help me!
I don't understand what problem you have.
You have severals audio drivers in SGDK, some permit you to play FM musics as the TFM or MVS drivers while others permit to play PCM samples.
There is not yet a driver which permit to play FM music with PCM samples.
The easiest way currently to have both SFX and music is to use 4 PCM with envelop support driver.
Here is a short description and the method to use (very simple) :

Code: Select all

/* <b>Z80_DRIVER_4PCM_ENV</b><br>
 * 4 channels 8 bits signed sample driver with volume support.<br>
 * It can mix up to 4 samples (8 bit signed) at a fixed 16 Khz rate.<br>
 * with volume support (16 levels du to memory limitation).<br>
 * Address and size of samples have to be 256 bytes boundary.<br>
 * The driver does support "cutoff" when mixing so you can use true 8 bits samples :)<br>
 */

  SND_setVolume_4PCM_ENV(SOUND_PCM_CH1, end);

  if (SND_isPlaying_4PCM_ENV(SOUND_PCM_CH1_MSK))
    SND_stopPlay_4PCM_ENV(SOUND_PCM_CH1);
  else
    SND_startPlay_4PCM_ENV(sample, sizeof(sample), SOUND_PCM_CH1, loop);