mirror of
https://github.com/suloku/gcmm.git
synced 2026-03-22 02:14:07 -05:00
- command line for both wii and gamecube - support sdgecko in wii mode - you can now insert/remove devices without reboot via device selector
330 lines
8.8 KiB
C
330 lines
8.8 KiB
C
/****************************************************************************
|
|
* bitmap.c
|
|
*
|
|
* libogc example to display a Windows bitmap.
|
|
*
|
|
* NOTE: Windows BMP must comply to the following:
|
|
* 24-bit uncompressed (99.99% of Windows Editor output)
|
|
* Be less than or equal to 640 x 480(MPAL/NTSC) 640x528(PAL)
|
|
*
|
|
* This example decodes a BMP file onto the linear framebuffer.
|
|
****************************************************************************/
|
|
#include <gccore.h>
|
|
#include <ogcsys.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "bitmap.h"
|
|
#include "freetype.h"
|
|
#include "gci.h"
|
|
#include "sdsupp.h"
|
|
|
|
#ifdef DARK_MODE
|
|
#include "bg_dark_bmp.h"
|
|
#else
|
|
#include "bg_bmp.h"
|
|
#endif
|
|
|
|
#ifdef HW_DOL
|
|
extern u8 CUR_DEVICE;
|
|
extern bool have_sd;
|
|
#ifdef DARK_MODE
|
|
#include "bg_dark_gcload_bmp.h"
|
|
#include "bg_dark_sd2sp2_bmp.h"
|
|
#else
|
|
#include "bg_gcload_bmp.h"
|
|
#include "bg_sd2sp2_bmp.h"
|
|
#endif
|
|
#endif
|
|
extern u8 selector_flag;
|
|
|
|
extern card_direntry gci;
|
|
//*extern GXRModeObj *vmode; /*** Graphics Mode Object ***/
|
|
//extern u32 *xfb[2] = { NULL, NULL }; /*** Framebuffers ***/
|
|
//extern int whichfb = 0; /*** Frame buffer toggle ***/
|
|
|
|
/****************************************************************************
|
|
* Supporting Functions
|
|
*
|
|
* Intel to PowerPC
|
|
* FLIP32 Convert little to big endian ints.
|
|
* FLIP16 Convert little to big endian shorts.
|
|
* CvtRGB Convert RGB pixels to Y1CbY2Cr.
|
|
****************************************************************************/
|
|
u32 FLIP32(u32 value) {
|
|
u32 b;
|
|
|
|
b = (value & 0xff) << 24;
|
|
b |= (value & 0xff00) << 8;
|
|
b |= (value & 0xff0000) >> 8;
|
|
b |= (value & 0xff000000) >> 24;
|
|
|
|
return b;
|
|
}
|
|
|
|
u16 FLIP16(u16 value) {
|
|
return ((value & 0x00ff) << 8) | ((value & 0xff00) >> 8);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* CvtRGB
|
|
*
|
|
* This function simply returns two RGB pixels as one Y1CbY2Cr.
|
|
*****************************************************************************/
|
|
u32 CvtRGB(u8 r1, u8 g1, u8 b1, u8 r2, u8 g2, u8 b2) {
|
|
int y1, cb1, cr1, y2, cb2, cr2, cb, cr;
|
|
|
|
y1 = (299 * r1 + 587 * g1 + 114 * b1) / 1000;
|
|
cb1 = (-16874 * r1 - 33126 * g1 + 50000 * b1 + 12800000) / 100000;
|
|
cr1 = (50000 * r1 - 41869 * g1 - 8131 * b1 + 12800000) / 100000;
|
|
|
|
y2 = (299 * r2 + 587 * g2 + 114 * b2) / 1000;
|
|
cb2 = (-16874 * r2 - 33126 * g2 + 50000 * b2 + 12800000) / 100000;
|
|
cr2 = (50000 * r2 - 41869 * g2 - 8131 * b2 + 12800000) / 100000;
|
|
|
|
cb = (cb1 + cb2) >> 1;
|
|
cr = (cr1 + cr2) >> 1;
|
|
|
|
return (y1 << 24) | (cb << 16)| (y2 << 8)| cr;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Windows 24-Bit Bitmap Header
|
|
*
|
|
* These are only the values which are important for GC.
|
|
****************************************************************************/
|
|
typedef struct {
|
|
u16 bfMagic; /*** Always BM ***/
|
|
u32 bfSize; /*** Size of file ***/
|
|
u32 bfReserved; /*** Always 0 ***/
|
|
u32 bfOffset; /*** Offset to pixel data ***/
|
|
u32 biImageHdrSize; /*** Size of Image info header ***/
|
|
u32 biWidth; /*** Width of bitmap ***/
|
|
u32 biHeight; /*** Height of bitmap ***/
|
|
u16 biPlanes; /*** Number of planes ***/
|
|
u16 biBitsPerPixel; /*** Bits per pixel ***/
|
|
u32 biCompression; /*** Is this compressed? ***/
|
|
} __attribute__ ((__packed__)) WINBITMAP;
|
|
|
|
/****************************************************************************
|
|
* ShowBMP
|
|
*
|
|
* This function does some basic checks on the bitmap, to make sure it's the
|
|
* format expected.
|
|
*
|
|
* It will display the bitmap data centred on the NEXT framebuffer.
|
|
****************************************************************************/
|
|
u32 ShowBMP(u8 * bmpfile) {
|
|
WINBITMAP *bitmap;
|
|
u32 fbwidth, width, height;
|
|
u8 *bgr;
|
|
u32 fboffset;
|
|
u32 rows, cols;
|
|
|
|
bitmap = (WINBITMAP *) bmpfile;
|
|
|
|
/*** First check, is this a windows bitmap ? ***/
|
|
if (memcmp (&bitmap->bfMagic, "BM", 2))
|
|
return 0;
|
|
|
|
/*** Only support single plane ***/
|
|
if (FLIP16 (bitmap->biPlanes) != 1)
|
|
return 0;
|
|
|
|
/*** Only support non-compressed ***/
|
|
if (FLIP32 (bitmap->biCompression) != 0)
|
|
return 0;
|
|
|
|
/*** 24 bits per pixel ***/
|
|
if (FLIP16 (bitmap->biBitsPerPixel) != 24)
|
|
return 0;
|
|
|
|
width = FLIP32 (bitmap->biWidth);
|
|
height = FLIP32 (bitmap->biHeight);
|
|
|
|
/*** Will the bitmap fit in the framebuffer? ***/
|
|
if ((width > 640) || (height > vmode->xfbHeight))
|
|
return 0;
|
|
|
|
/*** Looks like decoding this is ok ***/
|
|
bgr = (u8 *) bmpfile + FLIP32 (bitmap->bfOffset);
|
|
|
|
fbwidth = width;
|
|
if (fbwidth & 1)
|
|
fbwidth++;
|
|
|
|
/***
|
|
* Windows BMP files are stored left-to-right, bottom-to-top
|
|
***/
|
|
|
|
/*** Centre width ***/
|
|
fboffset = ((640 - fbwidth) >> 1) >> 1;
|
|
|
|
/*** Centre height ***/
|
|
fboffset += (((vmode->xfbHeight - height) >> 1) * 320);
|
|
fboffset += (height * 320);
|
|
|
|
/*** Move to NEXT framebuffer ***/
|
|
whichfb ^= 1;
|
|
|
|
//Move background in the "device selection" screen to center the left pane with the GC memory card logo
|
|
if (selector_flag)
|
|
{
|
|
DrawBoxFilled(0,0,vmode->fbWidth-1,vmode->xfbHeight-1, COL_BG2);
|
|
for (rows = 0; rows < height; rows++) {
|
|
for (cols = 0; cols < (fbwidth >> 1); cols++) {
|
|
if (rows < 64 || rows > 398 || cols < (31>>1) || cols > (341>>1))
|
|
{
|
|
//xfb[whichfb][fboffset + cols] =CvtRGB (255,255,255,255,255,255);
|
|
}
|
|
else
|
|
{
|
|
xfb[whichfb][fboffset-(320*20) + (66)+cols] =CvtRGB (bgr[2], bgr[1], bgr[0],
|
|
bgr[5], bgr[4], bgr[3]);
|
|
}
|
|
|
|
bgr += 6;
|
|
}
|
|
|
|
fboffset -= 320; /*** Go up one row ***/
|
|
|
|
} /*** Outer row loop ***/
|
|
}
|
|
else
|
|
{
|
|
for (rows = 0; rows < height; rows++) {
|
|
for (cols = 0; cols < (fbwidth >> 1); cols++) {
|
|
xfb[whichfb][fboffset + cols] =CvtRGB (bgr[2], bgr[1], bgr[0],
|
|
bgr[5], bgr[4], bgr[3]);
|
|
bgr += 6;
|
|
}
|
|
|
|
fboffset -= 320; /*** Go up one row ***/
|
|
|
|
} /*** Outer row loop ***/
|
|
}
|
|
|
|
/*** Setup the video to display this picture ***/
|
|
/*VIDEO_SetNextFramebuffer (xfb[whichfb]);
|
|
VIDEO_Flush ();
|
|
VIDEO_WaitVSync ();*/
|
|
|
|
return 1;
|
|
}
|
|
|
|
/***
|
|
ShowBanner is ShowBMP but modified to be simpler. We don't need to
|
|
check for a header since we generated the bmp BGR values directly for each save game.
|
|
***/
|
|
void ShowBanner(u8 *banner) {
|
|
u32 fbwidth, width, height;
|
|
u8 *bgr;
|
|
u32 fboffset;
|
|
u32 rows, cols;
|
|
|
|
width = CARD_BANNER_W;
|
|
height = CARD_BANNER_H;
|
|
|
|
bgr = banner;
|
|
|
|
fbwidth = width;
|
|
if (fbwidth & 1)
|
|
fbwidth++;
|
|
|
|
/*** Position banner on screen ***/
|
|
fboffset = ((640 - fbwidth) >> 1) >> 1;
|
|
fboffset += (((vmode->xfbHeight - height) >> 1) * 320);
|
|
fboffset -= (height * 320 * 2);
|
|
fboffset += (height * 10);
|
|
fboffset += width/2+3; //at this point the banner is perfectly aligned with right window
|
|
fboffset += ((height *320)>>1)+3;
|
|
|
|
//fboffset += 24; //force banner to display to the right of icon
|
|
fboffset += 43; //force banner to display to the right of icon
|
|
|
|
for (rows = 0; rows < height; rows++) {
|
|
for (cols = 0; cols < (fbwidth >> 1); cols++) {
|
|
xfb[whichfb][fboffset + cols] =CvtRGB (bgr[2], bgr[1], bgr[0],
|
|
bgr[5], bgr[4], bgr[3]);
|
|
bgr += 6;
|
|
}
|
|
/*
|
|
Go down a row here, unlike what was used in ShowBMP.
|
|
bannerload actually stores the image normally instead of
|
|
adhering to bottom-to-top format.
|
|
*/
|
|
fboffset += 320;
|
|
|
|
}
|
|
}
|
|
|
|
void ShowIcon(u8 *icon) {
|
|
u32 fbwidth, width, height;
|
|
u8 *bgr;
|
|
u32 fboffset;
|
|
u32 rows, cols;
|
|
|
|
width = CARD_BANNER_W;
|
|
height = CARD_ICON_H;
|
|
|
|
bgr = icon;
|
|
|
|
fbwidth = width;
|
|
if (fbwidth & 1)
|
|
fbwidth++;
|
|
|
|
/*** Position icon on screen ***/
|
|
fboffset = ((640 - fbwidth) >> 1) >> 1;
|
|
fbwidth = CARD_ICON_W;
|
|
fboffset += (((vmode->xfbHeight - height) >> 1) * 320);
|
|
fboffset -= (height * 320 * 2);
|
|
fboffset += (height * 10);
|
|
fboffset += width/2+3;
|
|
fboffset += ((height *320)>>1)+3;
|
|
|
|
if (SDCARD_GetBannerFmt(gci.banner_fmt) == 1 || SDCARD_GetBannerFmt(gci.banner_fmt) == 2 )
|
|
{
|
|
fboffset += 20;
|
|
}else
|
|
{
|
|
fboffset += 47; //center icon
|
|
}
|
|
|
|
|
|
for (rows = 0; rows < height; rows++) {
|
|
for (cols = 0; cols < (fbwidth >> 1); cols++) {
|
|
xfb[whichfb][fboffset + cols] =CvtRGB (bgr[2], bgr[1], bgr[0],
|
|
bgr[5], bgr[4], bgr[3]);
|
|
bgr += 6;
|
|
}
|
|
fboffset += 320;
|
|
|
|
}
|
|
}
|
|
|
|
void ClearScreen() {
|
|
|
|
#ifdef HW_DOL
|
|
|
|
#ifdef DARK_MODE
|
|
if (CUR_DEVICE == DEV_GCSDC && have_sd) ShowBMP((u8*) bg_dark_sd2sp2_bmp);
|
|
else if (CUR_DEVICE == DEV_GCODE && have_sd) ShowBMP((u8*) bg_dark_gcload_bmp);
|
|
else
|
|
ShowBMP((u8*) bg_dark_bmp);
|
|
#else
|
|
if (CUR_DEVICE == DEV_GCSDC && have_sd) ShowBMP((u8*) bg_sd2sp2_bmp);
|
|
else if (CUR_DEVICE == DEV_GCODE && have_sd) ShowBMP((u8*) bg_gcload_bmp);
|
|
else
|
|
ShowBMP((u8*) bg_bmp);
|
|
#endif
|
|
|
|
#else
|
|
#ifdef DARK_MODE
|
|
ShowBMP((u8*) bg_dark_bmp);
|
|
#else
|
|
ShowBMP((u8*) bg_bmp);
|
|
#endif
|
|
#endif
|
|
|
|
}
|