diff --git a/source/freetype.c b/source/freetype.c index 9debfb6..94e3449 100644 --- a/source/freetype.c +++ b/source/freetype.c @@ -38,7 +38,8 @@ extern card_stat CardStatus; extern int cancel; extern int doall; extern int mode; -extern s32 MEM_CARD; +extern s32 MEM_CARD; + extern u16 bannerdata[CARD_BANNER_W*CARD_BANNER_H] ATTRIBUTE_ALIGN (32); extern u8 bannerdataCI[CARD_BANNER_W*CARD_BANNER_H] ATTRIBUTE_ALIGN (32); extern u8 icondata[8][1024] ATTRIBUTE_ALIGN (32); @@ -46,8 +47,11 @@ extern u16 icondataRGB[8][1024] ATTRIBUTE_ALIGN (32); extern u16 tlut[9][256] ATTRIBUTE_ALIGN (32); extern u16 tlutbanner[256] ATTRIBUTE_ALIGN (32); extern int numicons; -extern int frametable[8]; -extern int lastframe; +extern int frametable[2*CARD_MAXICONS - 2]; +extern int iconindex[2*CARD_MAXICONS - 2]; +extern int lastframe; +extern int lasticon; + extern Header cardheader; extern s32 memsize, sectsize; extern syssramex *sramex; @@ -64,7 +68,8 @@ extern int screenheight; extern u32 *xfb[2]; extern int whichfb; extern GXRModeObj *vmode; -extern int vmode_60hz; +extern int vmode_60hz; +extern u32 retraceCount; /*** File listings ***/ extern card_dir CardList[]; @@ -824,18 +829,6 @@ void showSaveInfo(int sel) else if (SDCARD_GetBannerFmt(gci.banner_fmt) == CARD_BANNER_CI) { bannerloadCI(bannerdataCI, tlutbanner); } - - //Show first icon - if ((gci.icon_fmt&CARD_ICON_MASK)== 1) { - //CI with shared palette - iconloadCI(icondata[0], tlut[8]); - } - else if ((gci.icon_fmt&CARD_ICON_MASK)== 3) { - iconloadCI(icondata[0], tlut[0]); - } - else if ((gci.icon_fmt&CARD_ICON_MASK)== 2) { - iconloadRGB(icondataRGB[0]); - } /*** Display relevant info for this save ***/ sprintf(txt, "#%d %s/%s", sel, gamecode, company); @@ -1100,17 +1093,20 @@ static u8 CalculateFrameRate() } return FPS; } -#endif -int getdurationmilisecs(u16 icon_speed, int index) -{ - int speed = ((icon_speed >> (2*index))&CARD_SPEED_MASK)*4; +#endif +#ifdef USE_TIME +int getdurationmilisecs(u16 icon_speed, int index, int bounce) +{ + + int speed = SDCARD_GetIconSpeedBounce(icon_speed,index,bounce)*4; if(vmode_60hz){ return 1000/(60/speed); }else{ return 1000/(50/speed); } -} +} +#endif /**************************************************************************** * ShowSelector @@ -1133,10 +1129,14 @@ int ShowSelector (int saveinfo) int selection = 0; //animated icon display vars int currframe = 0; - int reverse = 0; - + int bounceindex; +#ifdef USE_TIME u64 lasttime, currtime; - lasttime = ticks_to_millisecs(gettime()); + currtime = ticks_to_millisecs(gettime()); + lasttime = currtime - 250; +#else + int i; +#endif #ifdef DEBUG_VALUES u8 fps = 0; @@ -1146,10 +1146,6 @@ int ShowSelector (int saveinfo) while (quit == 0) { - currtime = ticks_to_millisecs(gettime()); -#ifdef DEBUG_VALUES - fps = CalculateFrameRate(); -#endif if (redraw) { //clear buffers @@ -1164,59 +1160,66 @@ int ShowSelector (int saveinfo) //reinit variables redraw = 0; - reverse = 0; - currframe = 1; - lasttime = ticks_to_millisecs(gettime()); - + currframe = 0; + bounceindex = CARD_MAXICONS;//This ensures getting correct duration values for non-bouncing animations + if (SDCARD_GetIconAnim(gci.banner_fmt) == CARD_ANIM_BOUNCE) + { + bounceindex = 0; + while(SDCARD_GetIconSpeed(gci.icon_speed, bounceindex) != 0 && bounceindex < CARD_MAXICONS) + { + bounceindex++; + } + } +#ifdef USE_TIME + lasttime -= 250;//to ensure first icon will be loaded +#endif } -#ifdef DEBUG_VALUES - sprintf (test, "FPS%d numicons%d CF%d LF%d FT%d animtype%d speed%d", fps, numicons, currframe, lastframe, frametable[currframe], CHECK_BIT(gci.banner_fmt,2), ((gci.icon_speed >> (2*currframe))&CARD_SPEED_MASK)*4 ); + +#ifdef DEBUG_VALUES + fps = CalculateFrameRate(); + sprintf (test, "%d FPS%d numicons%02d lasticon%02d CF%02d LF%03d FT%03d II%02d animtype%d speed%02d", retraceCount, fps, numicons, lasticon, currframe, lastframe, frametable[currframe], iconindex[currframe], SDCARD_GetIconAnim(gci.banner_fmt), SDCARD_GetIconSpeedBounce(gci.icon_speed,currframe,bounceindex)*4 ); ShowAction(test); +#endif + if (lastframe) + { +#ifdef USE_TIME + currtime = ticks_to_millisecs(gettime()); + if((currtime - lasttime) >= getdurationmilisecs(gci.icon_speed, currframe, bounceindex) ) + { +#else + currframe = retraceCount % lastframe; + for (i = 0; i < 2 * CARD_MAXICONS - 2; ++i) + { + if (currframe < frametable[i]) + { + break; + } + } + currframe = i; #endif + //If there's a real icon show it, if not just wait until next icon frame + if ( SDCARD_GetIconFmt(gci.icon_fmt,iconindex[currframe])== 1) { + //CI with shared palette + iconloadCI(icondata[iconindex[currframe]], tlut[8]); + } + else if ( SDCARD_GetIconFmt(gci.icon_fmt,iconindex[currframe])== 3) { + iconloadCI(icondata[iconindex[currframe]], tlut[iconindex[currframe]]); + } + else if ( SDCARD_GetIconFmt(gci.icon_fmt,iconindex[currframe])== 2) { + iconloadRGB(icondataRGB[iconindex[currframe]]); + } + //ShowScreen(); - if (numicons > 1){ - - if((currtime - lasttime) >= getdurationmilisecs(gci.icon_speed, currframe) ){ - //If there's a real icon show it, if not just wait until next icon frame - if (frametable[currframe]){ - if ( ((gci.icon_fmt >> (2*currframe))&CARD_ICON_MASK)== 1) { - //CI with shared palette - iconloadCI(icondata[currframe], tlut[8]); - } - else if ( ((gci.icon_fmt >> (2*currframe))&CARD_ICON_MASK)== 3) { - iconloadCI(icondata[currframe], tlut[currframe]); - } - else if ( ((gci.icon_fmt >> (2*currframe))&CARD_ICON_MASK)== 2) { - iconloadRGB(icondataRGB[currframe]); - } - ShowScreen(); - } - - //Each bit pair in gci.icon_speed states for an icon's speed. - //Blank bit pairs can be used to delay the animation - //Check animation type (ping pong style if true) - if (CHECK_BIT(gci.banner_fmt,2)){ - if (reverse) currframe --; - if (!reverse) currframe ++; - //Bounce back - if (currframe > lastframe){ - reverse = 1; - currframe = lastframe -1; - }else if (currframe < 0){ - reverse = 0; - currframe = 1; - } - }else{ - currframe ++; - if (currframe > lastframe){ - currframe = 0; - } - } - - lasttime = currtime; - } - - } + currframe ++; + if (currframe > lasticon) + { + currframe = 0; + } +#ifdef USE_TIME + lasttime = currtime; + } +#endif + } p = PAD_ButtonsDown (0); #ifdef HW_RVL diff --git a/source/freetype.h b/source/freetype.h index 6837b8f..6af24f6 100644 --- a/source/freetype.h +++ b/source/freetype.h @@ -12,11 +12,12 @@ #define RESTORE_MODE 400 //#define RELOAD_MODE 500 /* Free mode */ -//pos 0 is less significant bit and pos 7 the most significant -#define CHECK_BIT(var,pos) ((var) & (1<<(pos))) - //Uncomment this definiton to show some debug values on screen -//#define DEBUG_VALUES +//#define DEBUG_VALUES + +//Uncomment this definiton to use time lapse for icon duration instead of retrace count +//Time code is mantained as an alternative example of animating the icons +#define USE_TIME #ifdef HW_RVL void initialise_power() ; diff --git a/source/gci.h b/source/gci.h index e2c42c7..21526d7 100644 --- a/source/gci.h +++ b/source/gci.h @@ -18,6 +18,7 @@ #define SDCARD_GetBannerFmt(banner_fmt) ((banner_fmt) & 0x03) #define SDCARD_GetIconFmt(icon_fmt,n) (((icon_fmt)>>(2*(n))) & 0x03) #define SDCARD_GetIconSpeed(icon_speed,n) (((icon_speed)>>(2*(n))) & 0x03) +#define SDCARD_GetIconSpeedBounce(icon_speed,n,i) ((n) < (i) ? (((icon_speed)>>(2*(n))) & 0x03) : (((icon_speed)>>(2*((i*2)-2-n)) & 0x03)) ) #define SDCARD_GetIconAnim(banner_fmt) ((banner_fmt) & 0x04) typedef struct { diff --git a/source/main.c b/source/main.c index 206812d..ede302d 100644 --- a/source/main.c +++ b/source/main.c @@ -44,7 +44,8 @@ GXRModeObj *vmode; /*** Graphics Mode Object ***/ u32 *xfb[2] = { NULL, NULL }; /*** Framebuffers ***/ int whichfb = 0; /*** Frame buffer toggle ***/ int screenheight; -int vmode_60hz = 0; +int vmode_60hz = 0; +u32 retraceCount; extern u8 filelist[1024][1024]; extern bool offsetchanged; @@ -53,8 +54,9 @@ s32 MEM_CARD = CARD_SLOTB; extern syssramex *sramex; extern u8 imageserial[12]; -static void updatePAD() -{ +static void updatePAD(u32 retrace) +{ + retraceCount = retrace; PAD_ScanPads(); #ifdef HW_RVL WPAD_ScanPads(); diff --git a/source/mcard.c b/source/mcard.c index d6200cc..8890ed0 100644 --- a/source/mcard.c +++ b/source/mcard.c @@ -41,8 +41,10 @@ u16 bannerdata[CARD_BANNER_W*CARD_BANNER_H] ATTRIBUTE_ALIGN (32); Needs decoding by bannerloadCI function before we can show it ***/ u8 bannerdataCI[CARD_BANNER_W*CARD_BANNER_H] ATTRIBUTE_ALIGN (32); int numicons; -int frametable[8]; -int lastframe; +int frametable[2*CARD_MAXICONS - 2]; +int iconindex[2*CARD_MAXICONS - 2]; +int lastframe; +int lasticon; /*** This matrix will serve as our array of filenames for each file on the card We add 10 to filenamelen since we add on game company info***/ u8 filelist[1024][1024]; @@ -104,7 +106,7 @@ int MountCard(int cslot) /*** Mount the card ***/ ret = CARD_Mount (cslot, SysArea, card_removed); if (ret >= 0) break; - + VIDEO_WaitVSync (); tries++; } @@ -115,7 +117,7 @@ int MountCard(int cslot) return isMounted; } /*** If this point is reached, something went wrong ***/ - + return ret; } @@ -343,59 +345,86 @@ int CardReadFileHeader (int slot, int id) offset += 3072; memcpy(tlutbanner, offset, 512); offset += 512; - } - //Icon data - check_fmt = gci.icon_fmt; - check_speed = gci.icon_speed; - int shared_pal = 0; - lastframe = 0; - numicons = 0; - for (i=0;i<8;i++){ - //this stores if the frame has a real icon or not - //no need to clear all values since we will only use the ones until last frame - frametable[i] = 0; - - //Animation speed is mandatory to be set even for a single icon - //When a speed is 0 there are no more icons - //Some games may have bits set after the "blank icon" both in - //speed (Baten Kaitos) and format (Wario Ware Inc.) bytes, which are just garbage - if (!(check_speed&CARD_ICON_MASK)){ - break; - }else - {//We've got a frame - lastframe=i; - - if (check_fmt & CARD_ICON_MASK){ - //count the number of real icons - numicons++; - frametable[i]=1; //There's a real icon - - //CI with shared palette - if ((check_fmt&CARD_ICON_MASK) == 1) { - memcpy(icondata[i], offset, 1024); + } + + //Icon data + int shared_pal = 0; + lastframe = 0; + numicons = 0; + int j =0; + i=0; + int current_icon = 0; + for (current_icon=0;i> 2; - check_speed = check_speed >> 2; - } + shared_pal = 1; + } + //CI with palette after the icon + else if (SDCARD_GetIconFmt(gci.icon_fmt,current_icon) == 3) + { + memcpy(icondata[current_icon], offset, 1024); + offset += 1024; + memcpy(tlut[current_icon], offset, 512); + offset += 512; + } + //RGB 16 bit icon + else if (SDCARD_GetIconFmt(gci.icon_fmt,current_icon) == 2) + { + memcpy(icondataRGB[current_icon], offset, 2048); + offset += 2048; + } + }else + { //Get next real icon + for(j=current_icon;j1) //We need at least 3 icons + { + j=current_icon; + for (i = current_icon-2; 0 < i; --i, ++j) + { + lastframe += SDCARD_GetIconSpeed(gci.icon_speed,i)*4; + frametable[j] = lastframe; + iconindex[j] = iconindex[i]; + } + lasticon = j-1; + } //Get the shared palette if (shared_pal) memcpy(tlut[8], offset, 512); @@ -558,7 +587,7 @@ int CardWriteFile (int slot) continue; } } - + /*** User canceled - abort ***/ CARD_Unmount (slot); WaitCardError("File already exists", err); @@ -589,13 +618,13 @@ tryagain: { WaitCardError("MCDel", err); CARD_SetCompany(NULL); - CARD_SetGamecode(NULL); + CARD_SetGamecode(NULL); CARD_Unmount (slot); return 0; } goto tryagain; } - } + } } //Return To show all so we don't have errors CARD_SetCompany(NULL); @@ -631,7 +660,7 @@ tryagain: /*** Finally, update the status ***/ CARD_SetStatus (slot, CardFile.filenum, &CardStatus); //For some reason this sets the file to Move->allowed, Copy->not allowed, Public file instead of the actual permission value - CARD_SetAttributes(slot, CardFile.filenum, &permission); + CARD_SetAttributes(slot, CardFile.filenum, &permission); #else __card_setstatusex(slot, CardFile.filenum, &gci); #endif @@ -649,7 +678,7 @@ tryagain: void WaitCardError(char *src, int error) { char msg[1024], err[256]; - + //Error message possibilites switch (error) { @@ -784,14 +813,14 @@ void MC_FormatMode(s32 slot) { int erase = 1; int err; - + //0 = B wass pressed -> ask again if (!slot){ erase = WaitPromptChoice("Are you sure you want to format memory card in slot A?", "Format", "Cancel"); }else{ erase = WaitPromptChoice("Are you sure you want to format memory card in slot B?", "Format", "Cancel"); } - + if (!erase){ if (!slot){ erase = WaitPromptChoiceAZ("All contents of memory card in slot A will be erased!", "Format", "Cancel"); @@ -837,7 +866,7 @@ void MC_FormatMode(s32 slot) //The following code is made by Ralf at GSCentral forums (gscentral.org) //http://board.gscentral.org/retro-hacking/53093.htm#post188949 -// u8 FileBuffer[MAXFILEBUFFER]: .gci file buffer +// u8 FileBuffer[MAXFILEBUFFER]: .gci file buffer // MCDATAOFFSET: .gci header size (0x40 bytes) /*************************************************************/ diff --git a/source/sdsupp.c b/source/sdsupp.c index b3e76fc..007b33f 100644 --- a/source/sdsupp.c +++ b/source/sdsupp.c @@ -29,6 +29,7 @@ extern u8 FileBuffer[MAXFILEBUFFER] ATTRIBUTE_ALIGN (32); extern Header cardheader; extern u8 CommentBuffer[64] ATTRIBUTE_ALIGN (32); + extern u16 bannerdata[CARD_BANNER_W*CARD_BANNER_H] ATTRIBUTE_ALIGN (32); extern u8 bannerdataCI[CARD_BANNER_W*CARD_BANNER_H] ATTRIBUTE_ALIGN (32); extern u8 icondata[8][1024] ATTRIBUTE_ALIGN (32); @@ -36,8 +37,11 @@ extern u16 icondataRGB[8][1024] ATTRIBUTE_ALIGN (32); extern u16 tlut[9][256] ATTRIBUTE_ALIGN (32); extern u16 tlutbanner[256] ATTRIBUTE_ALIGN (32); extern int numicons; -extern int frametable[8]; +extern int frametable[2*CARD_MAXICONS - 2]; +extern int iconindex[2*CARD_MAXICONS - 2]; extern int lastframe; +extern int lasticon; + extern u8 filelist[1024][1024]; extern u32 maxfile; extern GCI gci; @@ -254,7 +258,6 @@ int SDLoadMCImageHeader(char *sdfilename) //int bytesToRead = 0; long bytesToRead = 0; int i; - u16 check_fmt, check_speed; /*** Clear the work buffers ***/ memset (FileBuffer, 0, MAXFILEBUFFER); @@ -399,62 +402,88 @@ int SDLoadMCImageHeader(char *sdfilename) fseek(handle, MCDATAOFFSET + OFFSET + gci.icon_addr, SEEK_SET); /*** Get the Banner/Icon Data from the save file ***/ - if ((gci.banner_fmt&CARD_BANNER_MASK) == CARD_BANNER_RGB) { + if (SDCARD_GetBannerFmt(gci.banner_fmt) == CARD_BANNER_RGB) { //RGB banners are 96*32*2 in size fread (bannerdata, 1, 6144, handle); } - else if ((gci.banner_fmt&CARD_BANNER_MASK) == CARD_BANNER_CI) { + else if (SDCARD_GetBannerFmt(gci.banner_fmt) == CARD_BANNER_CI) { fread(bannerdataCI, 1, 3072, handle); fread(tlutbanner, 1, 512, handle); } //Icon data - check_fmt = gci.icon_fmt; - check_speed = gci.icon_speed; int shared_pal = 0; lastframe = 0; numicons = 0; - for (i=0;i<8;i++){ - //this stores if the frame has a real icon or not - //no need to clear all values since we will only use the ones until last frame - frametable[i] = 0; + int j =0; + i=0; + int current_icon = 0; + for (current_icon=0;i> 2; - check_speed = check_speed >> 2; } + + lasticon = current_icon-1; + //Now get icon indexes for ping-pong style icons + if (SDCARD_GetIconAnim(gci.banner_fmt) == CARD_ANIM_BOUNCE && current_icon>1) //We need at least 3 icons + { + j=current_icon; + for (i = current_icon-2; 0 < i; --i, ++j) + { + lastframe += SDCARD_GetIconSpeed(gci.icon_speed,i)*4; + frametable[j] = lastframe; + iconindex[j] = iconindex[i]; + } + lasticon = j-1; + } //Get the shared palette if (shared_pal) fread(tlut[8], 1, 512, handle);