Advertisement
MrCheeze

Iwata's Pokemon Gold/Silver compression code

Apr 25th, 2020
2,537
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 41.16 KB | None | 0 0
  1. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DECODE2.DMG ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2.  
  3. ;$Id: decode2.dmg,v 1.6 1994/12/13 01:14:03 yoshiki Exp $
  4. ;*************************************************************
  5. ;   DMG用 汎用VRAMデータデコードルーチン
  6. ;           *高速版!!
  7. ;       Created by S.Iwata on June, 1989
  8. ;       (C) 1989 HAL Laboratory,inc.
  9. ;*************************************************************
  10.     include common.def
  11.     include macro.h
  12.  
  13. bank0   group   0
  14. ;
  15. ;   ビット反転テーブルの展開
  16. ;
  17.  
  18.  ifn 0
  19.     public  initlrchgdat
  20. initlrchgdat
  21.     ld  hl,lrchgdat
  22. _lp ld  b,8
  23. _lp1    rrc l
  24.     rla
  25.     dec b
  26.     jr  nz,_lp1
  27.     ld  (hli),a
  28.     inc a
  29.     jr  nz,_lp
  30.     ret
  31.  endif
  32.  
  33.     public  BankChangeDecode
  34. BankChangeDecode:
  35.     ld  (decodeBank),a
  36.  
  37.     ld  a,(rombankno)
  38.     push    af
  39.  
  40.     ld  a,(decodeBank)
  41.     BANK_SET
  42. ;   ld  (rombankno),a
  43. ;   ld  (ROMBANK),a
  44.    
  45.     call    decode
  46.  
  47.     pop af
  48.     BANK_SET
  49. ;   ld  (rombankno),a
  50. ;   ld  (ROMBANK),a
  51.     ret
  52.    
  53.  ifn 0
  54. ;
  55. ;       DMG版 データ圧縮のデータフォーマット
  56. ;
  57. ;   <ヘッダ> <データフィールド>
  58. ;   <ヘッダ> <位置指定フィールド>
  59. ;
  60. ; ◎ヘッダの構造
  61. ;   ヘッダは1バイト形式と2バイト形式がある
  62. ;   11111111 ($ff)      データの終端
  63. ;   kkk lllll       1バイト形式ヘッダ
  64. ;       kkkは 000110のデータ種別フィールド(3ビット)
  65. ;       lllllは 132を表わす長さフィールド(5ビット)
  66. ;   111 kkkll  llllllll 2バイト形式ヘッダ
  67. ;       kkkは 000110のデータ種別フィールド(3ビット)
  68. ;       ll lllllll は 11024を表わす長さフィールド(10ビット)
  69. ;   ●データ種別フィールド(3ビット)
  70. ;   000 以下に非圧縮データが続く    <データフィールド>が続く
  71. ;   001 1データ連続          <データフィールド>が続く
  72. ;   010 2データ連続          <データフィールド>が続く
  73. ;   011 +1データ連続           <データフィールド>が続く
  74. ;   100 参照(上下左右方向標準)    <位置指定フィールド>が続く
  75. ;   101 参照(左右反転)        <位置指定フィールド>が続く
  76. ;   110 参照(上下反転)        <位置指定フィールド>が続く
  77. ;   111 特殊
  78. ;
  79. ; ◎データフィールド(nバイト)
  80. ;   種別 = 000        長さ指定分のデータが続く
  81. ;   種別 = 001        1バイトのデータが続く
  82. ;   種別 = 010        2バイトのデータが続く
  83. ;   種別 = 011        1バイトのデータが続く
  84. ;
  85. ;  ◎位置指定フィールド(16ビット)
  86. ;   xxxxxxxx xxxxxxxx   64kバイトの範囲内で、参照の位置指定を表わす
  87. ;
  88. ;
  89.  
  90. ;   segment program
  91. ;
  92. ;   VRAM圧縮形式データの展開
  93. ;   void    decode(char *data, void *vadrs)
  94. ;
  95. ;Entry:
  96. ;   [DE]:展開先のアドレス
  97. ;   [HL]:圧縮データの先頭アドレス
  98. ;
  99. ;Return:
  100. ;   [DE]:展開データの終端アドレス+1
  101. ;
  102.     public  decode
  103. decode
  104.     ld  a,e     ;VRAM書き込みアドレスを退避
  105.     ld  (decodeAdrs),a
  106.     ld  a,d
  107.     ld  (decodeAdrs+1),a
  108. ;
  109. decode1
  110.     ld  a,(hl)      ;ヘッダを取り出す
  111.     cp  %11111111   ;終了判定
  112.     ret z       ; Yes, データ終了
  113. ;
  114.     and %11100000   ;2バイト形式か?
  115.     cp  %11100000
  116.     jr  nz,decode2  ; No, 1バイト形式である
  117. ;   2バイト形式ヘッダの長さの取得
  118.     ld  a,(hl)      ;2バイト形式のデータ種別フィールドを取り出す
  119.     add a,a
  120.     add a,a
  121.     add a,a     ;上位3ビットにシフトする
  122.     and %11100000
  123.     push    af      ;データ種別フィールドの保存
  124.     ld  a,(hli)     ;長さの上位バイト(2ビット)を取り出す
  125.     and %00000011
  126.     ld  b,a
  127.     ld  a,(hli)     ;長さの下位バイト(8ビット)を取り出す
  128.     ld  c,a
  129.     inc bc      ;0で1を表わしているので補正
  130.     jr  decode3
  131. ;   1バイト形式ヘッダの長さの取得
  132. decode2
  133.     push    af      ;データ種別フィールドの保存
  134.     ld  a,(hli)
  135.     and %00011111   ;短形式の長さを設定(5ビット)
  136.     ld  c,a
  137.     ld  b,0
  138.     inc c       ;0で1を表わしているので補正
  139. ;
  140. decode3 inc b       ;指定回数のループの高速化のため、
  141.     inc c       ; あらかじめ[B],[C]をインクリメントしておく
  142.     pop af      ;データ種別フィールドの回復
  143.     bit 7,a     ;参照データか繰り返しデータかを区別する
  144.     jr  nz,decodeRef    ; 参照データである
  145. ;
  146.     cp  %00100000
  147.     jr  z,decodeRepeat  ;1データ連続の展開
  148.     cp  %01000000
  149.     jr  z,decodeRep2    ;2データ交互連続の展開
  150.     cp  %01100000
  151.     jr  z,decodeRepInc ;+1データ連続の展開
  152. ;   非圧縮データの展開
  153. decodeNormal
  154.     dec c
  155.     jr  nz,decodeNorm1
  156.     dec b
  157.     jp  z,decode1   ; データ展開終了
  158. decodeNorm1
  159.     ld  a,(hli)     ;データを読み出す
  160.     ld  (de),a      ;データを書き込む
  161.     inc de
  162.     jr  decodeNormal
  163.  
  164. ;   1データ連続の展開
  165. decodeRepeat
  166.     ld  a,(hli)     ;展開するデータを[A]に読み出す
  167. decodeRep1
  168.     dec c
  169.     jr  nz,decodeRep10
  170.     dec b
  171.     jp  z,decode1   ; データ展開終了
  172. decodeRep10
  173.     ld  (de),a      ;連続データを書き込む
  174.     inc de
  175.     jr  decodeRep1
  176.  
  177. ;   2データ交互連続の展開
  178. decodeRep2
  179.     dec c
  180.     jr  nz,decodeRep20
  181.     dec b
  182.     jp  z,decRep2End    ; データ展開終了
  183. decodeRep20
  184.     ld  a,(hli)     ;連続データを書き込む
  185.     ld  (de),a
  186.     inc de
  187.     ld  a,(hld)
  188.     ld  (de),a
  189.     inc de
  190.     jr  decodeRep2
  191. ;
  192. decRep2End
  193.     inc hl
  194.     inc hl
  195.     jr  decode1
  196.  
  197. ;   +1データ連続の展開
  198. decodeRepInc
  199.     ld  a,(hli)     ;展開するデータを[A]に読み出す
  200. decodeInc1
  201.     dec c
  202.     jr  nz,decodeInc10
  203.     dec b
  204.     jp  z,decode1   ; データ展開終了
  205. decodeInc10
  206.     ld  (de),a
  207.     inc de
  208.     inc a
  209.     jr  decodeInc1
  210.  
  211.  
  212. ;   参照データの展開
  213. decodeRef
  214.     push    hl      ;データアドレスの退避
  215.     push    af      ;データ種別フィールドを再度退避
  216.     ld  a,(hli)     ;参照アドレスを読み出す
  217.     ld  l,(hl)
  218.     ld  h,a
  219.     ld  a,(decodeAdrs)  ;(decodeAdrs)を加えてデータ参照アドレスを算出
  220.     add a,l
  221.     ld  l,a
  222.     ld  a,(decodeAdrs+1)
  223.     adc a,h
  224.     ld  h,a
  225. ;
  226.     pop af      ;データ種別フィールドを回復
  227. ;
  228.     cp  %10000000
  229.     jr  z,refNormal ;通常参照展開
  230.     cp  %10100000
  231.     jr  z,refLR     ;左右反転参照展開
  232.     cp  %11000000
  233.     jr  z,refUD     ;上下反転参照展開
  234.  
  235.  
  236. ;   データ参照
  237. refNormal
  238.     dec c
  239.     jr  nz,refNorm1
  240.     dec b
  241.     jr  z,refEnd    ; データ展開終了
  242. refNorm1
  243.     ld  a,(hli)     ;参照データを読み出す
  244.     ld  (de),a      ;データを書き込む
  245.     inc de
  246.     jr  refNormal
  247.  
  248. ;   左右反転データ参照
  249. refLR
  250.     dec c
  251.     jr  nz,refLR1
  252.     dec b
  253.     jp  z,refEnd    ; データ展開終了
  254. refLR1
  255.     ld  a,(hli)     ;参照データを読み出す
  256.     ife 1
  257.     push    hl      ;テーブルを利用した高速左右反転
  258.     ld  h,>lrchgdat
  259.     ld  l,a
  260.     ld  a,(hl)
  261.     pop hl
  262.     endif
  263.  
  264.     ife 0
  265.     push    bc      ;[BC](カウンタ)の退避
  266.     ld  bc,8        ;データの左右反転
  267. refLR2  rra
  268.     rl  b
  269.     dec c
  270.     jr  nz,refLR2
  271.     ld  a,b
  272.     pop bc      ;[BC](カウンタ)の回復
  273.     endif
  274.  
  275.     ld  (de),a      ;左右反転した参照データを書き込む
  276.     inc de
  277.     jr  refLR
  278.  
  279. ;   上下反転データ参照
  280. refUD
  281.     dec c
  282.     jr  nz,refUD1
  283.     dec b
  284.     jp  z,refEnd    ; データ展開終了
  285. refUD1
  286.     ld  a,(hld)     ;参照データを読み出す
  287.     ld  (de),a      ;データを書き込む
  288.     inc de      ;上下反転なので、データを逆順に展開
  289.     jr  refUD
  290.  
  291. ;   参照展開終了
  292. refEnd
  293.     pop hl      ;データアドレスの回復
  294.     inc hl      ;参照アドレスフィールドの2バイトをスキップ
  295.     inc hl
  296.     jp  decode1     ;次のデータを展開
  297.  
  298.  else
  299.  
  300. ;*************************************************************
  301. ;   DMG用 汎用VRAMデータデコードルーチン
  302. ;           *高速版!!
  303. ;       Created by S.Iwata on June, 1989
  304. ;    for ポケモン金銀バージョン on September, 1998
  305. ;       (C) 1989 HAL Laboratory,inc.
  306. ;*************************************************************
  307.  
  308. ;
  309. ;       DMG版 データ圧縮のデータフォーマット
  310. ;
  311. ;   <ヘッダ> <データフィールド>
  312. ;   <ヘッダ> <位置指定フィールド>
  313. ;
  314. ; ◎ヘッダの構造
  315. ;   ヘッダは1バイト形式と2バイト形式がある
  316. ;   11111111 ($ff)      データの終端
  317. ;   kkk lllll       1バイト形式ヘッダ
  318. ;       kkkは 000110のデータ種別フィールド(3ビット)
  319. ;       lllllは 132を表わす長さフィールド(5ビット)
  320. ;   111 kkkll  llllllll 2バイト形式ヘッダ
  321. ;       kkkは 000110のデータ種別フィールド(3ビット)
  322. ;       ll lllllll は 11024を表わす長さフィールド(10ビット)
  323. ;   ●データ種別フィールド(3ビット)
  324. ;   000 以下に非圧縮データが続く    <データフィールド>が続く
  325. ;   001 1データ連続          <データフィールド>が続く
  326. ;   010 2データ連続          <データフィールド>が続く
  327. ;   011 +1データ連続           <データフィールド>が続く
  328. ;   100 参照(上下左右方向標準)    <位置指定フィールド>が続く
  329. ;   101 参照(左右反転)        <位置指定フィールド>が続く
  330. ;   110 参照(上下反転)        <位置指定フィールド>が続く
  331. ;   111 特殊
  332. ;
  333. ; ◎データフィールド(nバイト)
  334. ;   種別 = 000        長さ指定分のデータが続く
  335. ;   種別 = 001        1バイトのデータが続く
  336. ;   種別 = 010        2バイトのデータが続く
  337. ;   種別 = 011        1バイトのデータが続く
  338. ;
  339. ;  ◎位置指定フィールド(16ビット)
  340. ;   xxxxxxxx xxxxxxxx   64kバイトの範囲内で、参照の位置指定を表わす
  341. ;
  342. ;
  343.  
  344. ;   segment program
  345. ;
  346. ;   VRAM圧縮形式データの展開
  347. ;   void    decode(char *data, void *vadrs)
  348. ;
  349. ;Entry:
  350. ;   [DE]:展開先のアドレス
  351. ;   [HL]:圧縮データの先頭アドレス
  352. ;
  353. ;Return:
  354. ;   [DE]:展開データの終端アドレス+1
  355. ;
  356.     public  decode
  357. decode
  358.     ld  a,e     ;VRAM書き込みアドレスを退避
  359.     ld  (decodeAdrs),a
  360.     ld  a,d
  361.     ld  (decodeAdrs+1),a
  362. decode1
  363.     ld  a,(hl)      ;ヘッダを取り出す
  364.     cp  %11111111   ;終了判定
  365.     ret z       ; Yes, データ終了
  366.  
  367.     and %11100000   ;2バイト形式か?
  368.     cp  %11100000
  369.     jr  nz,decode2  ; No, 1バイト形式である
  370.  
  371. ;   2バイト形式ヘッダの長さの取得
  372.  
  373.     ld  a,(hl)      ;2バイト形式のデータ種別フィールドを取り出す
  374.     add a,a
  375.     add a,a
  376.     add a,a     ;上位3ビットにシフトする
  377.     and %11100000
  378.     push    af      ;データ種別フィールドの保存
  379.     ld  a,(hli)     ;長さの上位バイト(2ビット)を取り出す
  380.     and %00000011
  381.     ld  b,a
  382.     ld  a,(hli)     ;長さの下位バイト(8ビット)を取り出す
  383.     ld  c,a
  384.     inc bc      ;0で1を表わしているので補正
  385.     jr  decode3
  386.  
  387. ;   1バイト形式ヘッダの長さの取得
  388.  
  389. decode2
  390.     push    af      ;データ種別フィールドの保存
  391.     ld  a,(hli)
  392.     and %00011111   ;短形式の長さを設定(5ビット)
  393.     ld  c,a
  394.     ld  b,0
  395.     inc c       ;0で1を表わしているので補正
  396.  
  397. decode3 inc b       ;指定回数のループの高速化のため、
  398.     inc c       ; あらかじめ[B],[C]をインクリメントしておく
  399.     pop af      ;データ種別フィールドの回復
  400.     bit 7,a     ;参照データか繰り返しデータかを区別する
  401.     jr  nz,decodeRef    ; 参照データである
  402.  
  403.     cp  %00100000
  404.     jr  z,decodeRepeat  ;1データ連続の展開
  405.     cp  %01000000
  406.     jr  z,decodeRep2    ;2データ交互連続の展開
  407.     cp  %01100000
  408.     jr  z,decodeRepInc ;+1データ連続の展開
  409.  
  410. ;   非圧縮データの展開
  411.  
  412. decodeNormal
  413.     dec c
  414.     jr  nz,decodeNorm1
  415.     dec b
  416.     jp  z,decode1   ; データ展開終了
  417. decodeNorm1
  418.     ld  a,(hli)     ;データを読み出す
  419.     ld  (de),a      ;データを書き込む
  420.     inc de
  421.     jr  decodeNormal
  422.  
  423. ;   1データ連続の展開
  424.  
  425. decodeRepeat
  426.     ld  a,(hli)     ;展開するデータを[A]に読み出す
  427. decodeRep1
  428.     dec c
  429.     jr  nz,decodeRep10
  430.     dec b
  431.     jp  z,decode1   ; データ展開終了
  432. decodeRep10
  433.     ld  (de),a      ;連続データを書き込む
  434.     inc de
  435.     jr  decodeRep1
  436.  
  437. ;   2データ交互連続の展開
  438.  
  439. decodeRep2
  440.     dec c
  441.     jr  nz,decodeRep20
  442.     dec b
  443.     jp  z,decRep2End    ; データ展開終了
  444. decodeRep20
  445.     ld  a,(hli)     ;連続データを書き込む
  446.     ld  (de),a
  447.     inc de
  448.     dec c       ;ポケモン金銀モードでは奇数個のデータも許す
  449.     jr  nz,decodeRep21
  450.     dec b
  451.     jp  z,decRep2End1   ; データ展開終了
  452. decodeRep21
  453.     ld  a,(hld)
  454.     ld  (de),a
  455.     inc de
  456.     jr  decodeRep2
  457. ;
  458. decRep2End
  459.     inc hl
  460. decRep2End1
  461.     inc hl
  462.     jr  decode1
  463.  
  464. ;   +1データ連続の展開
  465.  
  466.     public  decodeRepInc
  467. decodeRepInc
  468.     xor a       ;ポケモン金銀モードでは0の連続
  469. ;;  ld  a,(hli)     ;展開するデータを[A]に読み出す
  470. decodeInc1
  471.     dec c
  472.     jr  nz,decodeInc10
  473.     dec b
  474.     jp  z,decode1   ; データ展開終了
  475. decodeInc10
  476.     ld  (de),a
  477.     inc de
  478. ;   inc a
  479.     jr  decodeInc1
  480.  
  481.  
  482. ;   参照データの展開
  483.  
  484. decodeRef
  485.     push    hl      ;データアドレスの退避
  486.     push    af      ;データ種別フィールドを再度退避
  487.     ld  a,(hli)     ;参照アドレスを読み出す
  488.     bit 7,a     ;ポケモン金銀モードでは最上位ビットの立っている場合
  489.     jr  z,decodeRef1
  490.     and $7f     ; -128 までの現在位置からのオフセットを意味する
  491.     cpl
  492.     add a,e
  493.     ld  l,a
  494.     ld  a,$ff
  495.     adc a,d
  496.     ld  h,a
  497.     jr  decodeRef2
  498. decodeRef1
  499.     ld  l,(hl)
  500.     ld  h,a
  501.     ld  a,(decodeAdrs)  ;(decodeAdrs)を加えてデータ参照アドレスを算出
  502.     add a,l
  503.     ld  l,a
  504.     ld  a,(decodeAdrs+1)
  505.     adc a,h
  506.     ld  h,a
  507.  
  508. decodeRef2
  509.     pop af      ;データ種別フィールドを回復
  510.  
  511.     cp  %10000000
  512.     jr  z,refNormal ;通常参照展開
  513.     cp  %10100000
  514.     jr  z,refLR     ;左右反転参照展開
  515.     cp  %11000000
  516.     jr  z,refUD     ;上下反転参照展開
  517.  
  518.  
  519. ;   データ参照
  520.  
  521. refNormal
  522.     dec c
  523.     jr  nz,refNorm1
  524.     dec b
  525.     jr  z,refEnd    ; データ展開終了
  526. refNorm1
  527.     ld  a,(hli)     ;参照データを読み出す
  528.     ld  (de),a      ;データを書き込む
  529.     inc de
  530.     jr  refNormal
  531.  
  532. ;   左右反転データ参照
  533.  
  534. refLR
  535.     dec c
  536.     jr  nz,refLR1
  537.     dec b
  538.     jp  z,refEnd    ; データ展開終了
  539. refLR1
  540.     ld  a,(hli)     ;参照データを読み出す
  541.  
  542.  ifn    0
  543.     push    hl      ;テーブルを利用した高速左右反転
  544.     ld  h,>lrchgdat
  545.     ld  l,a
  546.     ld  a,(hl)
  547.     pop hl
  548.  else
  549.     push    bc      ;[BC](カウンタ)の退避
  550.     ld  bc,8        ;データの左右反転
  551. refLR2  rra
  552.     rl  b
  553.     dec c
  554.     jr  nz,refLR2
  555.     ld  a,b
  556.     pop bc      ;[BC](カウンタ)の回復
  557.  endif
  558.  
  559.     ld  (de),a      ;左右反転した参照データを書き込む
  560.     inc de
  561.     jr  refLR
  562.  
  563. ;   上下反転データ参照
  564.  
  565. refUD
  566.     dec c
  567.     jr  nz,refUD1
  568.     dec b
  569.     jp  z,refEnd    ; データ展開終了
  570. refUD1
  571.     ld  a,(hld)     ;参照データを読み出す
  572.     ld  (de),a      ;データを書き込む
  573.     inc de      ;上下反転なので、データを逆順に展開
  574.     jr  refUD
  575.  
  576. ;   参照展開終了
  577.  
  578. refEnd
  579.     pop hl      ;データアドレスの回復
  580.     bit 7,(hl)      ;ポケモン金銀モードでは1バイトオフセットもある
  581.     jr  nz, refEnd1 ; 1バイトオフセット
  582.     inc hl      ;参照アドレスフィールドの2バイトをスキップ
  583. refEnd1
  584.     inc hl
  585.     jp  decode1     ;次のデータを展開
  586.  endif
  587.  
  588.  
  589.  
  590.  
  591.  
  592. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VPACKSUB.C ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  593.  
  594.  
  595. vpacksub.c                                                     TEXTdosa  @      5    イ,kxイ$M>                             /*
  596.  *  データ圧縮ユーティリティー
  597.  *      Written by S.Iwata
  598.  *          on April,1989
  599.  *      revised by M.Kanai
  600.  *          on Aug., 1989
  601.  *      revised by T.Gunji
  602.  *          on May., 1994
  603.  *      revised by S.Iwata
  604.  *          on September, 1996
  605.  *      revised by S.Iwata
  606.  *          on September, 1998
  607.  *
  608.  */
  609. #include  <stdio.h>
  610. #include  <stdlib.h>
  611.  
  612. typedef unsigned char   BYTE;
  613. typedef unsigned int    WORD;
  614. typedef unsigned long   DWORD;
  615.  
  616. #define TRUE    1
  617. #define FALSE   0
  618. #define FILENAMELENGTH  64      /* ファイル名用バッファの大きさ */
  619. #define DATASIZELIMIT   65536       /* 扱えるデータの最大値 64KB */
  620. #define EMPTY   (WORD)DATASIZELIMIT /* ハッシュテーブル内で空きを示す */
  621. #define HASHTABLESIZE   131111      /* 素数 524287 512KB */
  622.                     /* (old-version 131111) */
  623.  
  624. BYTE    data[DATASIZELIMIT + 1];    /* 圧縮データバッファ */
  625. BYTE    algorythm[DATASIZELIMIT];   /* 圧縮アルゴリズム */
  626. WORD    compLength[DATASIZELIMIT];  /* 圧縮対象データ長 */
  627. WORD    reference[DATASIZELIMIT];   /* 参照インデックス */
  628. WORD    originalSize = 0;       /* 圧縮前のデータ長 */
  629. WORD    packedSize = 0;         /* 圧縮後のデータ長 */
  630. WORD    nrefHash[HASHTABLESIZE];
  631. WORD    vrefHash[HASHTABLESIZE];
  632.  
  633. BYTE    invertTable[256];       /* 左右反転用テーブル */
  634. #define Invert(n)   (invertTable[n]) /* 左右反転データを得る */
  635.  
  636.  
  637. #define NORMAL      (BYTE)0     /* 非圧縮通常データ */
  638. #define RUNLENGTH   (BYTE)1     /* 1データ連続 */
  639. #define RUNLENGTH2  (BYTE)2     /* 2データ交互連続 */
  640. #define INCRUNLEN   (BYTE)3     /* インクリメンタルデータ連続 */
  641. #define REFERENCE   (BYTE)4     /* 通常データ参照 */
  642. #define REFERLR     (BYTE)5     /* 左右反転データ参照 */
  643. #define REFERUD     (BYTE)6     /* 上下反転データ参照 */
  644. #define SPECIAL     (BYTE)7     /* 特殊データ */
  645. #define ENDMARK     (BYTE)0xff  /* データ終端 */
  646.  
  647. WORD    algoPacked[] = {1, 2, 3, 2, 3, 3, 3};
  648.                 /* 各アルゴリズムで圧縮した場合のバイト数 */
  649. WORD    algoPackedZ[] = {1, 2, 3, 1, 2, 2, 2};
  650.  
  651. WORD    longEnough = 64;
  652.  
  653. int op_quiet = TRUE;
  654. int op_percent = FALSE;
  655. int pockemonFlag = TRUE;    /* ポケモン金銀モード */
  656.                 /* 最大データサイズを32KBに制限して1ByteOffset使用 */
  657.                 /* インクリメンタルデータ連続を0の連続の表記に使用 */
  658.  
  659.  
  660.  
  661. /*
  662.  *  1バイトのデータを出力する
  663.  */
  664. void putByte(BYTE data, FILE *fpo)
  665. {
  666.   fputc(data, fpo);
  667.   packedSize++;
  668. }
  669.  
  670.  
  671.  
  672. /*
  673.  *  ビットパターンを左右反転するためのテーブルを用意する
  674.  */
  675. void makeInvertTable(void)
  676. {
  677.   int       i;
  678.   BYTE      d;
  679.  
  680.   for (i = 0; i < 256; ++i) {
  681.     d = 0;
  682.     if ( i & 0x01 ) d |= 0x80;
  683.     if ( i & 0x02 ) d |= 0x40;
  684.     if ( i & 0x04 ) d |= 0x20;
  685.     if ( i & 0x08 ) d |= 0x10;
  686.     if ( i & 0x10 ) d |= 0x08;
  687.     if ( i & 0x20 ) d |= 0x04;
  688.     if ( i & 0x40 ) d |= 0x02;
  689.     if ( i & 0x80 ) d |= 0x01;
  690.     invertTable[i] = d;
  691.   }
  692. }
  693.  
  694.  
  695.  
  696. /*
  697.  *  ハッシュテーブルを初期化する
  698.  */
  699. void initHashTable(void )
  700. {
  701.   WORD      i;
  702.  
  703.   for (i = 0; i < HASHTABLESIZE; ++i) {
  704.     nrefHash[i] = EMPTY;
  705.     vrefHash[i] = EMPTY;
  706.   }
  707. }
  708.  
  709.  
  710.  
  711. /*
  712.  *  ハッシュ関数
  713.  */
  714. WORD hashf(BYTE d0, BYTE d1, BYTE d2, BYTE d3)
  715. {
  716.   DWORD     x;
  717.  
  718.   x = (DWORD)d0 + ((DWORD)d1 << 8) + ((DWORD)d2 << 16) + ((DWORD)d3 << 24);
  719.   return (WORD)(x % (DWORD)HASHTABLESIZE);
  720. }
  721.  
  722.  
  723.  
  724. /*
  725.  *  オープンアドレッシングのハッシュテーブルから次々に値を返す
  726.  */
  727. WORD scanNHash(WORD h)
  728. {
  729.   static WORD   lastH = HASHTABLESIZE;
  730.   static WORD   y, d;
  731.   WORD      r;
  732.  
  733.   if (h != lastH) {
  734.     y = h;
  735.     d = 1;
  736.   }
  737.   r = nrefHash[y];
  738.   lastH = (r == EMPTY) ? HASHTABLESIZE : h;
  739.   d += 2;
  740.   if ((y += d) >= HASHTABLESIZE)
  741.     y -= HASHTABLESIZE;
  742.   return r;
  743. }
  744.  
  745.  
  746. WORD scanVHash(WORD h)
  747. {
  748.   static WORD   lastH = HASHTABLESIZE;
  749.   static WORD   y, d;
  750.   WORD      r;
  751.  
  752.   if (h != lastH) {
  753.     y = h;
  754.     d = 1;
  755.   }
  756.   r = vrefHash[y];
  757.   lastH = (r == EMPTY) ? HASHTABLESIZE : h;
  758.   d += 2;
  759.   if ((y += d) >= HASHTABLESIZE)
  760.     y -= HASHTABLESIZE;
  761.   return r;
  762. }
  763.  
  764.  
  765.  
  766. /*
  767.  *  ハッシュテーブルに登録する
  768.  */
  769. void registNHash(WORD x, WORD y)
  770. {
  771.   WORD      d = 1;
  772.  
  773.   while (nrefHash[y] != EMPTY) {
  774.     d += 2;
  775.     if ((y += d) >= HASHTABLESIZE)
  776.       y -= HASHTABLESIZE;
  777.   }
  778.   nrefHash[y] = x;
  779. }
  780.  
  781.  
  782. void registVHash(WORD x)
  783. {
  784.   WORD      y, d = 1;
  785.  
  786.   y = hashf(data[x], data[x-1], data[x-2], data[x-3]);
  787.   while (vrefHash[y] != EMPTY) {
  788.     d += 2;
  789.     if ((y += d) >= HASHTABLESIZE)
  790.       y -= HASHTABLESIZE;
  791.   }
  792.   vrefHash[y] = x;
  793. }
  794.  
  795.  
  796.  
  797. /*
  798.  *  連続性・参照などのチェック
  799.  */
  800. void checkData(void)
  801. {
  802.   unsigned int  i, j, k, l;
  803.   WORD      r;
  804.   BYTE      *p1, *p2, *p3, *p1a;
  805.   WORD      hn, hh              /*, hv*/;
  806.   int       cnt = 0;
  807.   int       skipFlag = 0;
  808.  
  809.   for ( i = 0 ; i < originalSize ; i++ ) {
  810.  
  811.     /* 同一データの連続性調査 */
  812.     for ( j = 1 ; i+j < originalSize ; j++ ) {
  813.       if ( data[i] != data[i+j] )
  814.     break;
  815.     }
  816.     algorythm[i] = RUNLENGTH;           /* 圧縮アルゴリズム */
  817.     compLength[i] = j;              /* 圧縮対象データ長 */
  818.  
  819.     if (pockemonFlag) { /* ポケモン金銀モードでは奇数の2データ連続を許す */
  820.       /* 2データの交互連続性調査 */
  821.       if (i+3 < originalSize && data[i] == data[i+2] && data[i+1] == data[i+3]) {
  822.     for (j = 2 ; i+j < originalSize-1 ; j += 2) {
  823.       if ( data[i] != data[i+j] || data[i+1] != data[i+j+1] )
  824.         break;
  825.     }
  826.     if (data[i] == data[i+j])   j++;
  827.       }
  828.       if ( compLength[i] < j ) {
  829.     algorythm[i] = RUNLENGTH2;      /* 圧縮アルゴリズム */
  830.     compLength[i] = j;          /* 圧縮対象データ長 */
  831.       }
  832.     } else {
  833.       /* 2データの交互連続性調査 */
  834.       for ( j = 2 ; i+j < originalSize-1 ; j += 2 ) {
  835.     if ( data[i] != data[i+j] || data[i+1] != data[i+j+1] )
  836.       break;
  837.       }
  838.       if ( compLength[i] < j ) {
  839.     algorythm[i] = RUNLENGTH2;      /* 圧縮アルゴリズム */
  840.     compLength[i] = j;          /* 圧縮対象データ長 */
  841.       }
  842.     }
  843.  
  844.     if (pockemonFlag) { /* ポケモン金銀モードではインクリメンタルデータ連続を0の連続に使用 */
  845.       /* 0の連続性調査 */
  846.       if (data[i] == 0) {
  847.     for ( j = 1 ; i+j < originalSize ; j++ ) {
  848.       if (data[i+j] != 0)   break;
  849.     }
  850.     algorythm[i] = INCRUNLEN;       /* 圧縮アルゴリズム */
  851.     compLength[i] = j;          /* 圧縮対象データ長 */
  852.       }
  853.     } else {
  854.       /* インクリメンタルデータの連続性調査 */
  855.       for ( j = 1 ; i+j < originalSize ; j++ ) {
  856.     if ( data[i+j-1] != data[i+j]-1 )
  857.       break;
  858.       }
  859.       if ( compLength[i] < j ) {
  860.     algorythm[i] = INCRUNLEN;           /* 圧縮アルゴリズム */
  861.     compLength[i] = j;          /* 圧縮対象データ長 */
  862.       }
  863.     }
  864.  
  865.     /* */
  866.     if (compLength[i] >= longEnough) {
  867.       i += (compLength[i] - 1);
  868.       if (!op_quiet && !op_percent)
  869.     fputc('L' ,stderr);
  870.       cnt++;
  871.       continue;
  872.     }
  873.  
  874.     /* 以前に出現したデータの参照の調査 */
  875.     l = 0;
  876.     hn = hashf(data[i], data[i+1], data[i+2], data[i+3]);
  877.     while ((j = scanNHash(hn)) != EMPTY) {
  878.       p1 = p1a = data + i;
  879.       p2 = data + j;
  880.       p3 = data + originalSize;
  881.       while ((*p1 == *p2) /*&& (p2 < p1a)*/ && (p1 < p3))
  882.     ++p1, ++p2;
  883.       if ((k = p1 - p1a) > l) {
  884.     l = k, r = j;       /* 今回スキャンしたデータの方が長い一致 */
  885.       } else if (k == l && j > r) {
  886.     l = k, r = j;       /* 同じ長さの一致なら近い方を優先 */
  887.       }
  888.     }
  889.     if (l >= 3 && compLength[i] < l) {
  890.       algorythm[i] = REFERENCE;         /* 圧縮アルゴリズム */
  891.       compLength[i] = l;            /* 圧縮対象データ長 */
  892.       reference[i] = r;             /* 参照位置 */
  893.     }
  894.  
  895.     /* 以前に出現したデータの左右反転の参照の調査 */
  896.     l = 0;
  897.     hh = hashf(Invert(data[i]), Invert(data[i+1]), Invert(data[i+2]), Invert(data[i+3]));
  898.     while ((j = scanNHash(hh)) != EMPTY) {
  899.       p1 = p1a = data + i;
  900.       p2 = data + j;
  901.       p3 = data + originalSize;
  902.       while ((*p1 == Invert(*p2)) /*&& (p2 < p1a)*/ && (p1 < p3))
  903.     ++p1, ++p2;
  904.       if ((k = p1 - p1a) > l) {
  905.     l = k, r = j;       /* 今回スキャンしたデータの方が長い一致 */
  906.       } else if (k == l && j > r) {
  907.     l = k, r = j;       /* 同じ長さの一致なら近い方を優先 */
  908.       }
  909.     }
  910.     if (l >= 3 && compLength[i] < l) {
  911.       algorythm[i] = REFERLR;           /* 圧縮アルゴリズム */
  912.       compLength[i] = l;            /* 圧縮対象データ長 */
  913.       reference[i] = r;             /* 参照位置 */
  914.     }
  915.  
  916.     /* 以前に出現したデータの上下反転の参照の調査 */
  917.     l = 0;
  918.     /*hv = hashf(data[i], data[i+1], data[i+2], data[i+3]); */
  919.     while ((j = scanVHash(hn)) != EMPTY) {
  920.       p1 = p1a = data + i;
  921.       p2 = data + j;
  922.       p3 = data + originalSize;
  923.       while ((*p1 == *p2) && (p2 >= data) && (p1 < p3))
  924.     ++p1, --p2;
  925.       if ((k = p1 - p1a) > l) {
  926.     l = k, r = j;       /* 今回スキャンしたデータの方が長い一致 */
  927.       } else if (k == l && j > r) {
  928.     l = k, r = j;       /* 同じ長さの一致なら近い方を優先 */
  929.       }
  930.     }
  931.     if (l >= 3 && compLength[i] < l) {
  932.       algorythm[i] = REFERUD;           /* 圧縮アルゴリズム */
  933.       compLength[i] = l;            /* 圧縮対象データ長 */
  934.       reference[i] = r;             /* 参照位置 */
  935.     }
  936.  
  937.     registNHash(i, hn);
  938.     registVHash(i);
  939.  
  940.     if (compLength[i] >= longEnough) {
  941.       i += (compLength[i] - 1);
  942.       if (!op_quiet && !op_percent)
  943.     fputc('L' ,stderr);
  944.       cnt++;
  945.       continue;
  946.     }
  947.  
  948.     if ((i & 0x03F) == 0x03F) {
  949.       if (!op_quiet && !op_percent)
  950.     fputc('*' ,stderr);
  951.       cnt++;
  952.     }
  953.  
  954.   }
  955.  
  956.   /*
  957.      if (!op_quiet)
  958.      for (i = 0; i < cnt; i++)
  959.      fputs("\b \b", stderr);
  960.     */
  961.  
  962.   /*
  963.     for (i = 0; i < originalSize ; i++)
  964.     printf("%04X: %d %d\n", i, algorythm[i], compLength[i]);
  965.     */
  966.  
  967. }
  968.  
  969.  
  970. /*
  971.  *  圧縮可能情報を順に調べて、圧縮した方が得かどうか調べる
  972.  */
  973. void judge(void)
  974. {
  975.   unsigned int  i,j;
  976.  
  977.   /* そのデータを圧縮データにしてもトータルで損になる場合は除外 */
  978.   for ( i = 0 ; i < originalSize ; i++ ) {
  979.     if ( algorythm[i] ) {
  980.       for ( j = 1 ; j < compLength[i] ; j++ ) {
  981.     if ( compLength[i+j] > compLength[i] ) {
  982.       compLength[i] = j;
  983.       if (algorythm[i] == RUNLENGTH2 && (j & 1))
  984.         compLength[i]--;
  985.     }
  986.       }
  987.     }
  988.   }
  989.  
  990.   /* 単純に圧縮してもデータが短くならない場合は圧縮対象から除外 */
  991.   if (pockemonFlag) {
  992.     for ( i = 0 ; i < originalSize ; i++ ) {
  993.       if (compLength[i] <= algoPackedZ[algorythm[i]]) {
  994.     algorythm[i] = NORMAL;
  995.     compLength[i] = 0;
  996.       }
  997.       if (algorythm[i] >= REFERENCE && i-reference[i] > 128) {
  998.     if ( compLength[i] <= algoPacked[algorythm[i]] ) {
  999.       algorythm[i] = NORMAL;
  1000.       compLength[i] = 0;
  1001.     }
  1002.       }
  1003.     }
  1004.   } else {
  1005.     for ( i = 0 ; i < originalSize ; i++ ) {
  1006.       if ( compLength[i] <= algoPacked[algorythm[i]] ) {
  1007.     algorythm[i] = NORMAL;
  1008.     compLength[i] = 0;
  1009.       }
  1010.     }
  1011.   }
  1012.  
  1013.   /* 非圧縮データの連続性をチェックする */
  1014.   for ( i = 0; i < originalSize ; ) {
  1015.     if ( algorythm[i] == NORMAL ) {
  1016.       for ( j = 1 ; i+j < originalSize ; j++ ) {
  1017.     if ( algorythm[i+j] != NORMAL ) break;
  1018.       }
  1019.       compLength[i] = j;
  1020.       i += j;
  1021.     } else {
  1022.       i += compLength[i];
  1023.     }
  1024.   }
  1025. }
  1026.  
  1027.  
  1028. /*
  1029.  *  圧縮形式のデータを実際に出力する
  1030.  */
  1031. void outData(FILE *fpo)
  1032. {
  1033.   unsigned int  i,j,k,len,loc;
  1034.  
  1035.   i = 0;
  1036.   while ( i < originalSize ) {
  1037.     len = compLength[i];
  1038.     if (!pockemonFlag) {
  1039.       if ( algorythm[i] == RUNLENGTH2 )
  1040.     len /= 2;
  1041.     }
  1042.     loc = i;
  1043.     do {
  1044.       j = (len > 1024) ? 1024 : len;
  1045.       if ( j > 32 ) {
  1046.     /* 圧縮長33以上 */
  1047.     putByte((BYTE)(0xe0+(algorythm[i]<<2)+((j-1)>>8)), fpo);
  1048.     putByte((BYTE)((j-1)&255), fpo);
  1049.       } else {
  1050.     /* 圧縮長1~32 */
  1051.     putByte((BYTE)((algorythm[i]<<5) + j-1), fpo);
  1052.       }
  1053.       switch ( algorythm[i] ) {
  1054.       case NORMAL:
  1055.     for ( k = 0; k < j; k++ )
  1056.       putByte(data[loc+k], fpo);
  1057.     loc += j;
  1058.     break;
  1059.       case RUNLENGTH:
  1060.     putByte(data[i], fpo);
  1061.     break;
  1062.       case INCRUNLEN:
  1063.     if (!pockemonFlag) {
  1064.       putByte(data[i], fpo);
  1065.     }
  1066.     break;
  1067.       case RUNLENGTH2:
  1068.     putByte(data[i], fpo);
  1069.     putByte(data[i+1], fpo);
  1070.     break;
  1071.       case REFERENCE:
  1072.       case REFERLR:
  1073.     if (pockemonFlag) {
  1074.       if (i - reference[i] <= 128) {
  1075.         putByte((BYTE)((i-reference[i]-1)|0x80), fpo);
  1076.       } else {
  1077.         putByte((BYTE)(reference[i]>>8), fpo);
  1078.         putByte((BYTE)(reference[i]&0xff), fpo);
  1079.       }
  1080.     } else {
  1081.       putByte((BYTE)(reference[i]>>8), fpo);
  1082.       putByte((BYTE)(reference[i]&0xff), fpo);
  1083.     }
  1084.     /*reference[i] += j;???*/
  1085.     break;
  1086.       case REFERUD:
  1087.     if (pockemonFlag) {
  1088.       if (i - reference[i] <= 128) {
  1089.         putByte((BYTE)((i-reference[i]-1)|0x80), fpo);
  1090.       } else {
  1091.         putByte((BYTE)(reference[i]>>8), fpo);
  1092.         putByte((BYTE)(reference[i]&0xff), fpo);
  1093.       }
  1094.     } else {
  1095.       putByte((BYTE)(reference[i]>>8), fpo);
  1096.       putByte((BYTE)(reference[i]&0xff), fpo);
  1097.     }
  1098.     /*reference[i] -= j;???*/
  1099.     break;
  1100.       }
  1101.       len -= j;
  1102.     } while ( len );
  1103.     i += compLength[i];
  1104.   }
  1105.   putByte(ENDMARK, fpo);                /* エンドマークを書き出す */
  1106. }
  1107.  
  1108.  
  1109. int vpack(FILE *fpi, FILE *fpo)
  1110. {
  1111.   packedSize = 0;
  1112.   /* 圧縮処理に必要な初期設定 */
  1113.   makeInvertTable();
  1114.   initHashTable();
  1115.  
  1116.   /* バッファにデータを読み出す */
  1117.   originalSize = fread(data, 1, DATASIZELIMIT + 1, fpi);
  1118.   if (originalSize > DATASIZELIMIT) {
  1119.     exit(1);
  1120.   }
  1121.  
  1122.   /* データの連続性・参照などのチェック */
  1123.   if (!op_quiet && !op_percent)
  1124.     fprintf(stderr, "データ解析.......");
  1125.   checkData();
  1126.   if (!op_quiet && !op_percent)
  1127.     fprintf(stderr, "...終了\n");
  1128.  
  1129.   /* 実際に圧縮するかどうか調べる */
  1130.   if (!op_quiet && !op_percent)
  1131.     fprintf(stderr, "圧縮効果解析.....");
  1132.   judge();
  1133.   if (!op_quiet && !op_percent)
  1134.     fprintf(stderr, "終了\n");
  1135.  
  1136.   /* 圧縮形式でデータを出力する */
  1137.   if (!op_quiet && !op_percent)
  1138.     fprintf(stderr, "圧縮データ出力...");
  1139.   outData(fpo);
  1140.   if (!op_quiet && !op_percent)
  1141.     fprintf(stderr, "終了     \n");
  1142.  
  1143.   if (!op_quiet)
  1144.     fprintf(stderr,
  1145.         "    %u Byteから %u Byte( %d%% )に圧縮されました。差分は %u Byteです。\n", originalSize, packedSize, (int)((DWORD)packedSize*100/(DWORD)originalSize), originalSize-packedSize);
  1146.   return packedSize;
  1147. }
  1148.                                                                                                          
  1149.  
  1150. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MONSPACK.C ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1151.  
  1152.  
  1153. monspack.c                                                     TEXTdosa         +     イ+ナzイ+ナp                             /*
  1154.  *  ポケモングラフィックデータの圧縮・バンク詰めコンバータ
  1155.  *      Created by S.Iwata / HAL Laboragtory, Inc.
  1156.  */
  1157. #include  <stdio.h>
  1158. #include  <stdlib.h>
  1159.  
  1160. typedef unsigned char   BYTE;
  1161. typedef unsigned int    WORD;
  1162. typedef unsigned long   DWORD;
  1163.  
  1164.  
  1165. /* ファイルに1バイト出力 */
  1166. void putByte(BYTE, FILE*);
  1167. /* ファイルfpiの内容を圧縮してfpoに出力し圧縮後のサイズを返す */
  1168. int vpack(FILE *fpi, FILE *fpo);
  1169. /* 圧縮用データバッファ(データ出力に使用) */
  1170. extern BYTE data[];
  1171.  
  1172. /* データ種別定義 */
  1173. typedef enum {
  1174.   MonsFront = 0,    /* モンスター正面 */
  1175.   MonsBack,     /* モンスター背面 */
  1176.   UnknownFront,     /* アンノーン正面 */
  1177.   UnknownBack,      /* アンノーン背面 */
  1178.   Trainer       /* トレーナー */
  1179. } DKind;
  1180.  
  1181. /* データ断片 */
  1182. typedef struct {
  1183.   DKind kind;       /* データ種別 */
  1184.   int   idno;       /* データID(モンスター番号) */
  1185.   int   bank;       /* バンク番号 */
  1186.   long  bpoint;     /* バンク内のポインタ */
  1187.   int   size;       /* この情報のサイズ */
  1188. } BLOCKREC;
  1189.  
  1190. int comparec(const void*s1, const void *s2)
  1191. {
  1192.   return( ((BLOCKREC*)s2)->size - ((BLOCKREC*)s1)->size );
  1193. }
  1194.  
  1195. BLOCKREC blockrec[1000];    /* ナップザックに格納するデータ断片 */
  1196. long    knaps[256];     /* ナップザックに格納されているデータサイズ */
  1197.  
  1198.  
  1199.  
  1200.  
  1201.  
  1202.  
  1203. /*
  1204.  *  ナップザック問題を解く
  1205.  */
  1206. void PutIntoKnap(int blocknum, int minbank, int maxbank, int banksize)
  1207. {
  1208.   BLOCKREC  *thing;
  1209.   int   i;
  1210.   long  k;
  1211.  
  1212.   for (k = 0; k < blocknum; k++) {
  1213.     thing = &blockrec[k];
  1214.     for(i = minbank; i <= maxbank; i++) {
  1215.       if (banksize >= knaps[i] + thing->size) {
  1216.     thing->bank = i;
  1217.     thing->bpoint = knaps[i];
  1218.     knaps[i] += thing->size;
  1219.     goto next;      /* put */
  1220.       }
  1221.     }
  1222.     fprintf(stderr , "knapsack: is full\n");
  1223.     exit(1);  
  1224.   next:;
  1225.   }
  1226. }
  1227.  
  1228.  
  1229.  
  1230.  
  1231.  
  1232.  
  1233. #define NumMons     (251)   /* ポケモンの数 */
  1234. #define MonsUnkown  (201)   /* アンノーンのモンスター番号(欠番) */
  1235. #define NumUnknown  (26)    /* アンノーンの数 */
  1236. #define NumTrainer  (66)    /* トレーナーの数 */
  1237.  
  1238. #define MinBank     (0x12)  /* 先頭バンク番号 */
  1239. #define MaxBank     (0x20)  /* 最終バンク番号 */
  1240. #define BankSize    (0x4000)/* バンクサイズ */
  1241. #define BankOffset  (0x4000)/* バンクの先頭アドレス */
  1242.  
  1243. BYTE MonsFrontBank[NumMons];          /* モンスター正面のバンク */
  1244. WORD MonsFrontAdrs[NumMons];          /* モンスター正面のアドレス */
  1245. BYTE MonsBackBank[NumMons];       /* モンスター背面のバンク */
  1246. WORD MonsBackAdrs[NumMons];       /* モンスター背面のアドレス */
  1247. BYTE UnknownFrontBank[NumUnknown];    /* アンノーン正面のバンク */
  1248. WORD UnknownFrontAdrs[NumUnknown];    /* アンノーン正面のアドレス */
  1249. BYTE UnknownBackBank[NumUnknown];     /* アンノーン背面のバンク */
  1250. WORD UnknownBackAdrs[NumUnknown];     /* アンノーン背面のアドレス */
  1251. BYTE TrainerBank[NumTrainer];         /* トレイナーのバンク */
  1252. WORD TrainerAdrs[NumTrainer];         /* トレイナーのアドレス */
  1253.  
  1254. void main(int argc, char **argv)
  1255. {
  1256.   int i, j;
  1257.   char infile[256];
  1258.   char outfile[256];
  1259.   FILE *fpi;
  1260.   FILE *fpo;
  1261.   int blockNum = 0;
  1262.   int offset;
  1263.  
  1264.   if (argc != 4) {
  1265.     fprintf(stderr, "monspack k|s datadir packdir");
  1266.     exit(1);
  1267.   }
  1268.  
  1269.   /* ポケモンキャラクタファイル群を圧縮 */
  1270.   for (i = 1; i <= NumMons; i++) {
  1271.     if (i == MonsUnkown)    continue;   /* アンノーンはスキップ */
  1272.     /* 正面グラフィック */
  1273.     sprintf(infile, "%s\\pm%sf_%03d.tmp", argv[2], argv[1], i);
  1274.     sprintf(outfile, "%s\\pm%sf_%03d.bin", argv[3], argv[1], i);
  1275.     fprintf(stderr, "File: %s\n", infile);
  1276.     fpi = fopen(infile, "rb");
  1277.     if (fpi != NULL) {
  1278.       fpo = fopen(outfile, "wb");
  1279.       blockrec[blockNum].kind = MonsFront;
  1280.       blockrec[blockNum].idno = i;
  1281.       blockrec[blockNum++].size = vpack(fpi, fpo);
  1282.       fclose(fpi);
  1283.       fclose(fpo);
  1284.     } else {
  1285.       fprintf(stderr, "%s not found\n", infile);
  1286.     }
  1287.     /* 背面グラフィック */
  1288.     sprintf(infile, "%s\\pm%sb_%03d.tmp", argv[2], argv[1], i);
  1289.     sprintf(outfile, "%s\\pm%sb_%03d.bin", argv[3], argv[1], i);
  1290.     fprintf(stderr, "File: %s\n", infile);
  1291.     fpi = fopen(infile, "rb");
  1292.     if (fpi != NULL) {
  1293.       fpo = fopen(outfile, "wb");
  1294.       blockrec[blockNum].kind = MonsBack;
  1295.       blockrec[blockNum].idno = i;
  1296.       blockrec[blockNum++].size = vpack(fpi, fpo);
  1297.       fclose(fpi);
  1298.       fclose(fpo);
  1299.     } else {
  1300.       fprintf(stderr, "%s not found\n", infile);
  1301.     }
  1302.   }
  1303.   /* アンノーンポケモンデータの圧縮 */
  1304.   for (i = 0; i < NumUnknown; i++) {
  1305.     /* 正面グラフィック */
  1306.     sprintf(infile, "%s\\pm%sf_un%c.tmp", argv[2], argv[1], i+'a');
  1307.     sprintf(outfile, "%s\\pm%sf_un%c.bin", argv[3], argv[1], i+'a');
  1308.     fprintf(stderr, "File: %s\n", infile);
  1309.     fpi = fopen(infile, "rb");
  1310.     if (fpi != NULL) {
  1311.       fpo = fopen(outfile, "wb");
  1312.       blockrec[blockNum].kind = UnknownFront;
  1313.       blockrec[blockNum].idno = i;
  1314.       blockrec[blockNum++].size = vpack(fpi, fpo);
  1315.       fclose(fpi);
  1316.       fclose(fpo);
  1317.     } else {
  1318.       fprintf(stderr, "%s not found\n", infile);
  1319.     }
  1320.     /* 背面グラフィック */
  1321.     sprintf(infile, "%s\\pm%sb_un%c.tmp", argv[2], argv[1], i+'a');
  1322.     sprintf(outfile, "%s\\pm%sb_un%c.bin", argv[3], argv[1], i+'a');
  1323.     fprintf(stderr, "File: %s\n", infile);
  1324.     fpi = fopen(infile, "rb");
  1325.     if (fpi != NULL) {
  1326.       fpo = fopen(outfile, "wb");
  1327.       blockrec[blockNum].kind = UnknownBack;
  1328.       blockrec[blockNum].idno = i;
  1329.       blockrec[blockNum++].size = vpack(fpi, fpo);
  1330.       fclose(fpi);
  1331.       fclose(fpo);
  1332.     } else {
  1333.       fprintf(stderr, "%s not found\n", infile);
  1334.     }
  1335.   }
  1336.   /* トレーナーファイル群を圧縮 */
  1337.   for (i = 1; i <= NumTrainer; i++) {
  1338.     sprintf(infile, "%s\\p%sdl_%03d.tmp", argv[2], argv[1], i);
  1339.     sprintf(outfile, "%s\\p%sdl_%03d.bin", argv[3], argv[1], i);
  1340.     fprintf(stderr, "File: %s\n", infile);
  1341.     fpi = fopen(infile, "rb");
  1342.     if (fpi != NULL) {
  1343.       fpo = fopen(outfile, "wb");
  1344.       blockrec[blockNum].kind = Trainer;
  1345.       blockrec[blockNum].idno = i;
  1346.       blockrec[blockNum++].size = vpack(fpi, fpo);
  1347.       fclose(fpi);
  1348.       fclose(fpo);
  1349.     } else {
  1350.       fprintf(stderr, "%s not found\n", infile);
  1351.     }
  1352.   }
  1353.  
  1354.   fprintf(stderr, "Total %d files\n", blockNum);
  1355.  
  1356.   /* ナップザック問題を解く準備 */
  1357.   qsort((void*)blockrec, (size_t)blockNum, sizeof(BLOCKREC), comparec);
  1358.   for(i = MinBank; i <= MaxBank; i++)   knaps[i] = 0;
  1359.   knaps[MinBank] = (NumMons)*6;  /* バンク12にはモンスター251体分のポインタ */
  1360.   knaps[MinBank+1] = (NumUnknown)*6;  /* バンク13にはアンノーン26体分のポインタ */
  1361.   knaps[MinBank+2] = (NumTrainer)*3;  /* バンク14にはトレーナー66体分のポインタ */
  1362.   /* ナップザック問題を解く */
  1363.   PutIntoKnap(blockNum, MinBank, MaxBank, BankSize);
  1364.  
  1365.   /* バンクの使用量表示 */
  1366.   for (i = MinBank; i <= MaxBank; i++) {
  1367.     fprintf(stderr, "Bank:%02X  Size:%04X\n", i, knaps[i]);
  1368.   }
  1369.  
  1370.   /* バンクファイルの出力準備 */
  1371.   for (i = 0; i < NumMons; i++) {
  1372.     MonsFrontBank[i] = 0xff;
  1373.     MonsFrontAdrs[i] = 0xffff;
  1374.     MonsBackBank[i] = 0xff;
  1375.     MonsBackAdrs[i] = 0xffff;
  1376.   }
  1377.   for (i = 0; i < NumUnknown; i++) {
  1378.     UnknownFrontBank[i] = 0xff;
  1379.     UnknownFrontAdrs[i] = 0xffff;
  1380.     UnknownBackBank[i] = 0xff;
  1381.     UnknownBackAdrs[i] = 0xffff;
  1382.   }
  1383.   for (i = 0; i < NumTrainer; i++) {
  1384.     TrainerBank[i] = 0xff;
  1385.     TrainerAdrs[i] = 0xffff;
  1386.   }
  1387.   /* 詰め込まれたデータを確認してポインタテーブルをつくる */
  1388.   for (i = 0; i < blockNum; i++) {
  1389.     switch(blockrec[i].kind) {
  1390.     case MonsFront:
  1391.       if (blockrec[i].idno < 1 || blockrec[i].idno > NumMons) {
  1392.     fprintf(stderr, "Illegal monster no\n");
  1393.     exit(1);
  1394.       }
  1395.       MonsFrontBank[blockrec[i].idno-1] = blockrec[i].bank;
  1396.       MonsFrontAdrs[blockrec[i].idno-1] = blockrec[i].bpoint+BankOffset;
  1397.       break;
  1398.     case MonsBack:
  1399.       if (blockrec[i].idno < 1 || blockrec[i].idno > NumMons) {
  1400.     fprintf(stderr, "Illegal monster no\n");
  1401.     exit(1);
  1402.       }
  1403.       MonsBackBank[blockrec[i].idno-1] = blockrec[i].bank;
  1404.       MonsBackAdrs[blockrec[i].idno-1] = blockrec[i].bpoint+BankOffset;
  1405.       break;
  1406.     case UnknownFront:
  1407.       if (blockrec[i].idno < 0 || blockrec[i].idno >= NumUnknown) {
  1408.     fprintf(stderr, "Illegal monster no\n");
  1409.     exit(1);
  1410.       }
  1411.       UnknownFrontBank[blockrec[i].idno] = blockrec[i].bank;
  1412.       UnknownFrontAdrs[blockrec[i].idno] = blockrec[i].bpoint+BankOffset;
  1413.       break;
  1414.     case UnknownBack:
  1415.       if (blockrec[i].idno < 0 || blockrec[i].idno >= NumUnknown) {
  1416.     fprintf(stderr, "Illegal monster no\n");
  1417.     exit(1);
  1418.       }
  1419.       UnknownBackBank[blockrec[i].idno] = blockrec[i].bank;
  1420.       UnknownBackAdrs[blockrec[i].idno] = blockrec[i].bpoint+BankOffset;
  1421.       break;
  1422.     case Trainer:
  1423.       if (blockrec[i].idno < 1 || blockrec[i].idno > NumTrainer) {
  1424.     fprintf(stderr, "Illegal monster no\n");
  1425.     exit(1);
  1426.       }
  1427.       TrainerBank[blockrec[i].idno-1] = blockrec[i].bank;
  1428.       TrainerAdrs[blockrec[i].idno-1] = blockrec[i].bpoint+BankOffset;
  1429.       break;
  1430.     default:
  1431.       fprintf(stderr, "Illegal Data\n");
  1432.       exit(1);
  1433.       break;
  1434.     }
  1435.   }
  1436.  
  1437.   for (i = MinBank; i <= MaxBank; i++) {
  1438.     offset = 0;
  1439.     sprintf(outfile, "bank%02x.bin", i);
  1440.     fpo = fopen(outfile, "wb");
  1441.     /* バンク先頭にアドレステーブルを出力する必要あり? */
  1442.     switch(i) {
  1443.     case MinBank: /* バンク12の先頭にモンスターデータテーブル */
  1444.       for (j = 0; j < NumMons; j++) {
  1445.     putByte(MonsFrontBank[j], fpo);
  1446.     putByte((BYTE)(MonsFrontAdrs[j]&0xff), fpo);
  1447.     putByte((BYTE)(MonsFrontAdrs[j]>>8), fpo);
  1448.     putByte(MonsBackBank[j], fpo);
  1449.     putByte((BYTE)(MonsBackAdrs[j]&0xff), fpo);
  1450.     putByte((BYTE)(MonsBackAdrs[j]>>8), fpo);
  1451.       }
  1452.       offset += NumMons*6;
  1453.       break;
  1454.     case MinBank+1: /* バンク13の先頭にアンノーンデータテーブル */
  1455.       for (j = 0; j < NumUnknown; j++) {
  1456.     putByte(UnknownFrontBank[j], fpo);
  1457.     putByte((BYTE)(UnknownFrontAdrs[j]&0xff), fpo);
  1458.     putByte((BYTE)(UnknownFrontAdrs[j]>>8), fpo);
  1459.     putByte(UnknownBackBank[j], fpo);
  1460.     putByte((BYTE)(UnknownBackAdrs[j]&0xff), fpo);
  1461.     putByte((BYTE)(UnknownBackAdrs[j]>>8), fpo);
  1462.       }
  1463.       offset += NumUnknown*6;
  1464.       break;
  1465.     case MinBank+2: /* バンク14の先頭にトレイナーデータテーブル */
  1466.       for (j = 0; j < NumTrainer; j++) {
  1467.     putByte(TrainerBank[j], fpo);
  1468.     putByte((BYTE)(TrainerAdrs[j]&0xff), fpo);
  1469.     putByte((BYTE)(TrainerAdrs[j]>>8), fpo);
  1470.       }
  1471.       offset += NumTrainer*3;
  1472.       break;
  1473.     }
  1474.     /* このバンクに詰め込まれたデータを次々出力 */
  1475.     for (j = 0; j < blockNum; j++) {
  1476.       if (blockrec[j].bank != i)    continue;
  1477.       if (blockrec[j].bpoint != offset) {
  1478.     fprintf(stderr, "Illegal Offset\n");
  1479.     exit(1);
  1480.       }
  1481.       offset += blockrec[j].size;
  1482.       switch(blockrec[j].kind) {
  1483.       case MonsFront:
  1484.     sprintf(infile, "%s\\pm%sf_%03d.bin", argv[3], argv[1], blockrec[j].idno);
  1485.     break;
  1486.       case MonsBack:
  1487.     sprintf(infile, "%s\\pm%sb_%03d.bin", argv[3], argv[1], blockrec[j].idno);
  1488.     break;
  1489.       case UnknownFront:
  1490.     sprintf(infile, "%s\\pm%sf_un%c.bin", argv[3], argv[1], blockrec[j].idno+'a');
  1491.     break;
  1492.       case UnknownBack:
  1493.     sprintf(infile, "%s\\pm%sb_un%c.bin", argv[3], argv[1], blockrec[j].idno+'a');
  1494.     break;
  1495.       case Trainer:
  1496.     sprintf(infile, "%s\\p%sdl_%03d.bin", argv[3], argv[1], blockrec[j].idno);
  1497.     break;
  1498.       }
  1499.       fpi = fopen(infile, "rb");
  1500.       fread(data, 1, blockrec[j].size, fpi);
  1501.       fwrite(data, 1, blockrec[j].size, fpo);
  1502.       fclose(fpi);
  1503.     }
  1504.     fclose(fpo);
  1505.   }
  1506.  
  1507. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement