铁血丹心

 找回密码
 我要成为铁血侠客
搜索
查看: 5959|回复: 5

[DOS] 原版《金庸群侠传》开场动画文件格式破解。

[复制链接]
发表于 2013-9-15 00:32 | 显示全部楼层 |阅读模式
本帖最后由 zgames 于 2013-9-17 13:57 编辑
  1. /* 原版《金庸群侠传》开场动画播放程序
  2. *
  3. * 说明:播放《金庸群侠传》的开场动画,你需要有TIT2.MOV和TIT.WAV这两个
  4. *       文件。
  5. *
  6. * 程序:zgames(at)yeah(dot)net
  7. *
  8. */

  9. #include <SDL.h>
  10. #include <SDL_mixer.h>

  11. #define MOV_FILE                "tit2.mov"
  12. #define WAV_FILE                "tit.wav"
  13. #define DELAY                        134                        // 动画帧之间的延时,单位毫秒。

  14. SDL_Surface         *screen;
  15. SDL_Color                 palette[256];
  16. SDL_Surface         *cur_surface;
  17. SDL_Surface         *real_screen;


  18. void SelectSurface(SDL_Surface *surface)
  19. {
  20.         cur_surface = surface;
  21. }


  22. void Putpixel(int x, int y, Uint8 c)
  23. {
  24.         Uint8 *p = (Uint8 *)(cur_surface->pixels + y * cur_surface->pitch) + x;
  25.         *p = c;
  26. }


  27. int DecodePalette(FILE *fp)
  28. {
  29.         int i;
  30.         int pos=0, n=0;
  31.         int packets=0;

  32.         fread(&packets, 2, 1, fp); // 重复次数

  33.         while (packets-- > 0)
  34.         {
  35.                 pos += fgetc(fp);                // 需要修改的起始下标
  36.                 n = fgetc(fp);                        // 要写入几组?每组3个字节。
  37.                 if (n==0)
  38.                 {
  39.                         n = 256;
  40.                 }
  41.                 for (i=pos; i<pos+n; i++)
  42.                 {
  43.                         palette[i].r = fgetc(fp);
  44.                         palette[i].g = fgetc(fp);
  45.                         palette[i].b = fgetc(fp);
  46.                         palette[i].unused = 0;
  47.                 }
  48.                 pos += n;
  49.         }
  50.         return 0;
  51. }


  52. void DecodeChunkType7(FILE *fp)
  53. {
  54.         Sint16 v;
  55.         int lines = 0;
  56.         Uint16 wd=0;
  57.         int x = 0;
  58.         int y = 0;

  59.         fread(&v, 2, 1, fp);
  60.         if (v > 200)
  61.         {
  62.                 fprintf(stderr, "you should not see this!\n");
  63.                 return;
  64.         }

  65.         lines = (Uint16)v;

  66.         while (1)
  67.         {
  68.                 fread(&v, 2, 1, fp);
  69.                 if (v < 0)
  70.                 {
  71.                         if (v & 0x4000)
  72.                         {
  73.                                 v = -v;
  74.                                 if (v > 200)
  75.                                 {
  76.                                         return;
  77.                                 }
  78.                                 y += (int)v;
  79.                                 x=0;
  80.                         }
  81.                         else
  82.                         {
  83.                                 fprintf(stderr, "wd === ");
  84.                                 wd = (Uint16)v;
  85.                         }

  86.                         continue;
  87.                 }
  88.                 else if (v > 0)
  89.                 {
  90.                         int n;

  91.                         if (v > 320)
  92.                         {
  93.                                 return;
  94.                         }

  95.                         n = v;
  96.                         while (n-- > 0)
  97.                         {
  98.                                 x += fgetc(fp);  // skip some points
  99.                                 v = (Sint8) fgetc(fp);
  100.                                 v <<= 1;

  101.                                 if (v < 0)
  102.                                 {
  103.                                         v = -v;
  104.                                         Uint32 n = v>>2;
  105.                                         Uint8 t = v & 3;
  106.                                         int lo = fgetc(fp);
  107.                                         int hi = fgetc(fp);
  108.                                         while (n-- > 0)
  109.                                         {
  110.                                                 Putpixel(x++, y, lo);
  111.                                                 Putpixel(x++, y, hi);
  112.                                                 Putpixel(x++, y, lo);
  113.                                                 Putpixel(x++, y, hi);
  114.                                         }
  115.                                         while (t-- > 0)
  116.                                         {
  117.                                                 Putpixel(x++, y, lo);
  118.                                         }
  119.                                 }
  120.                                 else if (v > 0)
  121.                                 {
  122.                                         int n = (Uint8)(v & 0xff);
  123.                                         while (n-->0)
  124.                                         {
  125.                                                 Putpixel(x++, y, fgetc(fp));
  126.                                         }
  127.                                 }
  128.                         }
  129.                 }

  130.                 if (wd)
  131.                 {
  132.                         Putpixel(x++, y, wd & 0xff);
  133.                         wd = 0;
  134.                 }

  135.                 if (--lines == 0)
  136.                 {
  137.                         break;
  138.                 }

  139.                 y++;
  140.                 x = 0;
  141.         }
  142. }


  143. void DecodeChunkType12(FILE *fp)
  144. {
  145.         Sint16 v=0;
  146.         int lines = 0;
  147.         int x = 0;
  148.         int y = 0;

  149.         fread(&v, 2, 1, fp);
  150.         y += v;        // 跳过一些行。修改y时一定要同时修改vaddr
  151.         x = 0;

  152.         fread(&v, 2, 1, fp);
  153.         if (v > 200)
  154.         {
  155.                 // shoud not get here.
  156.                 return;
  157.         }

  158.         lines = v;

  159.         while (1)
  160.         {
  161.                 v = fgetc(fp);
  162.                 if (v)
  163.                 {
  164.                         int n = v;
  165.                         while (n-- > 0)
  166.                         {
  167.                                 x += fgetc(fp);
  168.                                 v = (Sint8) fgetc(fp);
  169.                                 if (v < 0)
  170.                                 {
  171.                                         int n = -v;
  172.                                         int b = fgetc(fp);
  173.                                         while (n-- > 0)
  174.                                         {
  175.                                                 Putpixel(x++, y, b);
  176.                                         }
  177.                                 }
  178.                                 else if (v > 0)
  179.                                 {
  180.                                         int n = v;
  181.                                         while (n-- > 0)
  182.                                         {
  183.                                                 Putpixel(x++, y, fgetc(fp));
  184.                                         }
  185.                                 }
  186.                         }
  187.                 }

  188.                 if (--lines == 0)
  189.                 {
  190.                         break;
  191.                 }
  192.                 y++;
  193.                 x = 0;
  194.         }
  195. }


  196. void DecodeChunkType15(FILE *fp)
  197. {
  198.         int y;
  199.         int x;

  200.         for (y=0; y<200; y++)
  201.         {
  202.                 fgetc(fp);
  203.                 for (x=0; x<320; )
  204.                 {
  205.                         Sint8 c = (Sint8) fgetc(fp);
  206.                         if (c < 0)
  207.                         {
  208.                                 c = -c;
  209.                                 while (c-- > 0)
  210.                                         Putpixel(x++, y, fgetc(fp));
  211.                         }
  212.                         else
  213.                         {
  214.                                 int v = fgetc(fp);
  215.                                 while (c-- > 0)
  216.                                         Putpixel(x++, y, v);
  217.                         }
  218.                 }
  219.         }
  220. }


  221. // RAW data
  222. void DecodeChunkType16(FILE *fp)
  223. {
  224.         int x, y;
  225.         for (y=0; y<200; y++)
  226.         {
  227.                 for (x=0; x<320; x++)
  228.                 {
  229.                         Putpixel(x, y, fgetc(fp));
  230.                 }
  231.         }
  232. }


  233. int CloseWindowPressed(void)
  234. {
  235.         int ret = 0;
  236.         SDL_Event event;
  237.         while (SDL_PollEvent(&event))
  238.         {
  239.                 switch (event.type)
  240.                 {
  241.                         case SDL_QUIT:
  242.                                 ret = 1;
  243.                                 break;
  244.                         case SDL_ACTIVEEVENT:
  245.                                 if (event.active.state & SDL_APPACTIVE) {
  246.                                         if (event.active.gain) {
  247.                                                 fprintf(stderr, "App activated.\n");
  248.                                         } else {
  249.                                                 fprintf(stderr, "App iconified.\n");
  250.                                         }
  251.                                 }
  252.                         default:
  253.                                 break;
  254.                 }
  255.         }
  256.         return ret;
  257. }


  258. void DecodeChunk(FILE *fp, int type)
  259. {
  260.         static int sp = 0;

  261.         if (sp)
  262.         {
  263.                 SDL_SetPalette(real_screen, SDL_LOGPAL | SDL_PHYSPAL, palette, 0, 256);
  264.                 sp = 0;
  265.         }

  266.         switch (type)
  267.         {
  268.         case 4:
  269.                 DecodePalette(fp);
  270.                 sp = 1;
  271.                 break;

  272.         case 15:
  273.                 DecodeChunkType15(fp);
  274.                 break;

  275.         case 7:
  276.                 DecodeChunkType7(fp);
  277.                 break;

  278.         case 12:
  279.                 DecodeChunkType12(fp);
  280.                 break;

  281.         case 16:
  282.                 DecodeChunkType16(fp);
  283.                 break;

  284.         default:
  285.                 fprintf(stderr, "type = %d, file pos: %d\n", type, ftell(fp));
  286.                 break;
  287.         }
  288. }

  289. void RenderScreen(void)
  290. {
  291.         SDL_SoftStretch(screen, NULL, real_screen, NULL);
  292.         SDL_UpdateRect(real_screen, 0, 0, 0, 0);
  293. }

  294. int Audio_Init(void)
  295. {
  296.         if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
  297.                 return -1;
  298.         if (Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 4096) < 0)
  299.                 return -1;
  300.         return 0;
  301. }


  302. void Audio_Quit(void)
  303. {
  304.         Mix_HaltMusic();
  305.         Mix_CloseAudio();
  306. }



  307. int SeekNextChunk(FILE *fp)
  308. {
  309.         static long pos = 0;
  310.         Uint32 dw;

  311.         fseek(fp, pos, SEEK_SET);
  312.         fread(&dw, 4, 1, fp);
  313.         if (dw == 0xFFFFFFFF)
  314.         {
  315.                 return 0;
  316.         }
  317.         pos = pos + dw;
  318.         return 1;
  319. }

  320. int GetChunkType(FILE *fp)
  321. {
  322.         Uint16 dw;
  323.         fread(&dw, 2, 1, fp);
  324.         return dw;
  325. }

  326. #include "icon.c"

  327. void SetSDLWindowIcon(void)
  328. {
  329.         SDL_RWops *rw;
  330.         SDL_Surface *icon = NULL;

  331.         rw = SDL_RWFromMem(logo_data, sizeof(logo_data));
  332.         icon = SDL_LoadBMP_RW(rw, 0);
  333.         SDL_FreeRW(rw);
  334.         SDL_SetColorKey(icon, SDL_SRCCOLORKEY, SDL_MapRGB(icon->format, 255, 0, 255));
  335.         SDL_WM_SetIcon(icon, NULL);
  336.         SDL_FreeSurface(icon);

  337. }

  338. const char *jy_window_title = "\xe9\x87\x91\xe5\xba\xb8\xe7\xbe\xa4\xe4\xbe\xa0\xe4\xbc\xa0 zgames@yeah.net";
  339. const char *jy_iconic_title = "\xe9\x87\x91\xe5\xba\xb8\xe7\xbe\xa4\xe4\xbe\xa0\xe4\xbc\xa0";

  340. int main(int argc, char *argv[])
  341. {
  342.         FILE                 *mov_fp = NULL;
  343.         Mix_Music        *music = NULL;
  344.         Uint32                t1 = 0;
  345.         Uint32                t2 = 0;
  346.         int                        run = 1;

  347.         SDL_Init(SDL_INIT_EVERYTHING);
  348.         freopen("error.log", "w", stderr);
  349.         SetSDLWindowIcon();
  350.         SDL_WM_SetCaption(jy_window_title, jy_iconic_title);
  351.         real_screen = SDL_SetVideoMode(640, 480, 8, SDL_HWSURFACE | SDL_HWPALETTE);
  352.         if (!real_screen)
  353.         {
  354.                 fprintf(stderr, "cann't set video mode!\n");
  355.                 exit(-1);
  356.         }
  357.         screen = SDL_CreateRGBSurface(real_screen->flags & ~SDL_HWSURFACE,
  358.                         320, 200, 8,
  359.                         real_screen->format->Rmask,
  360.                         real_screen->format->Gmask,
  361.                         real_screen->format->Bmask,
  362.                         real_screen->format->Amask);

  363.         Audio_Init();
  364.         music = Mix_LoadMUS(WAV_FILE);
  365.         if (!music)
  366.         {
  367.                 fprintf(stderr, "cannot open file %s.", MOV_FILE);
  368.                 Audio_Quit();
  369.                 SDL_Quit();
  370.                 exit(-1);
  371.         }

  372.         SelectSurface(screen);
  373.         mov_fp = fopen("tit2.mov", "rb");
  374.         if (!mov_fp)
  375.         {
  376.                 fprintf(stderr, "cannot open file %s.", MOV_FILE);
  377.                 Audio_Quit();
  378.                 SDL_Quit();
  379.                 exit(-1);
  380.         }


  381.         // 数据块共有5种类型
  382.         // 4: 调色板数据
  383.         // 7, 12, 15: 压缩位图数据
  384.         // 16: 原始位图数据,可直接复制到屏幕。
  385.        
  386.         Mix_PlayMusic(music, 1);
  387.         t1 = SDL_GetTicks();

  388.         SeekNextChunk(mov_fp);

  389.         while (run)
  390.         {
  391.                 int type=0;

  392.                 if (CloseWindowPressed())
  393.                         goto getout;
  394.        
  395.                 while (t1 + DELAY > SDL_GetTicks())
  396.                 {
  397.                         SDL_Delay(10);
  398.                 }

  399.                 while (! (t1 + DELAY > SDL_GetTicks()) && run)
  400.                 {
  401.                         type = GetChunkType(mov_fp);
  402.                         if (type != 4)
  403.                                 t1 += DELAY;
  404.                         DecodeChunk(mov_fp, type);
  405.                         run = SeekNextChunk(mov_fp);
  406.                 }

  407.                 RenderScreen();
  408.         }

  409.         while (!CloseWindowPressed())
  410.         {
  411.                 SDL_Delay(30);
  412.         }

  413. getout:
  414.         Mix_HaltMusic();
  415.         if (music)
  416.                 Mix_FreeMusic(music);
  417.         if (mov_fp)
  418.                 fclose(mov_fp);
  419.         Audio_Quit();
  420.         SDL_FreeSurface(screen);
  421.         SDL_Quit();

  422.         return 0;
  423. }


复制代码
============================================================================================

破解完成


这只是动画播放程序,把本程序和原版游戏里的TIT2.MOV和TIT.WAV这两个文件放在一个文件夹里才可以播放动画。
要是你找不到数据文件,可以联系我。



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要成为铁血侠客

x

评分

参与人数 1声望 +18 收起 理由
KA + 18 高手

查看全部评分

【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
发表于 2013-9-15 01:09 | 显示全部楼层
这个有人制作过视频。
lz的编程习惯不太好,最后一段不应使用goto。此外音频部分有没有。
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
 楼主| 发表于 2013-9-15 08:34 | 显示全部楼层
weyl 发表于 2013-9-15 01:09
这个有人制作过视频。
lz的编程习惯不太好,最后一段不应使用goto。此外音频部分有没有。

呵呵,因为破解没完,程序实验性多一些,确实不太好看,最后还忘了关闭文件了,见笑了。
之所以做这个东西是因为我在网上找到的开场动画不完美,动画临近结尾的一段都没有,有些则是音乐和画面不同步。用DOSBOX播放DOS版《金庸》的动画速度太快。我的想法是做个原汁原味的开场动画,但是在网上找不到相关的破解资料,所以只好自己动手了。
怀念第一次看到这个动画时那种热血沸腾的感觉。
代码是你帮我排的吧,谢谢了。昨天有点困,没搞好就睡了,实在不好意思。
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
 楼主| 发表于 2013-9-17 13:57 | 显示全部楼层
破解完成了,需要的童鞋可以自己研究。希望对大家有所帮助!
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
发表于 2014-1-25 16:04 | 显示全部楼层
看的激动。。。 谢谢楼主了












慈众营销团队!!
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
发表于 2014-10-8 18:26 | 显示全部楼层
翻出了老光盘,片头不能播放,正好找到这里。
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。

本版积分规则

小黑屋|手机版|铁血丹心

GMT+8, 2024-5-2 03:48

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表