本帖最后由 zgames 于 2013-9-17 13:57 编辑
- /* 原版《金庸群侠传》开场动画播放程序
- *
- * 说明:播放《金庸群侠传》的开场动画,你需要有TIT2.MOV和TIT.WAV这两个
- * 文件。
- *
- * 程序:zgames(at)yeah(dot)net
- *
- */
- #include <SDL.h>
- #include <SDL_mixer.h>
- #define MOV_FILE "tit2.mov"
- #define WAV_FILE "tit.wav"
- #define DELAY 134 // 动画帧之间的延时,单位毫秒。
- SDL_Surface *screen;
- SDL_Color palette[256];
- SDL_Surface *cur_surface;
- SDL_Surface *real_screen;
- void SelectSurface(SDL_Surface *surface)
- {
- cur_surface = surface;
- }
- void Putpixel(int x, int y, Uint8 c)
- {
- Uint8 *p = (Uint8 *)(cur_surface->pixels + y * cur_surface->pitch) + x;
- *p = c;
- }
- int DecodePalette(FILE *fp)
- {
- int i;
- int pos=0, n=0;
- int packets=0;
- fread(&packets, 2, 1, fp); // 重复次数
- while (packets-- > 0)
- {
- pos += fgetc(fp); // 需要修改的起始下标
- n = fgetc(fp); // 要写入几组?每组3个字节。
- if (n==0)
- {
- n = 256;
- }
- for (i=pos; i<pos+n; i++)
- {
- palette[i].r = fgetc(fp);
- palette[i].g = fgetc(fp);
- palette[i].b = fgetc(fp);
- palette[i].unused = 0;
- }
- pos += n;
- }
- return 0;
- }
- void DecodeChunkType7(FILE *fp)
- {
- Sint16 v;
- int lines = 0;
- Uint16 wd=0;
- int x = 0;
- int y = 0;
- fread(&v, 2, 1, fp);
- if (v > 200)
- {
- fprintf(stderr, "you should not see this!\n");
- return;
- }
- lines = (Uint16)v;
- while (1)
- {
- fread(&v, 2, 1, fp);
- if (v < 0)
- {
- if (v & 0x4000)
- {
- v = -v;
- if (v > 200)
- {
- return;
- }
- y += (int)v;
- x=0;
- }
- else
- {
- fprintf(stderr, "wd === ");
- wd = (Uint16)v;
- }
- continue;
- }
- else if (v > 0)
- {
- int n;
- if (v > 320)
- {
- return;
- }
- n = v;
- while (n-- > 0)
- {
- x += fgetc(fp); // skip some points
- v = (Sint8) fgetc(fp);
- v <<= 1;
- if (v < 0)
- {
- v = -v;
- Uint32 n = v>>2;
- Uint8 t = v & 3;
- int lo = fgetc(fp);
- int hi = fgetc(fp);
- while (n-- > 0)
- {
- Putpixel(x++, y, lo);
- Putpixel(x++, y, hi);
- Putpixel(x++, y, lo);
- Putpixel(x++, y, hi);
- }
- while (t-- > 0)
- {
- Putpixel(x++, y, lo);
- }
- }
- else if (v > 0)
- {
- int n = (Uint8)(v & 0xff);
- while (n-->0)
- {
- Putpixel(x++, y, fgetc(fp));
- }
- }
- }
- }
- if (wd)
- {
- Putpixel(x++, y, wd & 0xff);
- wd = 0;
- }
- if (--lines == 0)
- {
- break;
- }
- y++;
- x = 0;
- }
- }
- void DecodeChunkType12(FILE *fp)
- {
- Sint16 v=0;
- int lines = 0;
- int x = 0;
- int y = 0;
- fread(&v, 2, 1, fp);
- y += v; // 跳过一些行。修改y时一定要同时修改vaddr
- x = 0;
- fread(&v, 2, 1, fp);
- if (v > 200)
- {
- // shoud not get here.
- return;
- }
- lines = v;
- while (1)
- {
- v = fgetc(fp);
- if (v)
- {
- int n = v;
- while (n-- > 0)
- {
- x += fgetc(fp);
- v = (Sint8) fgetc(fp);
- if (v < 0)
- {
- int n = -v;
- int b = fgetc(fp);
- while (n-- > 0)
- {
- Putpixel(x++, y, b);
- }
- }
- else if (v > 0)
- {
- int n = v;
- while (n-- > 0)
- {
- Putpixel(x++, y, fgetc(fp));
- }
- }
- }
- }
- if (--lines == 0)
- {
- break;
- }
- y++;
- x = 0;
- }
- }
- void DecodeChunkType15(FILE *fp)
- {
- int y;
- int x;
- for (y=0; y<200; y++)
- {
- fgetc(fp);
- for (x=0; x<320; )
- {
- Sint8 c = (Sint8) fgetc(fp);
- if (c < 0)
- {
- c = -c;
- while (c-- > 0)
- Putpixel(x++, y, fgetc(fp));
- }
- else
- {
- int v = fgetc(fp);
- while (c-- > 0)
- Putpixel(x++, y, v);
- }
- }
- }
- }
- // RAW data
- void DecodeChunkType16(FILE *fp)
- {
- int x, y;
- for (y=0; y<200; y++)
- {
- for (x=0; x<320; x++)
- {
- Putpixel(x, y, fgetc(fp));
- }
- }
- }
- int CloseWindowPressed(void)
- {
- int ret = 0;
- SDL_Event event;
- while (SDL_PollEvent(&event))
- {
- switch (event.type)
- {
- case SDL_QUIT:
- ret = 1;
- break;
- case SDL_ACTIVEEVENT:
- if (event.active.state & SDL_APPACTIVE) {
- if (event.active.gain) {
- fprintf(stderr, "App activated.\n");
- } else {
- fprintf(stderr, "App iconified.\n");
- }
- }
- default:
- break;
- }
- }
- return ret;
- }
- void DecodeChunk(FILE *fp, int type)
- {
- static int sp = 0;
- if (sp)
- {
- SDL_SetPalette(real_screen, SDL_LOGPAL | SDL_PHYSPAL, palette, 0, 256);
- sp = 0;
- }
- switch (type)
- {
- case 4:
- DecodePalette(fp);
- sp = 1;
- break;
- case 15:
- DecodeChunkType15(fp);
- break;
- case 7:
- DecodeChunkType7(fp);
- break;
- case 12:
- DecodeChunkType12(fp);
- break;
- case 16:
- DecodeChunkType16(fp);
- break;
- default:
- fprintf(stderr, "type = %d, file pos: %d\n", type, ftell(fp));
- break;
- }
- }
- void RenderScreen(void)
- {
- SDL_SoftStretch(screen, NULL, real_screen, NULL);
- SDL_UpdateRect(real_screen, 0, 0, 0, 0);
- }
- int Audio_Init(void)
- {
- if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
- return -1;
- if (Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 4096) < 0)
- return -1;
- return 0;
- }
- void Audio_Quit(void)
- {
- Mix_HaltMusic();
- Mix_CloseAudio();
- }
- int SeekNextChunk(FILE *fp)
- {
- static long pos = 0;
- Uint32 dw;
- fseek(fp, pos, SEEK_SET);
- fread(&dw, 4, 1, fp);
- if (dw == 0xFFFFFFFF)
- {
- return 0;
- }
- pos = pos + dw;
- return 1;
- }
- int GetChunkType(FILE *fp)
- {
- Uint16 dw;
- fread(&dw, 2, 1, fp);
- return dw;
- }
- #include "icon.c"
- void SetSDLWindowIcon(void)
- {
- SDL_RWops *rw;
- SDL_Surface *icon = NULL;
- rw = SDL_RWFromMem(logo_data, sizeof(logo_data));
- icon = SDL_LoadBMP_RW(rw, 0);
- SDL_FreeRW(rw);
- SDL_SetColorKey(icon, SDL_SRCCOLORKEY, SDL_MapRGB(icon->format, 255, 0, 255));
- SDL_WM_SetIcon(icon, NULL);
- SDL_FreeSurface(icon);
- }
- const char *jy_window_title = "\xe9\x87\x91\xe5\xba\xb8\xe7\xbe\xa4\xe4\xbe\xa0\xe4\xbc\xa0 zgames@yeah.net";
- const char *jy_iconic_title = "\xe9\x87\x91\xe5\xba\xb8\xe7\xbe\xa4\xe4\xbe\xa0\xe4\xbc\xa0";
- int main(int argc, char *argv[])
- {
- FILE *mov_fp = NULL;
- Mix_Music *music = NULL;
- Uint32 t1 = 0;
- Uint32 t2 = 0;
- int run = 1;
- SDL_Init(SDL_INIT_EVERYTHING);
- freopen("error.log", "w", stderr);
- SetSDLWindowIcon();
- SDL_WM_SetCaption(jy_window_title, jy_iconic_title);
- real_screen = SDL_SetVideoMode(640, 480, 8, SDL_HWSURFACE | SDL_HWPALETTE);
- if (!real_screen)
- {
- fprintf(stderr, "cann't set video mode!\n");
- exit(-1);
- }
- screen = SDL_CreateRGBSurface(real_screen->flags & ~SDL_HWSURFACE,
- 320, 200, 8,
- real_screen->format->Rmask,
- real_screen->format->Gmask,
- real_screen->format->Bmask,
- real_screen->format->Amask);
- Audio_Init();
- music = Mix_LoadMUS(WAV_FILE);
- if (!music)
- {
- fprintf(stderr, "cannot open file %s.", MOV_FILE);
- Audio_Quit();
- SDL_Quit();
- exit(-1);
- }
- SelectSurface(screen);
- mov_fp = fopen("tit2.mov", "rb");
- if (!mov_fp)
- {
- fprintf(stderr, "cannot open file %s.", MOV_FILE);
- Audio_Quit();
- SDL_Quit();
- exit(-1);
- }
- // 数据块共有5种类型
- // 4: 调色板数据
- // 7, 12, 15: 压缩位图数据
- // 16: 原始位图数据,可直接复制到屏幕。
-
- Mix_PlayMusic(music, 1);
- t1 = SDL_GetTicks();
- SeekNextChunk(mov_fp);
- while (run)
- {
- int type=0;
- if (CloseWindowPressed())
- goto getout;
-
- while (t1 + DELAY > SDL_GetTicks())
- {
- SDL_Delay(10);
- }
- while (! (t1 + DELAY > SDL_GetTicks()) && run)
- {
- type = GetChunkType(mov_fp);
- if (type != 4)
- t1 += DELAY;
- DecodeChunk(mov_fp, type);
- run = SeekNextChunk(mov_fp);
- }
- RenderScreen();
- }
- while (!CloseWindowPressed())
- {
- SDL_Delay(30);
- }
- getout:
- Mix_HaltMusic();
- if (music)
- Mix_FreeMusic(music);
- if (mov_fp)
- fclose(mov_fp);
- Audio_Quit();
- SDL_FreeSurface(screen);
- SDL_Quit();
- return 0;
- }
复制代码 ============================================================================================
破解完成。
这只是动画播放程序,把本程序和原版游戏里的TIT2.MOV和TIT.WAV这两个文件放在一个文件夹里才可以播放动画。
要是你找不到数据文件,可以联系我。
|