Page 1 of 5 12345 LastLast
Results 1 to 10 of 44

Thread: Misc KOS related issues

                  
   
  1. #1
    DCEmu Coder
    Join Date
    Aug 2006
    Posts
    571
    Rep Power
    67

    Default Misc KOS related issues

    I got a Dreamcast (finally) a bit over a week ago and decided to give the homebrew tools a quick try. I ran into a few things...

    First, I noticed that screen flipping hadn't been implemented yet, which is odd considering how old KOS is and how easy it was to add. In fact, the current video driver for KOS on the DC is rather limited - you get one frame buffer that is visible and you can only draw to it. That was nice for 1993 on your VGA card with 64 KB of vram, but this is a Dreamcast. Let's look at video.c.

    (sorry about the quotes, but code tags STILL don't work on this board!!!)

    vid_mode_t vid_builtin[DM_MODE_COUNT] = {
    /* NULL mode.. */
    /* DM_INVALID = 0 */
    { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, { 0, 0, 0, 0 } },

    /* 320x240 VGA 60Hz */
    /* DM_320x240_VGA */
    {
    DM_320x240,
    320, 240,
    VID_PIXELDOUBLE|VID_LINEDOUBLE,
    CT_VGA,
    0,
    262, 857,
    0xAC, 0x28,
    0x15, 0x104,
    141, 843,
    24, 263,
    0, 1,
    { 0, 0, 0, 0 }
    },
    I only show the first entry in the table to demonstrate the first change... see that final "1" right before the array of zeroes? That's how many buffers you get. Change them all like so

    vid_mode_t vid_builtin[DM_MODE_COUNT] = {
    /* NULL mode.. */
    /* DM_INVALID = 0 */
    { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, { 0, 0, 0, 0 } },

    /* 320x240 VGA 60Hz */
    /* DM_320x240_VGA */
    {
    DM_320x240,
    320, 240,
    VID_PIXELDOUBLE|VID_LINEDOUBLE,
    CT_VGA,
    0,
    262, 857,
    0xAC, 0x28,
    0x15, 0x104,
    141, 843,
    24, 263,
    0, VID_MAX_FB,
    { 0, 0, 0, 0 }
    },
    Now we need to set the frame buffer offsets. That's those last four zeroes... but we won't set it there as it's easier to do it in the vid_set_mode() function.

    void vid_set_mode(int dm, int pm) {
    static uint8 bpp[4] = { 2, 2, 0, 4 };
    vid_mode_t mode;
    int i, ct, found;

    ct = vid_check_cable();

    /* Check to see if we should use a direct mode index, a generic
    mode check, or if it's just invalid. */
    if (dm > DM_INVALID && dm < DM_SENTINEL) {
    memcpy(&mode, &vid_builtin[dm], sizeof(vid_mode_t));
    } else if (dm >= DM_GENERIC_FIRST && dm <= DM_GENERIC_LAST) {
    found = 0;
    for (i=1; i<DM_SENTINEL; i++) {
    /* Is it the right generic mode? */
    if (vid_builtin[i].generic != dm)
    continue;

    /* Do we have the right cable type? */
    if (vid_builtin[i].cable_type != CT_ANY &&
    vid_builtin[i].cable_type != ct)
    continue;

    /* Ok, nothing else to check right now -- we've got our mode */
    memcpy(&mode, &vid_builtin[i], sizeof(vid_mode_t));
    found = 1;
    break;
    }
    if (!found) {
    dbglog(DBG_ERROR, "vid_set_mode: invalid generic mode %04x\n", dm);
    return;
    }
    } else {
    dbglog(DBG_ERROR, "vid_set_mode: invalid mode specifier %04x\n", dm);
    return;
    }

    /* We set this here so actual mode is bit-depth independent.. */
    mode.pm = pm;

    /* This is also to be generic */
    mode.cable_type = ct;

    /* Set the framebuffer base array */
    mode.fb_base[1] = 0x200000;
    mode.fb_base[2] = 0x400000;
    mode.fb_base[3] = 0x600000;

    /* This will make a private copy of our "mode" */
    vid_set_mode_ex(&mode);
    }
    The new lines are towards the bottom where mode.fb_base[] is set. The offsets are far enough apart for any size display you might set.

    Then you need to change

    vid_set_start(0);
    in vid_set_mode_ex() to this

    vid_mode->fb_curr = -1; /* force update in flip */
    vid_flip(0);
    /* vid_set_start(0); */
    We could leave it there, but now that we have four buffers to play with, we need to add some ability to draw into the offscreen buffers. The current code sets a couple variables called vram_s and vram_l to point to the frame buffer when you set the mode. If yo draw through those variables, you are drawing to the visible screen. So I added a couple new variables, dvram_s and dvram_l that are set by vid_flip() to point to the next buffer after the one you just flipped to.

    void vid_flip(int fb) {
    uint16 oldfb;
    uint32 base;

    oldfb = vid_mode->fb_curr;
    if (fb < 0) {
    vid_mode->fb_curr++;
    } else {
    vid_mode->fb_curr = fb;
    }
    vid_mode->fb_curr &= (vid_mode->fb_count - 1);

    if (vid_mode->fb_curr == oldfb) {
    return;
    }

    /* The next buffer becomes the draw buffer. */
    base = vid_mode->fb_base[(vid_mode->fb_curr + 1) & (vid_mode->fb_count - 1)];
    dvram_s = (uint16*)(0xA5000000|base);
    dvram_l = (uint32*)(0xA5000000|base);

    /* Will set vram_s/vram_l to the current buffer. */
    vid_set_start(vid_mode->fb_base[vid_mode->fb_curr]);
    }
    Now if you draw through dvram_s or dvram_l, you'll be drawing to the buffer that will be visible the next time you call vid_flip(-1);

    So now you have working screen flipping. Just call vid_set_mode() like normal, then go into your main loop. The loop will draw through dvram_s or dvram_l, then call vid_flip(-1). That's all you need to do, and you have tear-free drawing.

    One other change... vid_clear() clears the current frame buffer. We want to clear the drawing buffer, not the frame buffer. We'll leave vid_clear() alone for backwards compatibility with existing software and make a new function - vid_clear_draw().

    /*-----------------------------------------------------------------------------*/
    /* Clears the draw buffer with a given color */
    void vid_clear_draw(int r, int g, int b) {
    uint16 pixel16;
    uint32 pixel32;

    switch (vid_mode->pm) {
    case PM_RGB555:
    pixel16 = ((r >> 3) << 10)
    | ((g >> 3) << 5)
    | ((b >> 3) << 0);
    sq_set16(dvram_s, pixel16, (vid_mode->width * vid_mode->height) * 2);
    break;
    case PM_RGB565:
    pixel16 = ((r >> 3) << 11)
    | ((g >> 2) << 5)
    | ((b >> 3) << 0);
    sq_set16(dvram_s, pixel16, (vid_mode->width * vid_mode->height) * 2);
    break;
    case PM_RGB888:
    pixel32 = (r << 16) | (g << 8) | (b << 0);
    sq_set32(dvram_l, pixel32, (vid_mode->width * vid_mode->height) * 4);
    break;
    }
    }
    It's EXACTLY the same as vid_clear(), but uses dvram_s/dvram_l instead of vram_s/vram_l as the address to clear. Don't forget to add the proto to the video.h file.

  2. #2
    DCEmu Coder
    Join Date
    Aug 2006
    Posts
    571
    Rep Power
    67

    Default

    Okay, next up is the BIOS font. Did you ever notice that only thousands mode is supported, not millions? Did you ever notice you are stuck with white text on a black background? Let's change that.

    /* KallistiOS ##version##

    biosfont.c

    (c)2000-2002 Dan Potter
    Japanese code (c) Kazuaki Matsumoto
    */

    #include <assert.h>
    #include <dc/biosfont.h>

    /*

    This module handles interfacing to the bios font. It supports the standard
    European encodings via ISO8859-1, and Japanese in both Shift-JIS and EUC
    modes. For Windows/Cygwin users, you'll probably want to call
    bfont_set_encoding(BFONT_CODE_SJIS) so that your messages are displayed
    properly; otherwise it will default to EUC (for *nix).

    Thanks to Marcus Comstedt for the bios font information.

    All the Japanese code is by Kazuaki Matsumoto.

    Foreground and background colors, and pixel mode support added by Chilly
    Willy.

    */

    /* Our current conversion mode */
    int bfont_code_mode = BFONT_CODE_ISO8859_1;

    /* Current foreground and background colors */
    uint32 bfont_fgcolor = 0xFFFFFF;
    uint32 bfont_bgcolor = 0x000000;

    /* Current pixel mode */
    int bfont_pmode = 1; /* video defaults to 565 */

    /* Set pixel mode - returns previous pixel mode */
    int bfont_set_pmode(int pmode) {
    int old_pmode = bfont_pmode;
    bfont_pmode = pmode;
    return old_pmode;
    }

    /* Set foreground color - returns previous color */
    uint32 bfont_set_fgcolor(uint32 color) {
    int old_color = bfont_fgcolor;
    bfont_fgcolor = color;
    return old_color;
    }

    /* Set background color - returns previous color */
    uint32 bfont_set_bgcolor(uint32 color) {
    int old_color = bfont_bgcolor;
    bfont_bgcolor = color;
    return old_color;
    }

    /* Select an encoding for Japanese (or disable) */
    void bfont_set_encoding(int enc) {
    if (enc < BFONT_CODE_ISO8859_1 || enc > BFONT_CODE_SJIS) {
    assert_msg( 0, "Unknown bfont encoding mode" );
    }
    bfont_code_mode = enc;
    }

    /* A little assembly that grabs the font address */
    extern uint8* get_font_address();
    asm(
    " .text\n"
    " .align 2\n"
    "_get_font_address:\n"
    " mov.l syscall_b4,r0\n"
    " mov.l @r0,r0\n"
    " jmp @r0\n"
    " mov #0,r1\n"
    "\n"
    " .align 4\n"
    "syscall_b4:\n"
    " .long 0x8c0000b4\n"
    );


    /* Shift-JIS -> JIS conversion */
    unsigned int sjis2jis(unsigned int sjis) {
    unsigned int hib, lob;

    hib = (sjis >> 8) & 0xff;
    lob = sjis & 0xff;
    hib -= (hib <= 0x9f) ? 0x71 : 0xb1;
    hib = (hib << 1) + 1;
    if (lob > 0x7f) lob--;
    if (lob >= 0x9e) {
    lob -= 0x7d;
    hib++;
    } else
    lob -= 0x1f;

    return (hib << 8) | lob;
    }


    /* EUC -> JIS conversion */
    unsigned int euc2jis(unsigned int euc) {
    return euc & ~0x8080;
    }

    /* Given an ASCII character, find it in the BIOS font if possible */
    uint8 *bfont_find_char(int ch) {
    int index = -1;
    uint8 *fa = get_font_address();

    /* 33-126 in ASCII are 1-94 in the font */
    if (ch >= 33 && ch <= 126)
    index = ch - 32;

    /* 160-255 in ASCII are 96-161 in the font */
    if (ch >= 160 && ch <= 255)
    index = ch - (160 - 96);

    /* Map anything else to a space */
    if (index == -1)
    index = 72 << 2;

    return fa + index*36;
    }

    /* JIS -> (kuten) -> address conversion */
    uint8 *bfont_find_char_jp(int ch) {
    uint8 *fa = get_font_address();
    int ku, ten, kuten = 0;

    /* Do the requested code conversion */
    switch(bfont_code_mode) {
    case BFONT_CODE_ISO8859_1:
    return NULL;
    case BFONT_CODE_EUC:
    ch = euc2jis(ch);
    break;
    case BFONT_CODE_SJIS:
    ch = sjis2jis(ch);
    break;
    default:
    assert_msg( 0, "Unknown bfont encoding mode" );
    }

    if (ch > 0) {
    ku = ((ch >> 8) & 0x7F);
    ten = (ch & 0x7F);
    if (ku >= 0x30)
    ku -= 0x30 - 0x28;
    kuten = (ku - 0x21) * 94 + ten - 0x21;
    }
    return fa + (kuten + 144)*72;
    }


    /* Half-width kana -> address conversion */
    uint8 *bfont_find_char_jp_half(int ch) {
    uint8 *fa = get_font_address();
    return fa + (32 + ch)*36;
    }

    /* Draw half-width kana */
    void bfont_draw_thin(uint16 *buffer, int bufwidth, int opaque, int c, int iskana) {
    uint8 *ch;
    uint16 word;
    int x, y;

    if (iskana)
    ch = bfont_find_char_jp_half(c);
    else
    ch = bfont_find_char(c);

    if (bfont_pmode == 0 || bfont_pmode == 1) {
    uint16 fc = bfont_pmode == 0 ? MAKE_RGB555(bfont_fgcolor) : MAKE_RGB565(bfont_fgcolor);
    uint16 bc = bfont_pmode == 0 ? MAKE_RGB555(bfont_bgcolor) : MAKE_RGB565(bfont_bgcolor);

    for (y=0; y<24; ) {
    /* Do the first row */
    word = (((uint16)ch[0]) << 4) | ((ch[1] >> 4) & 0x0f);
    for (x=0; x<12; x++) {
    if (word & (0x0800 >> x))
    *buffer = fc;
    else {
    if (opaque)
    *buffer = bc;
    }
    buffer++;
    }
    buffer += bufwidth - 12;
    y++;

    /* Do the second row */
    word = ( (((uint16)ch[1]) << 8) & 0xf00 ) | ch[2];
    for (x=0; x<12; x++) {
    if (word & (0x0800 >> x))
    *buffer = fc;
    else {
    if (opaque)
    *buffer = bc;
    }
    buffer++;
    }
    buffer += bufwidth - 12;
    y++;

    ch += 3;
    }
    } else {
    uint32 *lbuffer = (uint32 *)buffer;
    for (y=0; y<24; ) {
    /* Do the first row */
    word = (((uint16)ch[0]) << 4) | ((ch[1] >> 4) & 0x0f);
    for (x=0; x<12; x++) {
    if (word & (0x0800 >> x))
    *lbuffer = bfont_fgcolor;
    else {
    if (opaque)
    *lbuffer = bfont_bgcolor;
    }
    lbuffer++;
    }
    lbuffer += bufwidth - 12;
    y++;

    /* Do the second row */
    word = ( (((uint16)ch[1]) << 8) & 0xf00 ) | ch[2];
    for (x=0; x<12; x++) {
    if (word & (0x0800 >> x))
    *lbuffer = bfont_fgcolor;
    else {
    if (opaque)
    *lbuffer = bfont_bgcolor;
    }
    lbuffer++;
    }
    lbuffer += bufwidth - 12;
    y++;

    ch += 3;
    }
    }
    }

    /* Compat function */
    void bfont_draw(uint16 *buffer, int bufwidth, int opaque, int c) {
    bfont_draw_thin(buffer, bufwidth, opaque, c, 0);
    }

    /* Draw wide character */
    void bfont_draw_wide(uint16 *buffer, int bufwidth, int opaque, int c) {
    uint8 *ch = bfont_find_char_jp(c);
    uint16 word;
    int x, y;

    if (bfont_pmode == 0 || bfont_pmode == 1) {
    uint16 fc = bfont_pmode == 0 ? MAKE_RGB555(bfont_fgcolor) : MAKE_RGB565(bfont_fgcolor);
    uint16 bc = bfont_pmode == 0 ? MAKE_RGB555(bfont_bgcolor) : MAKE_RGB565(bfont_bgcolor);

    for (y=0; y<24; ) {
    /* Do the first row */
    word = (((uint16)ch[0]) << 4) | ((ch[1] >> 4) & 0x0f);
    for (x=0; x<12; x++) {
    if (word & (0x0800 >> x))
    *buffer = fc;
    else {
    if (opaque)
    *buffer = bc;
    }
    buffer++;
    }

    word = ( (((uint16)ch[1]) << 8) & 0xf00 ) | ch[2];
    for (x=0; x<12; x++) {
    if (word & (0x0800 >> x))
    *buffer = fc;
    else {
    if (opaque)
    *buffer = bc;
    }
    buffer++;
    }
    buffer += bufwidth - 24;
    y++;

    ch += 3;
    }
    } else {
    uint32 *lbuffer = (uint32 *)buffer;
    for (y=0; y<24; ) {
    /* Do the first row */
    word = (((uint16)ch[0]) << 4) | ((ch[1] >> 4) & 0x0f);
    for (x=0; x<12; x++) {
    if (word & (0x0800 >> x))
    *lbuffer = bfont_fgcolor;
    else {
    if (opaque)
    *lbuffer = bfont_bgcolor;
    }
    lbuffer++;
    }

    word = ( (((uint16)ch[1]) << 8) & 0xf00 ) | ch[2];
    for (x=0; x<12; x++) {
    if (word & (0x0800 >> x))
    *lbuffer = bfont_fgcolor;
    else {
    if (opaque)
    *lbuffer = bfont_bgcolor;
    }
    lbuffer++;
    }
    lbuffer += bufwidth - 24;
    y++;

    ch += 3;
    }
    }
    }


    /* Draw string of full-width (wide) and half-width (thin) characters
    Note that this handles the case of mixed encodings unless Japanese
    support is disabled (BFONT_CODE_ISO8859_1). */
    void bfont_draw_str(uint16 *buffer, int width, int opaque, char *str) {
    uint16 nChr, nMask, nFlag;

    while (*str) {
    nFlag = 0;
    nChr = *str & 0xff;
    if (bfont_code_mode != BFONT_CODE_ISO8859_1 && (nChr & 0x80)) {
    switch (bfont_code_mode) {
    case BFONT_CODE_EUC:
    if (nChr == 0x8e) {
    str++;
    nChr = *str & 0xff;
    if ( (nChr < 0xa1) || (nChr > 0xdf) )
    nChr = 0xa0; /* Blank Space */
    } else
    nFlag = 1;
    break;
    case BFONT_CODE_SJIS:
    nMask = nChr & 0xf0;
    if ( (nMask == 0x80) || (nMask == 0x90) || (nMask == 0xe0) )
    nFlag = 1;
    break;
    default:
    assert_msg( 0, "Unknown bfont encoding mode" );
    }

    if (nFlag == 1) {
    str++;
    nChr = (nChr << 8) | (*str & 0xff);
    bfont_draw_wide(buffer, width, opaque, nChr);
    buffer += bfont_pmode == 3 ? 48 : 24;
    } else {
    bfont_draw_thin(buffer, width, opaque, nChr, 1);
    buffer += bfont_pmode == 3 ? 24 : 12;
    }
    } else {
    bfont_draw_thin(buffer, width, opaque, nChr, 0);
    buffer += bfont_pmode == 3 ? 24 : 12;
    }
    str++;
    }
    }
    There we go! Now we can change the pixel mode with bfont_set_pmode(), and the colors using bfont_set_fgcolor() and bfont_set_bgcolor(). The drawing routines are changed to look at both the pixel mode and the colors when drawing. Now you can use the BIOS font on RGB888 screens, and in any color you want. This defaults to RGB565 and white and black to be backwards compatible.

    Note: given the problem with code tags, here's an archive of my altered video.c, video.h, biosfont.c, and biosfont.h files.

    kos-fixes-1.zip

  3. #3
    DCEmu Coder
    Join Date
    Aug 2006
    Posts
    571
    Rep Power
    67

    Default

    The next issue isn't with kos, it's with the compiler. The normal compiler used with kos is old and buggy. How buggy is it? Let's look at an example.

    How do you define boolean variables in C? If you're like many other programmers, you use

    typedef enum {false, true} boolean;
    Then let's say we set a boolean based on a configuration entry. It'll look something like this

    respawnparm = M_CheckParm ("-respawn");
    (have you recognized the app I was using as my DC dev test??)


    M_CheckParm() returns the index of the arg that matches the string passed in, or 0 if it isn't found. Clearly, the assignment above sets the boolean to false if 0 is returned, and true if non-zero is returned... or does it? If you have any kind of reasonably current compiler, it does. If you have the old, buggy compiler in kos, it most certainly doesn't. Instead, it just assigns the value returned to the boolean as if it were an int variable. You have to change the line (and any others like it) to

    respawnparm = M_CheckParm ("-respawn") ? true : false;
    God only knows what other bugs lurk in the compiler. I'm currently trying to get a reasonably new version of gcc 4 working with kos... or I should put that the other way around - getting kos to work with a reasonably new version of gcc 4. The compiler in question is the one I use for my 32X compiling - the SH family compiler from KPIT. Hopefully I'll have some good news to report on that soon.

  4. #4
    The Long Claw of the Law BlueCrab's Avatar
    Join Date
    Apr 2004
    Age
    36
    Posts
    1,215
    Rep Power
    50

    Default

    Its very easy to get KOS working with GCC 4.4.0 (at least since I fixed it a while back), in fact a (GCC) patch for doing just that was put out on the KOS mailing list not that long back.

    Also, might I suggest that if you wish to contribute to KOS, make patches against the SVN version and upload them. SVN makes it extremely easy to create patches, and they're a heck of a lot easier to apply to the code in the repository than random code laying in forums.

    As for comments on your changes (I've only read the first set, regarding the video code so far), adding multiple framebuffers is fine and dandy (by the way, KOS normally uses a two-frame buffering system), but doing so the way that you've gone about it may very well break the 3D hardware interface in KOS. The 3D hardware requires quite a bit of buffers on its own, and if you just go around assigning random addresses in VRAM to framebuffers, you may impede on those buffers needed by the PVR. Also, having more than 2 framebuffers will severely limit the amount of space available for textures in VRAM, which becomes a very serious problem if you're doing anything with the 3D hardware (as it is, with only two buffers, you end up with just about half of VRAM gone just to framebuffers and PVR required buffers).
    Last edited by BlueCrab; July 31st, 2009 at 20:48.
    Sylverant PSO Server
    http://crabemu.sourceforge.net/
    irc.freenode.net #dreamcastdev #dcemuuk #yabause #ljsdcdev

  5. #5
    DCEmu Coder
    Join Date
    Aug 2006
    Posts
    571
    Rep Power
    67

    Default

    Quote Originally Posted by BlueCrab View Post
    Its very easy to get KOS working with GCC 4.4.0 (at least since I fixed it a while back), in fact a (GCC) patch for doing just that was put out on the KOS mailing list not that long back.

    Also, might I suggest that if you wish to contribute to KOS, make patches against the SVN version and upload them. SVN makes it extremely easy to create patches, and they're a heck of a lot easier to apply to the code in the repository than random code laying in forums.

    As for comments on your changes (I've only read the first set, regarding the video code so far), adding multiple framebuffers is fine and dandy (by the way, KOS normally uses a two-frame buffering system), but doing so the way that you've gone about it may very well break the 3D hardware interface in KOS. The 3D hardware requires quite a bit of buffers on its own, and if you just go around assigning random addresses in VRAM to framebuffers, you may impede on those buffers needed by the PVR. Also, having more than 2 framebuffers will severely limit the amount of space available for textures in VRAM, which becomes a very serious problem if you're doing anything with the 3D hardware (as it is, with only two buffers, you end up with just about half of VRAM gone just to framebuffers and PVR required buffers).
    I wasn't sure if the svn was open to the public or not. Anywho, like I mention in the first post, the number of buffers set by the structures is ONE. There are NOT two buffers in KOS. In fact, looking at the SDL code, it uses it's own buffer code and vid_set_start() to do double-buffering. It sets the second buffer to 0x400000, or half the vram. SDL also uses completely different code for 3D vs non-3D, so my changes shouldn't effect it at all. However, I haven't looked at the KOS 3D yet. If you use the flip code above, you probably would cause trouble for KOS 3D, but it should be backwards compatible - don't use the flipping and it should still work with KOS 3D. I have seen no examples of ANYONE using vid_flip() because it doesn't work in kos as there's only one buffer. vid_flip(anything) always results in the buffer staying exactly the same as it was when you called vid_set_mode(). That's why SDL uses vid_set_start().

    To sum it up, the vid_flip() changes above are for CPU rendered video. The 3D uses completely different code and shouldn't have a problem. The old flip code was never used by anyone as it never did anything. I'll double-check the 3D to be sure it isn't affected by my changes before I even think about submitting them to the repo. Okay?

  6. #6
    DCEmu Newbie
    Join Date
    Aug 2007
    Location
    Corrientes - Argentina
    Posts
    93
    Rep Power
    0

    Default

    ˇwow that looks great! But i think that you should take a look to the pvr api, the framebuffer in dc it's just slow.

  7. #7
    DCEmu Coder
    Join Date
    Aug 2006
    Posts
    571
    Rep Power
    67

    Default

    Quote Originally Posted by Guaripolo View Post
    ˇwow that looks great! But i think that you should take a look to the pvr api, the framebuffer in dc it's just slow.
    Using the flipping code above, my port of Doom at 304x224 (TV mode) gets between 50 and 70 FPS while running the timedemo, spending most of the time right about 60 FPS. When playing the game, it stays a rock-solid 35 FPS the whole time (the code I work from has the frame limit except when running the timedemo). So the multi-buffer screen flipping is only as slow as your app is at drawing frames.

    In case you're wondering, I have played it at 608x448 (TV mode again), and it gets between 15 and 25 FPS at that resolution. That's a TRUE resolution - Doom is actually drawing at 608x448, not a lower res and then scaling up. The diagonals are noticeably cleaner.

    If you want to try it, here's an alpha. Everything SHOULD work, and mostly does, but weird things happen sometimes, all of which have so far been compiler problems.

    DCDoom-cw-alpha1.sbi

    That has the shareware wad file. If you just make the disc image, you can just immediately start playing. There's a nice readme in the readme directory. Source is included, as always.
    Last edited by JLF65; August 1st, 2009 at 01:14.

  8. #8
    The Long Claw of the Law BlueCrab's Avatar
    Join Date
    Apr 2004
    Age
    36
    Posts
    1,215
    Rep Power
    50

    Default

    Quote Originally Posted by JLF65 View Post
    I wasn't sure if the svn was open to the public or not.
    The SVN is open to the public for READ-ONLY access. You can create patches this way, and it'll make it a heck of a lot easier for any KOS maintainers (myself included) to figure out what's going on (and decide whether or not to accept/commit said patches).

    Anywho, like I mention in the first post, the number of buffers set by the structures is ONE.
    Yes, there is only one buffer set up by 2D mode, the PVR handles buffers differently (see kos/kernel/arch/dreamcast/hardware/pvr/*.c, and have fun figuring it all out).

    There are NOT two buffers in KOS.
    That is not true in the case of 3D, like I said. The PVR sets up its own buffers, and you would to much better to not mess with this stuff in KOS proper yourself (all of it can be done outside KOS if you do it right).

    In fact, looking at the SDL code, it uses it's own buffer code and vid_set_start() to do double-buffering.
    Also how the PVR generally does things.

    It sets the second buffer to 0x400000, or half the vram. SDL also uses completely different code for 3D vs non-3D, so my changes shouldn't effect it at all.
    SDL is crap (I'm sorry to say), and 3D support in SDL for the Dreamcast goes through the KOS PVR API (granted through another abstraction layer, KGL).

    However, I haven't looked at the KOS 3D yet. If you use the flip code above, you probably would cause trouble for KOS 3D, but it should be backwards compatible - don't use the flipping and it should still work with KOS 3D.
    It would indeed cause trouble, and I don't know why the code is still there to tell the truth. If you want to set up double buffering with vid_flip, make copies of the vid_mode_t structures you want to modify, and use the vid_set_mode_ex function to set them up. I do not feel that it is in the best interests of the rest of KOS to go mucking about with the stable/working video code.

    I have seen no examples of ANYONE using vid_flip() because it doesn't work in kos as there's only one buffer. vid_flip(anything) always results in the buffer staying exactly the same as it was when you called vid_set_mode(). That's why SDL uses vid_set_start().
    And vid_set_start is the proper/accepted way to get things to work if you don't want to make copies of the vid_mode_t structure to use in your code.

    To sum it up, the vid_flip() changes above are for CPU rendered video. The 3D uses completely different code and shouldn't have a problem. The old flip code was never used by anyone as it never did anything. I'll double-check the 3D to be sure it isn't affected by my changes before I even think about submitting them to the repo. Okay?
    In my opinion vid_flip should be done away with entirely, since it is pretty much pointless. If you really want to do a CPU-rendered double buffering system, use vid_set_start, its a much more sane way to do things anyway, and leads to less problems (since you do have full control over the process).
    Sylverant PSO Server
    http://crabemu.sourceforge.net/
    irc.freenode.net #dreamcastdev #dcemuuk #yabause #ljsdcdev

  9. #9
    DCEmu Coder
    Join Date
    Aug 2006
    Posts
    571
    Rep Power
    67

    Default

    Quote Originally Posted by BlueCrab View Post
    The SVN is open to the public for READ-ONLY access. You can create patches this way, and it'll make it a heck of a lot easier for any KOS maintainers (myself included) to figure out what's going on (and decide whether or not to accept/commit said patches).
    Thanks for the clarification. I'll post any diffs to the development list if/when I make some.

    Yes, there is only one buffer set up by 2D mode, the PVR handles buffers differently (see kos/kernel/arch/dreamcast/hardware/pvr/*.c, and have fun figuring it all out).
    Yes, I've been looking that over. The PVR code does indeed use two buffers. So the video code should definitely not be mixed with the PVR code, but it's still good. The changes I made for video.c make it simple to use multiple buffers for simpler 2D CPU rendered programs... of which there are quite a few. It won't interfere with the PVR code because you don't mix the two - you either use one or the other.

    That is not true in the case of 3D, like I said. The PVR sets up its own buffers, and you would to much better to not mess with this stuff in KOS proper yourself (all of it can be done outside KOS if you do it right).
    Except that KOS provided the functions to do that... they just weren't implemented. I simply made what was there work the way it was originally intended.

    Also how the PVR generally does things.

    SDL is crap (I'm sorry to say), and 3D support in SDL for the Dreamcast goes through the KOS PVR API (granted through another abstraction layer, KGL).
    Yes, that's true as well. I was just pointing out that SDL also ran into that problem with the double-buffer not being properly supported. I'm sure many people look at the vid_flip and think it would be great for their project, only to find it doesn't work. PVR is rather complicate for a simple double-buffer. Look at it this way - if all you needed was simple buffering, isn't it better to give something simple?

    It would indeed cause trouble, and I don't know why the code is still there to tell the truth. If you want to set up double buffering with vid_flip, make copies of the vid_mode_t structures you want to modify, and use the vid_set_mode_ex function to set them up. I do not feel that it is in the best interests of the rest of KOS to go mucking about with the stable/working video code.
    "If it ain't broke, don't fix it." Sorry, but it's broke - I fixed it. The point of making something open source is so that people can fix it. I'll post a diff and let others decide if it's stable and good enough to warrant inclusion in the main repo.

    And vid_set_start is the proper/accepted way to get things to work if you don't want to make copies of the vid_mode_t structure to use in your code.
    Accepted, yes. Proper, no. It still doesn't give you a draw buffer - it gives you a pointer to the VISIBLE FRAME BUFFER.

    In my opinion vid_flip should be done away with entirely, since it is pretty much pointless. If you really want to do a CPU-rendered double buffering system, use vid_set_start, its a much more sane way to do things anyway, and leads to less problems (since you do have full control over the process).
    It's not more sane - you don't get a draw buffer and you have to track all the buffers yourself. That's just ASKING for problems. My changes make it simple and fool proof.

    1. Call vid_set_mode()
    2. Draw through dvram_s or dvram_l
    3. Call vid_flip(-1)
    4. Loop to 2

    Look at how simple that is... it's virtually impossible to screw up. Perfect, simple, FAST, 2D multi-buffering. You can't EVEN compare using vid_set_start() to it at all.

  10. #10
    DCEmu Newbie
    Join Date
    Aug 2007
    Location
    Corrientes - Argentina
    Posts
    93
    Rep Power
    0

    Default

    wow that's a discussion! AWHEAUwehUAweAUWeh.
    JLF65 is right, kos is open and he can do whatever he want's, then we can decide if it's useful or not to some project. I think that kos can be split in different branches for different purposes, ie an small kernel without net, pvr can be used for software rendered projects -in this way more memory can be available-.
    There's a lot of people using software rendering (including me) for small projects and this can be significant for improve speed and quality in games.

    I appreciate that this kind of discussions are taking place: it means that the scene isn't dead and that there's a lot of things to improve in kos, sdl, and all the libraries available.

    JLF65: Thanks for the doom, i'll test it. The speed that you got looks impressive!
    I hope that you can release a working kpit sh tools for dc/kos, it will be significant for the scene.

Page 1 of 5 12345 LastLast

Thread Information

Users Browsing this Thread

There are currently 7 users browsing this thread. (0 members and 7 guests)

Similar Threads

  1. The State of the Homebrew Scene 2009
    By wraggster in forum DCEmu General Gaming and Current Affairs News forum
    Replies: 12
    Last Post: September 19th, 2010, 06:22
  2. Latest Total War game hampered by Steam, Nvidia issues
    By wraggster in forum PC News Forum
    Replies: 0
    Last Post: March 10th, 2009, 01:04
  3. V3N0M's PSP Custom Firmware Reference
    By V3N0M in forum DCEmu Gaming & General Discussion Forum
    Replies: 51
    Last Post: January 27th, 2008, 05:38
  4. mame compatibility list 097
    By plungmonies in forum DCEmu Gaming & General Discussion Forum
    Replies: 22
    Last Post: February 25th, 2006, 17:37

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •