DieHard Wolfers Forum Index DieHard Wolfers
A Wolfenstein 3d Fan Community


  Hosted by: MCS & Areyep.com - Designed by: BrotherTank

Original Yahoo Forum - Die Hard Archives

AReyeP HomepageAreyep Homepage DieHard Wolfenstein BunkerDieHard Wolfenstein Bunker Log inLog in RegisterRegister Banlist FAQFAQ Search ForumsSearch

  Username:    Password:      Remember me       

[Tutorial] Save game screenshots!
Page 1 of 1
DieHard Wolfers Forum Index -> SDL Code Crackers View Previous TopicRefresh this PageAdd Topic to your Browser FavoritesSearch ForumsPrint this TopicE-mail TopicGoto Page BottomView Next Topic
Post new topicReply to topic
Author Message
insurrectionman
DieHard Mutant
DieHard Mutant


Joined: 07 May 2005
Last Visit: 05 Jul 2018

Topics: 87
Posts: 758
Location: Wisconsin
usa.gif

PostPosted: Fri Mar 09, 2012 3:24 pm
   Subject: [Tutorial] Save game screenshots!
   [ IP : Logged ]
Reply with quote
Goto Top of PostsGoto Next PostGoto Bottom of Posts

Hey fellow Wolf Community,

Yesterday I was bored and thought "What if I could show an image of where I last saved my game?"
So I spent about 3 hours on this, learning more about SDL structs, and structure, and I developed this:



It shows the last spot you were in-game, when you go to save it. Neat huh?

Now this isn't 100% tested, it works in one case, but I don't have a fully proper tutorial. I'll continue to work on it.

What do you guys think? Is it a feasible feature that you think would be helpful in games?

To do it, is fairly simple too. So, I think I made a cool discovery here. Very Happy

_________________
I'm back! I missed this community!
Youtube Channel: TreeSapThief

New Site: http://www.treesapthief.com
Twitter: @treesapthief


Last edited by insurrectionman on Fri Mar 09, 2012 9:24 pm; edited 1 time in total
Chris
DieHard Wolfer
DieHard Wolfer


Joined: 11 Mar 2003
Last Visit: 18 Jul 2018

Topics: 55
Posts: 2135
Location: Canada
blank.gif

PostPosted: Fri Mar 09, 2012 4:12 pm
   Subject: Re: [Tutorial] Save game screenshots!
   [ IP : Logged ]
Reply with quote
Goto Top of PostsGoto Previous PostGoto Next PostGoto Bottom of Posts

I like it a lot. Looks more interesting and makes finding save games easier too.

Did you save a thumbnail pic into the saved game, or does it try to load the level into memory to draw it?
insurrectionman
DieHard Mutant
DieHard Mutant


Joined: 07 May 2005
Last Visit: 05 Jul 2018

Topics: 87
Posts: 758
Location: Wisconsin
usa.gif

PostPosted: Fri Mar 09, 2012 4:40 pm
   Subject: Re: [Tutorial] Save game screenshots!
   [ IP : Logged ]
Reply with quote
Goto Top of PostsGoto Previous PostGoto Next PostGoto Bottom of Posts

that would be a thumbnail. Much easier to handle, because, if I remember the "load->start game->draw screen" works you would have to load the full game before you would like to.

This actually was like the In-game screenshots debugger code. I just used SDL_SaveBMP, with a scaled surface to 128x80 thumbnail. I will now try to save them via each savegame slot, then just load them up dynamically.

And writing a tutorial should be easy, thanks to Mercurial Very Happy

_________________
I'm back! I missed this community!
Youtube Channel: TreeSapThief

New Site: http://www.treesapthief.com
Twitter: @treesapthief
Tricob
Moderator
<B>Moderator</B>


Joined: 14 Mar 2005
Last Visit: 5:34 ago.

Topics: 163
Posts: 8152
Location: Neo-traditions, Inc.
usa.gif

PostPosted: Fri Mar 09, 2012 4:52 pm
   Subject: Re: [Tutorial] Save game screenshots!
   [ IP : Logged ]
Reply with quote
Goto Top of PostsGoto Previous PostGoto Next PostGoto Bottom of Posts

insurrectionman wrote:
that would be a thumbnail. Much easier to handle, because, if I remember the "load->start game->draw screen" works you would have to load the full game before you would like to.
It is doable to draw the screen in "WL_DRAW-style" without losing your current in-game data. But IMO, your approach is far more practical. Smile

The alternative is re-writing the WL_DRAW code so it can draw the game window two different ways - the first way like you see in the game, and the other way like you see in the Load-game select screen. Even if you know a lot about the game's raycaster, that method would be very heavy-handed.
insurrectionman
DieHard Mutant
DieHard Mutant


Joined: 07 May 2005
Last Visit: 05 Jul 2018

Topics: 87
Posts: 758
Location: Wisconsin
usa.gif

PostPosted: Fri Mar 09, 2012 4:58 pm
   Subject: Re: [Tutorial] Save game screenshots!
   [ IP : Logged ]
Reply with quote
Goto Top of PostsGoto Previous PostGoto Next PostGoto Bottom of Posts

Yeah, well simply put. I deep-copied an SDL_Surface curSurface at the last moment you are in-game. Scaled it down. Saved it to BMP, then read it back.

If I were to do Chris's other suggestion, I could pre-emptively load each game as I cross it on the menu. Manage to load that viewstate as the gameSurface, and then Blit it on the screen. But that would be messier. I don't think it's too terrible that there are bmp's showing.

I'll continue to work on this concept, and I'll post a tutorial about it, hopefully this weekend. I just had to get back into Wolf3D, takes the edge off all the other programming I do for homework and other side-projects. I'm hoping to make this tutorial nice and detailed, so it is educational Very Happy

_________________
I'm back! I missed this community!
Youtube Channel: TreeSapThief

New Site: http://www.treesapthief.com
Twitter: @treesapthief
insurrectionman
DieHard Mutant
DieHard Mutant


Joined: 07 May 2005
Last Visit: 05 Jul 2018

Topics: 87
Posts: 758
Location: Wisconsin
usa.gif

PostPosted: Fri Mar 09, 2012 9:23 pm
   Subject: [Idea, possibly tutorial coming] Save game screenshots!
   [ IP : Logged ]
Reply with quote
Goto Top of PostsGoto Previous PostGoto Next PostGoto Bottom of Posts

UPDATED: 3/21/2012 (all errors removed, and tutorial works)

In wl_menu.h

Change this:
::: CODE :::

#define LSM_X   10
#define LSM_Y   55

Add this after "#define LSM_H 10*13+10":

::: CODE :::

#define LSP_X   184
#define LSP_Y   80
#define LSP_W   128
#define LSP_H   80
#define BMP_SAVE "savegam?.svg"



It does save in .bmp format, I just use .svg so they aren't viewable.

In id_vl.h

Add this:

::: CODE :::

extern SDL_Surface *screen, *screenBuffer, *curSurface, *lastGameSurface;


and change this:

::: CODE :::

byte VL_GetPixel        (SDL_Surface *surface, int x, int y);


Add this after that line:

::: CODE :::

void VL_SetSaveGameSlot();


In id_vl.cpp

Add this below "SDL_Surface *curSurface = NULL;"

::: CODE :::

SDL_Surface *lastGameSurface = NULL;


Now modify VL_GetPixel to this:

::: CODE :::

byte VL_GetPixel (SDL_Surface *surface, int x, int y)
{
    byte *ptr;
    byte col;

    assert_ret(x >= 0 && (unsigned) x < screenWidth
            && y >= 0 && (unsigned) y < screenHeight
            && "VL_GetPixel: Pixel out of bounds!");

    ptr = VL_LockSurface(surface);
    if(ptr == NULL) return 0;

    col = ((byte *) surface->pixels)[y * curPitch + x];

    VL_UnlockSurface(surface);

    return col;
}


Now below the function "VL_GetPixel" paste this:

::: CODE :::

/*
==============================
=
= SDL_DuplicateSurface
=
= Deep copies SDL_Surface
=
==============================
*/
SDL_Surface* SDL_DuplicateSurface (SDL_Surface* surf)
{
    SDL_Surface* cpy;
    cpy = (SDL_Surface *)malloc(sizeof(SDL_Surface));
    memcpy((SDL_Surface *)cpy, (SDL_Surface *)surf, sizeof(SDL_Surface));
    cpy->format = (SDL_PixelFormat *)malloc(sizeof(SDL_PixelFormat));
    memcpy((SDL_PixelFormat *)cpy->format, (SDL_PixelFormat *)surf->format,
    sizeof(SDL_PixelFormat));
    size_t size = surf->pitch * surf->h;
    cpy->pixels = malloc(size);
    memcpy((Uint8 *)cpy->pixels, (Uint8 *)surf->pixels, size * sizeof(Uint8));
    return cpy;
}

/*
==============================
=
= DrawPixel
=
= Draws the pixel onto the surface
=
==============================
*/
void DrawPixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
{
    int bpp = surface->format->BytesPerPixel;
    /* Here p is the address to the pixel we want to set */
    Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;

    switch(bpp) {
    case 1:
        *p = pixel;
        break;

    case 2:
        *(Uint16 *)p = pixel;
        break;

    case 3:
        if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
            p[0] = (pixel >> 16) & 0xff;
            p[1] = (pixel >> 8) & 0xff;
            p[2] = pixel & 0xff;
        } else {
            p[0] = pixel & 0xff;
            p[1] = (pixel >> 8) & 0xff;
            p[2] = (pixel >> 16) & 0xff;
        }
        break;

    case 4:
        *(Uint32 *)p = pixel;
        break;
    }
}

/*
=================================
=
= SDL_ScaleSurface
=
= Creates a surface to scaled width, then scales it accordingly
= Width and Height can be any size, not multiples of 320x200
=
=================================
*/
SDL_Surface *SDL_ScaleSurface(SDL_Surface *Surface, Uint16 Width, Uint16 Height)
{
    if(!Surface || !Width || !Height)
        return 0;
    SDL_Surface *_ret = SDL_CreateRGBSurface(Surface->flags, Width, Height, 8, 0, 0, 0, 0);
    SDL_SetColors(_ret, gamepal, 0, 256);

    double    _stretch_factor_x = (static_cast<double>(Width)  / static_cast<double>(Surface->w)),
        _stretch_factor_y = (static_cast<double>(Height) / static_cast<double>(Surface->h));
 
    for(Sint32 y = 0; y < Surface->h; y++)
        for(Sint32 x = 0; x < Surface->w; x++)
            for(Sint32 o_y = 0; o_y < _stretch_factor_y; ++o_y)
                for(Sint32 o_x = 0; o_x < _stretch_factor_x; ++o_x)
                    DrawPixel(_ret, static_cast<Sint32>(_stretch_factor_x * x) + o_x,
                        static_cast<Sint32>(_stretch_factor_y * y) + o_y, VL_GetPixel(Surface, x, y));
    return _ret;
}

/*
=================
=
= VL_SetSaveGameSlot
=
=================
*/
void VL_SetSaveGameSlot() {
    lastGameSurface = SDL_ScaleSurface(SDL_DuplicateSurface(curSurface), 128, 80);
}



Open wl_main.cpp and change the two occurances of:

::: CODE :::

VW_Bar (0,189,300,11,VL_GetPixel(0,0));


to this:

::: CODE :::

VW_Bar (0,189,300,11,VL_GetPixel(curSurface,0,0));


Now open wl_menu.cpp and go to "CP_SaveGame"

Add this:

::: CODE :::

    char savepath[300];
    char input[32];
    char picpath[300];
    char bmpName[13] = BMP_SAVE;



Search for "SaveTheGame" and it should be in the "if (quick)" block:

Add this after that function call:

::: CODE :::

           
            bmpName[7] = which + '0';
            if(configdir[0]) {
                snprintf(picpath, sizeof(picpath), "%s/%s", configdir, bmpName);
            }
            else {
                strcpy(picpath, bmpName);
            }

            unlink (picpath);
            SDL_SaveBMP(lastGameSurface, picpath);



Search again for "SaveTheGame", add the same block below that as well.

Now search for the function "TrackWhichGame",
Add this after the PrintLSEntry function calls:

::: CODE :::

    char loadpath[300];
    char bmpName[13] = BMP_SAVE;
    bmpName[7] = w + '0';

    if(configdir[0]) {
        snprintf(loadpath, sizeof(loadpath), "%s/%s", configdir, bmpName);
    }
    else {
        strcpy(loadpath, bmpName);
    }

    DrawWindow (LSP_X - 1, LSP_Y - 1, LSP_W + 1, LSP_H + 1, 0x00);
    SDL_Surface *bmpSurface = SDL_LoadBMP(bmpName);
    if (bmpSurface != NULL) {
        VL_LatchToScreenScaledCoord(bmpSurface, 0, 0, LSP_W, LSP_H, LSP_X*scaleFactor, LSP_Y*scaleFactor);
    }



Now to "DrawLoadSaveScreen":

Add this after the DrawWindow call:

::: CODE :::

    DrawWindow (LSP_X - 1, LSP_Y - 1, LSP_W + 1, LSP_H + 1, 0x00);


Now go to "CP_CheckQuick" and add this as the first line of "case sc_F8:":

::: CODE :::

            VL_SetSaveGameSlot();


Add lastly in wl_play.cpp, in the function CheckKeys, add this:

::: CODE :::

   if ((scan >= sc_F1 && scan <= sc_F9) || scan == sc_Escape || buttonstate[bt_esc])
    {
        int lastoffs = StopMusic ();
        VL_SetSaveGameSlot();
        ClearMemory ();
        VW_FadeOut ();


That should be it. I have been revisioning this tutorial, coming up with a few simpler calls to make, so that the code is not so intrusive, and that it could possibly be used for other things.

Enjoy and let me know if there are any bugs, anything I may have missed.

_________________
I'm back! I missed this community!
Youtube Channel: TreeSapThief

New Site: http://www.treesapthief.com
Twitter: @treesapthief


Last edited by insurrectionman on Wed Mar 21, 2012 4:17 pm; edited 6 times in total
Tricob
Moderator
<B>Moderator</B>


Joined: 14 Mar 2005
Last Visit: 5:34 ago.

Topics: 163
Posts: 8152
Location: Neo-traditions, Inc.
usa.gif

PostPosted: Sat Mar 10, 2012 8:25 pm
   Subject: Re: [Tutorial] Save game screenshots!
   [ IP : Logged ]
Reply with quote
Goto Top of PostsGoto Previous PostGoto Next PostGoto Bottom of Posts

insurrectionman wrote:
I don't think it's too terrible that there are bmp's showing.
Well, if it bothers you, you can put the BMP file data at the beginning of the saved game file, and have it load up the rest if the user selects that saved game. Smile
insurrectionman
DieHard Mutant
DieHard Mutant


Joined: 07 May 2005
Last Visit: 05 Jul 2018

Topics: 87
Posts: 758
Location: Wisconsin
usa.gif

PostPosted: Sun Mar 11, 2012 12:41 pm
   Subject: Re: [Tutorial] Save game screenshots!
   [ IP : Logged ]
Reply with quote
Goto Top of PostsGoto Previous PostGoto Next PostGoto Bottom of Posts

That could very well work. I'll look into that. Thanks.

_________________
I'm back! I missed this community!
Youtube Channel: TreeSapThief

New Site: http://www.treesapthief.com
Twitter: @treesapthief
Dean
Moderator
<B>Moderator</B>


Joined: 10 Jan 2006
Last Visit: 18 Jan 2018

Topics: 52
Posts: 2189
Location: Australia
australia.gif

PostPosted: Fri Mar 16, 2012 9:27 pm
   Subject: Re: [Tutorial] Save game screenshots!
   [ IP : Logged ]
Reply with quote
Goto Top of PostsGoto Previous PostGoto Next PostGoto Bottom of Posts

This is an outstanding feature in my opinion and one I would love to see in, well, lterally every single mod! It would just make things so much simpler.

Can't wait to see this fully developed and begin being added to mod releases! Smile

_________________
The Wolfenstein 3d Blog
The Wolfenstein 3d Blog is now on Facebook!

"Strong minds discuss ideas, average minds discuss events, weak minds discuss people" - Socrates
insurrectionman
DieHard Mutant
DieHard Mutant


Joined: 07 May 2005
Last Visit: 05 Jul 2018

Topics: 87
Posts: 758
Location: Wisconsin
usa.gif

PostPosted: Sun Mar 18, 2012 6:42 am
   Subject: Re: [Tutorial] Save game screenshots!
   [ IP : Logged ]
Reply with quote
Goto Top of PostsGoto Previous PostGoto Next PostGoto Bottom of Posts

Well, after a brief attempt. I found that I forgot SDL_Surface is a class object. I cannot just save that directly to the file :/ unless I serialize it. I looked into it, and nothing too promising. So I think that the current tutorial I have there should do justice. No one has officially tested it yet. I think I may do that for kicks and giggles, so that no one runs into any problems. I think all that I missed was the location of the file would be stored in the same configdir as the save games and config file.

Should be a simple update.

_________________
I'm back! I missed this community!
Youtube Channel: TreeSapThief

New Site: http://www.treesapthief.com
Twitter: @treesapthief
insurrectionman
DieHard Mutant
DieHard Mutant


Joined: 07 May 2005
Last Visit: 05 Jul 2018

Topics: 87
Posts: 758
Location: Wisconsin
usa.gif

PostPosted: Sun Mar 18, 2012 9:28 am
   Subject: Re: [Tutorial] Save game screenshots!
   [ IP : Logged ]
Reply with quote
Goto Top of PostsGoto Previous PostGoto Next PostGoto Bottom of Posts

Okay, I have updated the code to include the load/save path like the savegame files. If anyone would like to test out my tutorial, feel free to. I will try to do it on spare time that I have.

_________________
I'm back! I missed this community!
Youtube Channel: TreeSapThief

New Site: http://www.treesapthief.com
Twitter: @treesapthief
Ipank7000
Bring 'em On
Bring 'em On


Joined: 03 Sep 2011
Last Visit: 18 Sep 2016

Topics: 16
Posts: 100
Location: Depok, Indonesia
indonesia.gif

PostPosted: Sun Mar 18, 2012 11:20 pm
   Subject: Re: [Tutorial] Save game screenshots!
   [ IP : Logged ]
Reply with quote
Goto Top of PostsGoto Previous PostGoto Next PostGoto Bottom of Posts

Hey it looks nice, thanks for tut

_________________
Schutzstaffel!
ronwolf1705
Moderator
<B>Moderator</B>


Joined: 31 Jul 2006
Last Visit: 2:59 ago.

Topics: 72
Posts: 3751

blank.gif

PostPosted: Mon Mar 19, 2012 10:25 am
   Subject: Re: [Tutorial] Save game screenshots!
   [ IP : Logged ]
Reply with quote
Goto Top of PostsGoto Previous PostGoto Next PostGoto Bottom of Posts

Once this one has been fully tested, I'll add it to the tutorials list. Nice work! Smile
insurrectionman
DieHard Mutant
DieHard Mutant


Joined: 07 May 2005
Last Visit: 05 Jul 2018

Topics: 87
Posts: 758
Location: Wisconsin
usa.gif

PostPosted: Mon Mar 19, 2012 2:51 pm
   Subject: Re: [Tutorial] Save game screenshots!
   [ IP : Logged ]
Reply with quote
Goto Top of PostsGoto Previous PostGoto Next PostGoto Bottom of Posts

It's little things like this that I end up doing. I haven't really gotten anywhere in making a full-blown mod. Even my older ones are still just sitting on a repository hard drive, unfinished.

_________________
I'm back! I missed this community!
Youtube Channel: TreeSapThief

New Site: http://www.treesapthief.com
Twitter: @treesapthief
ronwolf1705
Moderator
<B>Moderator</B>


Joined: 31 Jul 2006
Last Visit: 2:59 ago.

Topics: 72
Posts: 3751

blank.gif

PostPosted: Mon Mar 19, 2012 5:01 pm
   Subject: Re: [Tutorial] Save game screenshots!
   [ IP : Logged ]
Reply with quote
Goto Top of PostsGoto Previous PostGoto Next PostGoto Bottom of Posts

OT: So I guess that means we won't be seeing Doom: LR released any time soon?
insurrectionman
DieHard Mutant
DieHard Mutant


Joined: 07 May 2005
Last Visit: 05 Jul 2018

Topics: 87
Posts: 758
Location: Wisconsin
usa.gif

PostPosted: Mon Mar 19, 2012 6:58 pm
   Subject: Re: [Tutorial] Save game screenshots!
   [ IP : Logged ]
Reply with quote
Goto Top of PostsGoto Previous PostGoto Next PostGoto Bottom of Posts

@ronwolf1705: For now, yes. I have college to focus on. I have one year left. Also this summer, I may have the chance to get some good time to work on it. So it is still promising. Might even include this feature. So no worries, it still has hope.

_________________
I'm back! I missed this community!
Youtube Channel: TreeSapThief

New Site: http://www.treesapthief.com
Twitter: @treesapthief
ronwolf1705
Moderator
<B>Moderator</B>


Joined: 31 Jul 2006
Last Visit: 2:59 ago.

Topics: 72
Posts: 3751

blank.gif

PostPosted: Mon Mar 19, 2012 7:37 pm
   Subject: Re: [Tutorial] Save game screenshots!
   [ IP : Logged ]
Reply with quote
Goto Top of PostsGoto Previous PostGoto Next PostGoto Bottom of Posts

That's good to hear! Smile
insurrectionman
DieHard Mutant
DieHard Mutant


Joined: 07 May 2005
Last Visit: 05 Jul 2018

Topics: 87
Posts: 758
Location: Wisconsin
usa.gif

PostPosted: Wed Mar 21, 2012 4:19 pm
   Subject: Re: [Tutorial] Save game screenshots!
   [ IP : Logged ]
Reply with quote
Goto Top of PostsGoto Previous PostGoto Next PostGoto Bottom of Posts

Success!!! I have tested this tutorial on a fresh copy of Wolf4SDL 1.7 rev 262, so it should work no problem. All of the typos and misplaced items are all fixed.

_________________
I'm back! I missed this community!
Youtube Channel: TreeSapThief

New Site: http://www.treesapthief.com
Twitter: @treesapthief
ronwolf1705
Moderator
<B>Moderator</B>


Joined: 31 Jul 2006
Last Visit: 2:59 ago.

Topics: 72
Posts: 3751

blank.gif

PostPosted: Thu Mar 22, 2012 5:04 am
   Subject: Re: [Tutorial] Save game screenshots!
   [ IP : Logged ]
Reply with quote
Goto Top of PostsGoto Previous PostGoto Next PostGoto Bottom of Posts

Updated the tutorials list with your code. Smile
doomjedi
DieHard Wolfer
DieHard Wolfer


Joined: 21 Jul 2006
Last Visit: 14:33 ago.

Topics: 106
Posts: 2821
Location: Israel
israel.gif

PostPosted: Mon Apr 02, 2012 1:09 am
   Subject: Re: [Tutorial] Save game screenshots!
   [ IP : Logged ]
Reply with quote
Goto Top of PostsGoto Previous PostGoto Bottom of Posts

Looks most cool Smile
Display posts from previous:   
Post new topicReply to topic Time synchronized with the forum server time
DieHard Wolfers Forum Index -> SDL Code Crackers View Previous TopicRefresh this PageAdd Topic to your Browser FavoritesSearch ForumsPrint this TopicE-mail TopicGoto Page TopView Next Topic
Page 1 of 1
Jump to:  

Related topics
 Topics   Replies   Views   Last Post 
No new posts Announcement: Wolf3d & Spear of Destiny Shareware SDL Downloads
Author: BrotherTank
10 14640 Tue Aug 24, 2010 10:18 am
dcbasic View latest post
No new posts Sticky: [Tutorial] Compiling Wolf4SDL with Code::Blocks
Author: dcbasic
90 22956 Wed May 24, 2017 7:53 pm
Falcon*93 View latest post
No new posts [HELP] sounds crush game?
Author: Raziel
23 6734 Wed Jul 30, 2008 12:41 pm
RichterBelmont12 View latest post
No new posts [Help] Gun Bobbing in SDL
Author: RichterBelmont12
8 2679 Wed Jul 23, 2008 6:37 pm
Tricob View latest post
No new posts [SDL] Apply 2nd ScaleFactor to selected (hi-res) vga gfx
Author: Andy_Nonymous
9 4247 Sun Apr 27, 2008 2:30 am
AlumiuN View latest post
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
   You cannot delete your posts in this forum
You cannot vote in polls in this forum


Copyright ©2003-2008 DieHard Wolfers
A Modified subBunker Theme by BrotherTank
Powered by phpBB © 2001, 2005 phpBB Group