home *** CD-ROM | disk | FTP | other *** search
/ hobbes.nmsu.edu 2008 / 2008-06-02_hobbes.nmsu.edu.zip / new / scummc-0.2.0-os2.zip / ScummC / src / write.c < prev    next >
Encoding:
C/C++ Source or Header  |  2006-11-28  |  23.5 KB  |  1,082 lines

  1. /* ScummC
  2.  * Copyright (C) 2004-2006  Alban Bedel
  3.  *
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU General Public License
  6.  * as published by the Free Software Foundation; either version 2
  7.  * of the License, or (at your option) any later version.
  8.  
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  17.  *
  18.  */
  19.  
  20. /**
  21.  * @file write.c
  22.  * @ingroup scumm
  23.  * @brief Write SCUMM data. Mostly obsolete.
  24.  */
  25.  
  26. #include "config.h"
  27.  
  28. #include <sys/types.h>
  29. #include <sys/stat.h>
  30. #include <fcntl.h>
  31. #include <inttypes.h>
  32. #include <stdlib.h>
  33. #include <unistd.h>
  34. #include <stdio.h>
  35. #include <errno.h>
  36. #include <string.h>
  37.  
  38. #include "scc_fd.h"
  39. #include "scc_util.h"
  40. #include "scc_cost.h"
  41. #include "scc.h"
  42.  
  43. int scc_res_list_size(scc_res_list_t* list) {
  44.   return 2 + 5*list->size;
  45. }
  46.  
  47. int scc_aary_size(scc_aary_t* aary) {
  48.   int size = 0;
  49.  
  50.   while(aary) {
  51.     size += 4*2;
  52.     aary = aary->next;
  53.   }
  54.   size += 2; // Terminal code
  55.   return size;
  56. }
  57.  
  58.  
  59. int scc_loff_size(scc_res_idx_t* idx) {
  60.   int num,i;
  61.  
  62.   for(num = i = 0 ; i < idx->room_list->size ; i++) {
  63.     if(idx->room_list->room_off[i]) num++;
  64.   }
  65.   return 1 + 5*num;
  66. }
  67.  
  68. int scc_cycl_size(scc_cycl_t* c) {
  69.   int size;
  70.   scc_cycl_t* iter;
  71.   
  72.   for(size = 0,iter = c ; iter ; iter = iter->next)
  73.     size += 9;
  74.   size += 1;
  75.   size = ((size+1)/2)*2; // Round up to next 2 multiple
  76.   return size;
  77. }
  78.  
  79. int scc_pals_size(scc_pal_t* p) {
  80.   int size = 8 + 8 + 8; // WRAP OFFS APAL
  81.   scc_pal_t* i;
  82.     
  83.   for(i = p ; i ; i = i->next) {
  84.     size += 4; // Offset entry
  85.     size += 256*3; // APAL data
  86.     if(i != p) size += 8; // sub pal header
  87.   }
  88.  
  89.   return size;
  90. }
  91.  
  92. int scc_rmim_size(scc_rmim_t* rmim) {
  93.   int size = 8 + 2 + 8 + 8 + rmim->smap_size;
  94.   int i;
  95.   for(i  = 0 ; i < SCC_MAX_IM_PLANES ; i++) {
  96.     if(!rmim->z_buf[i]) continue;
  97.     size += 8 + rmim->z_buf_size[i];
  98.   }
  99.   return size;
  100. }
  101.  
  102. int scc_imnn_size(scc_imnn_t* i) {
  103.   int n,size = 0;
  104.  
  105.   size += 8 + i->smap_size;
  106.   for(n = 0 ; n < SCC_MAX_IM_PLANES ; n++) {
  107.     if(!i->z_buf[n]) continue;
  108.     size += 8 + i->z_buf_size[n];
  109.   }
  110.   return size;
  111. }
  112.  
  113. int scc_obim_size(scc_obim_t* obim) {
  114.   int size = 8 + 18 + 4*obim->num_hotspots;
  115.   scc_imnn_t* i;
  116.  
  117.   for(i = obim->img ; i ; i = i->next) {
  118.     size += 8 + scc_imnn_size(i);
  119.   }
  120.   return size;
  121. }
  122.  
  123. int scc_verb_size(scc_verb_t* verb) {
  124.   int size = 1;
  125.  
  126.   //if(!verb) return 4;
  127.  
  128.   while(verb) {
  129.     size += 3 + verb->len;
  130.     //if(verb->idx == 0xFF) break;
  131.     //if(!verb->next)
  132.     //  size += 3; // closing 0
  133.     verb = verb->next;
  134.   }
  135.  
  136.   return size;
  137. }
  138.  
  139. int scc_obcd_size(scc_obcd_t* obcd) {
  140.   int size = 8 + 17; // CDHD
  141.  
  142.   size += 8 + scc_verb_size(obcd->verb);
  143.  
  144.   if(obcd->name)
  145.     size += 8 + strlen(obcd->name) + 1;
  146.  
  147.   return size;
  148. }
  149.  
  150. int scc_boxd_size(scc_boxd_t* boxd) {
  151.   int size = 2;
  152.  
  153.   while(boxd) {
  154.     size += 20;
  155.     boxd = boxd->next;
  156.   }
  157.  
  158.   return size;
  159. }
  160.  
  161. int scc_boxm_size(uint8_t ** m) {
  162.   int num,i,j;
  163.   int len = 0;
  164.  
  165.   for(num = 0 ; m[num] ; num++);
  166.  
  167.   for(i = 0 ; i < num ; i++) {
  168.     for(j = 0 ; j < num ; j++) {
  169.       int d = m[i][j];
  170.       if(d == 0xFF) continue;
  171.       while(j+1 < num && m[i][j+1] == d) j++;
  172.       len += 3;
  173.     }
  174.     len++;
  175.   }
  176.  
  177.   return len;
  178. }
  179.  
  180.  
  181. int scc_room_size(scc_room_t* r) {
  182.   int size = 8 + 6 + // RMHD
  183.     8 + scc_cycl_size(r->cycl) + // CYCL
  184.     8 + 2 + // TRNS
  185.     8 + scc_pals_size(r->pals) +
  186.     8 + scc_rmim_size(r->rmim) +
  187.     (r->excd ? 8 + r->excd->size : 0) +
  188.     (r->encd ? 8 + r->encd->size : 0) +
  189.     8 + 2 + // NLSC
  190.     (r->boxd ? 8 + scc_boxd_size(r->boxd) : 0) +
  191.     (r->boxm ? 8 + scc_boxm_size(r->boxm) : 0) +
  192.     (r->scal ? 8 + r->scal->size : 0);
  193.   scc_obim_t* obim;
  194.   scc_obcd_t* obcd;
  195.   scc_data_list_t* lscr;
  196.  
  197.   for(obim = r->obim ; obim ; obim = obim->next)
  198.     size += 8 + scc_obim_size(obim);
  199.   
  200.   for(obcd = r->obcd ; obcd ; obcd = obcd->next)
  201.     size += 8 + scc_obcd_size(obcd);
  202.  
  203.  
  204.   for(lscr = r->lscr ; lscr ; lscr = lscr->next)
  205.     size += 8 + 1 + lscr->size;
  206.  
  207.  
  208.  
  209.   return size;
  210. }
  211.  
  212. int scc_cost_anim_size(scc_cost_anim_t* a) {
  213.   int i;
  214.   int size = 2; // mask
  215.  
  216.   if(a->redir) return 0;
  217.  
  218.   for(i = 15 ; i >= 0 ; i--) {
  219.     if(!(a->mask & (1<<i))) continue;
  220.     size += 2;
  221.     if(a->limb[i].start != 0xFFFF) size += 1;
  222.   }
  223.   return size;
  224. }
  225.  
  226. int scc_cost_pic_size(scc_cost_pic_t* p,uint8_t fmt) {
  227.   scc_cost_pic_t* i;
  228.   int s,n,size = 0;
  229.  
  230.   // dup limb table
  231.   if(!p || p->id == 0xFF) return 0;
  232.  
  233.   for(n = 0, i = p ; i ; i = i->next) {
  234.     // get the hightest id, need for the table
  235.     if(i->id > n) n = i->id;
  236.     s = size;
  237.     size += 2 + 2 + // width,height
  238.       2 + 2 + // rel_x, rel_y
  239.       2 + 2; // move_x, move_y
  240.  
  241.     if((fmt & ~(0x81)) == 0x60) size += 1 + 1; // redir_limb, redir_pic
  242.         
  243.     size += i->data_size;
  244.  
  245.     //printf("Computed size pict %d -> %d\n",i->id,size-s);
  246.   }
  247.  
  248.   // limb table
  249.   size += 2*(n+1);
  250.  
  251.   return size;
  252.  
  253. }
  254.  
  255. int scc_cost_get_cmds_offset(scc_cost_t* c) {
  256.   scc_cost_anim_t* a;
  257.   int n,off =
  258.     4 + // cost size (repeated apparently)
  259.     2 + // CO header
  260.     1 + // num anim
  261.     1 + // format
  262.     c->pal_size +
  263.     2 + // anim cmds offset
  264.     16*2; // limbs offset
  265.  
  266.   // anims
  267.   for(n = 0,a = c->anims ; a ; a = a->next) {
  268.     off += scc_cost_anim_size(a); // anim def size
  269.     if(a->id > n) n = a->id;
  270.   }
  271.   off += 2*(n+1);
  272.  
  273.   return off;
  274. }
  275.  
  276. int scc_cost_size_intern(scc_cost_t* c) {
  277.   int n,size = scc_cost_get_cmds_offset(c);
  278.   
  279.   size += c->cmds_size; // cmds array
  280.  
  281.   //printf("Computed cmds end: %d\n",size); 
  282.   
  283.   for(n = 0 ; n < 16 ; n++) {
  284.     //int s = scc_cost_pic_size(c->limb_pic[n],c->format);
  285.     size += scc_cost_pic_size(c->limb_pic[n],c->format);
  286.   }
  287.   //printf("Pict size: %d %d\n",size -(cs + c->cmds_size),c->cmds_size);
  288.   //size = ((size+1)/2)*2;
  289.   return size;
  290. }
  291.  
  292. int scc_cost_size(scc_cost_t* c) {
  293.   int size = scc_cost_size_intern(c);
  294.   size = ((size+1)/2)*2;
  295.   return size;
  296. }
  297.  
  298. int scc_lfl_size(scc_lfl_t* l) {
  299.   int size = 8 + scc_room_size(&l->room);
  300.   scc_data_list_t* i;
  301.   scc_cost_t* c;
  302.  
  303.   for(i = l->scr ; i ; i = i->next)
  304.     size += 8 + i->size;
  305.  
  306.   for(i = l->snd ; i ; i = i->next)
  307.     size += 8 + i->size;
  308.   
  309.   for(c = l->cost ; c ; c = c->next)
  310.     size += 8 + scc_cost_size(c);
  311.  
  312.   for(i = l->chr ; i ; i = i->next)
  313.     size += 8 + i->size;
  314.  
  315.   return size;
  316. }
  317.  
  318. int scc_lecf_size(scc_res_t* r) {
  319.   int size = 8 + scc_loff_size(r->idx);
  320.   scc_lfl_t* i;
  321.  
  322.   for(i = r->lfl ; i ; i = i->next)
  323.     size += 8 + scc_lfl_size(i);
  324.  
  325.   return size;
  326. }
  327.  
  328. int scc_write_data_list(scc_fd_t* fd,uint32_t type,scc_data_list_t* l) {
  329.   int r,w;
  330.  
  331.   while(l) {
  332.     scc_fd_w32(fd,type);
  333.     scc_fd_w32be(fd,8+l->size);
  334.   
  335.     w=0;
  336.     while(w < l->size) {
  337.       r = scc_fd_write(fd,l->data+w,l->size-w);
  338.       if(r < 0) {
  339.     printf("Write error???\n");
  340.     return 0;
  341.       }
  342.       w += r;
  343.     }
  344.     l = l->next;
  345.   }
  346.   return 1;
  347. }
  348.  
  349. int scc_write_data(scc_fd_t* fd,uint32_t type,scc_data_t* d) {
  350.   int r,w=0;
  351.   scc_fd_w32(fd,type);
  352.   scc_fd_w32be(fd,8+d->size);
  353.  
  354.   while(w < d->size) {
  355.     r = scc_fd_write(fd,d->data+w,d->size-w);
  356.     if(r < 0) {
  357.       printf("Write error???\n");
  358.       return 0;
  359.     }
  360.     w += r;
  361.   }
  362.     
  363.   return 1;
  364. }
  365.  
  366. int scc_write_cycl(scc_fd_t* fd,scc_cycl_t* c) {
  367.   int s = 0;
  368.   while(c) {
  369.     scc_fd_w8(fd,c->idx);
  370.     scc_fd_w16be(fd,c->unk);
  371.     scc_fd_w16be(fd,c->freq);
  372.     scc_fd_w16be(fd,c->flags);
  373.     scc_fd_w8(fd,c->start);
  374.     scc_fd_w8(fd,c->end);
  375.     s += 9;
  376.     c = c->next;
  377.   }
  378.  
  379.   scc_fd_w8(fd,0);
  380.   s++;
  381.   if(s % 2) scc_fd_w8(fd,0);
  382.  
  383.   return 1;
  384. }
  385.  
  386. int scc_write_pals(scc_fd_t* fd,scc_pal_t* p) {
  387.   scc_pal_t* i;
  388.   int n,ofs,pos;
  389.  
  390.   for(n = 0,i = p ; i ; i = i->next,n++);
  391.   ofs = 8 +n*4;
  392.  
  393.   scc_fd_w32(fd,MKID('W','R','A','P'));
  394.   scc_fd_w32be(fd,scc_pals_size(p));
  395.  
  396.   scc_fd_w32(fd,MKID('O','F','F','S'));
  397.   scc_fd_w32be(fd,8+ 4*n);
  398.   scc_fd_w32le(fd,ofs);
  399.   ofs += 3*256 + 8;
  400.   for(i = p->next, pos = ofs ; i ; pos += 3*256 + 8,i = i->next)
  401.     scc_fd_w32le(fd,pos);
  402.   
  403.   scc_fd_w32(fd,MKID('A','P','A','L'));
  404.   scc_fd_w32be(fd,8+3*256);
  405.   for(pos = 0 ; pos < 256 ; pos++) {
  406.     scc_fd_w8(fd,p->r[pos]);
  407.     scc_fd_w8(fd,p->g[pos]);
  408.     scc_fd_w8(fd,p->b[pos]);
  409.   }
  410.   for(i = p->next ; i ; i = i->next) {
  411.     scc_fd_w32(fd,MKID('A','P','A','L'));
  412.     scc_fd_w32be(fd,8+3*256);
  413.     for(pos = 0 ; pos < 256 ; pos++) {
  414.       scc_fd_w8(fd,i->r[pos]);
  415.       scc_fd_w8(fd,i->g[pos]);
  416.       scc_fd_w8(fd,i->b[pos]);
  417.     }
  418.   }
  419.   return 1;
  420. }
  421.  
  422. int scc_write_rmim(scc_fd_t* fd,scc_rmim_t* rmim) {
  423.   int r,w,i;
  424.   // Room image header
  425.   scc_fd_w32(fd,MKID('R','M','I','H'));
  426.   scc_fd_w32be(fd,8 + 2);
  427.   scc_fd_w16le(fd,rmim->num_z_buf);
  428.  
  429.   // IM00
  430.   scc_fd_w32(fd,MKID('I','M','0','0'));
  431.   scc_fd_w32be(fd,scc_rmim_size(rmim)-8-2);
  432.  
  433.   // SMAP
  434.   scc_fd_w32(fd,MKID('S','M','A','P'));
  435.   scc_fd_w32be(fd,8 + rmim->smap_size);
  436.  
  437.   w = 0;
  438.   while(w < rmim->smap_size) {
  439.     r = scc_fd_write(fd,rmim->smap+w,rmim->smap_size-w);
  440.     if(r < 0) {
  441.       printf("Write error???\n");
  442.       return 0;
  443.     }
  444.     w += r;
  445.   }
  446.   
  447.   for(i = 0 ; i < SCC_MAX_IM_PLANES ; i++) {
  448.     if(!rmim->z_buf[i]) continue;
  449.     scc_fd_w32(fd,MKID('Z','P','0',('0'+i)));
  450.     scc_fd_w32be(fd,8 + rmim->z_buf_size[i]);
  451.  
  452.     w = 0;
  453.     while(w < rmim->z_buf_size[i]) {
  454.       r = scc_fd_write(fd,rmim->z_buf[i]+w,rmim->z_buf_size[i]-w);
  455.       if(r < 0) {
  456.     printf("Write error???\n");
  457.     return 0;
  458.       }
  459.       w += r;
  460.     }
  461.   }
  462.  
  463.   return 1;
  464. }
  465.  
  466. int scc_write_imnn(scc_fd_t* fd,scc_imnn_t* img) {
  467.   int r,w,nz;
  468.  
  469.   // SMAP
  470.   scc_fd_w32(fd,MKID('S','M','A','P'));
  471.   scc_fd_w32be(fd,8 + img->smap_size);
  472.   w = 0;
  473.   while(w < img->smap_size) {
  474.     r = scc_fd_write(fd,img->smap+w,img->smap_size-w);
  475.     if(r < 0) {
  476.       printf("Write error???\n");
  477.       return 0;
  478.     }
  479.     w += r;
  480.   }
  481.  
  482.   for(nz = 0 ; nz < SCC_MAX_IM_PLANES ; nz++) {
  483.     if(!img->z_buf[nz]) continue;
  484.       
  485.     scc_fd_w32(fd,MKID('Z','P','0',('0'+nz)));
  486.     scc_fd_w32be(fd,8 + img->z_buf_size[nz]);
  487.     
  488.     w = 0;
  489.     while(w < img->z_buf_size[nz]) {
  490.       r = scc_fd_write(fd,img->z_buf[nz]+w,img->z_buf_size[nz]-w);
  491.       if(r < 0) {
  492.     printf("Write error???\n");
  493.     return 0;
  494.       }
  495.       w += r;
  496.     }
  497.   }
  498.   return 1;
  499. }
  500.  
  501. int scc_write_obim(scc_fd_t* fd,scc_obim_t* im) {
  502.   int i;
  503.   scc_imnn_t* img;
  504.   // Object image header
  505.   scc_fd_w32(fd,MKID('I','M','H','D'));
  506.   scc_fd_w32be(fd,8 + 18 + im->num_hotspots*4);
  507.   
  508.   scc_fd_w16le(fd,im->idx);
  509.   scc_fd_w16le(fd,im->num_imnn);
  510.   scc_fd_w16le(fd,im->num_zpnn);
  511.   scc_fd_w16le(fd,im->unk);
  512.   scc_fd_w16le(fd,im->x);
  513.   scc_fd_w16le(fd,im->y);
  514.   scc_fd_w16le(fd,im->width);
  515.   scc_fd_w16le(fd,im->height);
  516.   scc_fd_w16le(fd,im->num_hotspots);
  517.  
  518.   for(i= 0 ; i < im->num_hotspots ; i++) {
  519.     scc_fd_w16le(fd,im->hotspots[2*i]);
  520.     scc_fd_w16le(fd,im->hotspots[2*i+1]);
  521.   }
  522.  
  523.   for(img = im->img ; img ; img = img->next) {
  524.     scc_fd_w32(fd,MKID('I','M','0','0'+img->idx));
  525.     scc_fd_w32be(fd,8 + scc_imnn_size(img));
  526.     scc_write_imnn(fd,img);
  527.   }
  528.   return 1;
  529. }
  530.  
  531. int scc_write_obcd(scc_fd_t* fd,scc_obcd_t* o) {
  532.   
  533.   scc_fd_w32(fd,MKID('C','D','H','D'));
  534.   scc_fd_w32be(fd,8 + 17);
  535.  
  536.   scc_fd_w16le(fd,o->idx);
  537.   scc_fd_w16le(fd,o->x);
  538.   scc_fd_w16le(fd,o->y);
  539.   scc_fd_w16le(fd,o->width);
  540.   scc_fd_w16le(fd,o->height);
  541.   scc_fd_w8(fd,o->flags);
  542.   scc_fd_w8(fd,o->parent);
  543.   scc_fd_w16le(fd,o->unk1);
  544.   scc_fd_w16le(fd,o->unk2);
  545.   scc_fd_w8(fd,o->actor_dir);
  546.  
  547.   if(o->verb)
  548.     scc_write_data(fd,MKID('V','E','R','B'),o->verb);
  549.  
  550.   if(o->name) {
  551.     int r,w=0,len = strlen(o->name) + 1;
  552.     scc_fd_w32(fd,MKID('O','B','N','A'));
  553.     scc_fd_w32be(fd,8 + len);
  554.     while(w < len) {
  555.       r = scc_fd_write(fd,o->name+w,len-w);
  556.       if(r < 0) {
  557.     printf("Write error???\n");
  558.     return 0;
  559.       }
  560.       w += r;
  561.     }
  562.   }
  563.   return 1;
  564. }
  565.  
  566. int scc_write_boxd(scc_fd_t* fd,scc_boxd_t* b) {
  567.   uint16_t num;
  568.   scc_boxd_t* i;
  569.  
  570.   for(num = 0, i = b ; i ; i = i->next) num++;
  571.   
  572.   scc_fd_w16le(fd,num);
  573.   while(b) {
  574.     scc_fd_w16le(fd,b->ulx);
  575.     scc_fd_w16le(fd,b->uly);
  576.     scc_fd_w16le(fd,b->urx);
  577.     scc_fd_w16le(fd,b->ury);
  578.     scc_fd_w16le(fd,b->lrx);
  579.     scc_fd_w16le(fd,b->lry);
  580.     scc_fd_w16le(fd,b->llx);
  581.     scc_fd_w16le(fd,b->lly);
  582.     scc_fd_w8(fd,b->mask);
  583.     scc_fd_w8(fd,b->flags);
  584.     scc_fd_w16le(fd,b->scale);
  585.     b = b->next;
  586.   }
  587.  
  588.   return 1;
  589. }
  590.  
  591. int scc_write_boxm(scc_fd_t* fd,uint8_t ** m) {
  592.   int num,i,j;
  593.   
  594.   for(num = 0 ; m[num] ; num++);
  595.  
  596.   for(i = 0 ; i < num ; i++) {
  597.     for(j = 0 ; j < num ; j++) {
  598.       int d = m[i][j];
  599.       if(d == 0xFF) continue;
  600.       scc_fd_w8(fd,j);
  601.       while(j+1 < num && m[i][j+1] == d) j++;
  602.       scc_fd_w8(fd,j);
  603.       scc_fd_w8(fd,d);
  604.     }
  605.     scc_fd_w8(fd,0xFF);
  606.   }
  607.  
  608.   return 1;
  609. }
  610.  
  611. int scc_write_room(scc_fd_t* fd,scc_room_t* room) {
  612.   
  613.   // Room header
  614.   scc_fd_w32(fd,MKID('R','M','H','D'));
  615.   scc_fd_w32be(fd,8 + 6);
  616.  
  617.   scc_fd_w16le(fd,room->width);
  618.   scc_fd_w16le(fd,room->height);
  619.   scc_fd_w16le(fd,room->num_objs);
  620.  
  621.   // Cycle
  622.   scc_fd_w32(fd,MKID('C','Y','C','L'));
  623.   scc_fd_w32be(fd,8 + scc_cycl_size(room->cycl));;
  624.   scc_write_cycl(fd,room->cycl);
  625.  
  626.   // Trns
  627.   scc_fd_w32(fd,MKID('T','R','N','S'));
  628.   scc_fd_w32be(fd,8 + 2);
  629.   scc_fd_w16le(fd,room->transp);
  630.  
  631.   // Pals
  632.   scc_fd_w32(fd,MKID('P','A','L','S'));
  633.   scc_fd_w32be(fd,8 + scc_pals_size(room->pals));
  634.   scc_write_pals(fd,room->pals);
  635.  
  636.   // RMIM
  637.   scc_fd_w32(fd,MKID('R','M','I','M'));
  638.   scc_fd_w32be(fd,8 + scc_rmim_size(room->rmim));
  639.   scc_write_rmim(fd,room->rmim);
  640.  
  641.   // OBIM
  642.   if(room->obim) {
  643.     scc_obim_t* i = room->obim;
  644.     while(i) {
  645.       scc_fd_w32(fd,MKID('O','B','I','M'));
  646.       scc_fd_w32be(fd,8 + scc_obim_size(i));
  647.       scc_write_obim(fd,i);
  648.       i = i->next;
  649.     }
  650.   }
  651.  
  652.   // OBCD
  653.   if(room->obcd) {
  654.     scc_obcd_t* i = room->obcd;
  655.     while(i) {
  656.       scc_fd_w32(fd,MKID('O','B','C','D'));
  657.       scc_fd_w32be(fd,8 + scc_obcd_size(i));
  658.       scc_write_obcd(fd,i);
  659.       i = i->next;
  660.     }
  661.   }
  662.  
  663.   // EXCD
  664.   scc_write_data(fd,MKID('E','X','C','D'),room->excd);
  665.   
  666.   // ENCD
  667.   scc_write_data(fd,MKID('E','N','C','D'),room->encd);
  668.  
  669.   // NLSC
  670.   scc_fd_w32(fd,MKID('N','L','S','C'));
  671.   scc_fd_w32be(fd,8+2);
  672.   scc_fd_w16le(fd,room->nlsc);
  673.  
  674.   if(room->lscr) {
  675.     scc_data_list_t* l = room->lscr;
  676.     int r,w;
  677.  
  678.     while(l) {
  679.       scc_fd_w32(fd,MKID('L','S','C','R'));
  680.       scc_fd_w32be(fd,8+1+l->size);
  681.       scc_fd_w8(fd,l->idx);
  682.       w = 0;
  683.       while(w < l->size) {
  684.     r = scc_fd_write(fd,l->data+w,l->size-w);
  685.     if(r < 0) {
  686.       printf("Write error\n");
  687.       break;
  688.     }
  689.     w += r;
  690.       }
  691.       l = l->next;
  692.     }
  693.   }
  694.   
  695.   if(room->boxd) { 
  696.     scc_fd_w32(fd,MKID('B','O','X','D'));
  697.     scc_fd_w32be(fd,8 + scc_boxd_size(room->boxd));
  698.     scc_write_boxd(fd,room->boxd);
  699.   }
  700.  
  701.   if(room->boxm) {
  702.     scc_fd_w32(fd,MKID('B','O','X','M'));
  703.     scc_fd_w32be(fd,8 + scc_boxm_size(room->boxm));
  704.     scc_write_boxm(fd,room->boxm);
  705.   }
  706.  
  707.   if(room->scal)
  708.     scc_write_data(fd,MKID('S','C','A','L'),room->scal);
  709.  
  710.   return 1;
  711. }
  712.  
  713. int scc_write_cost(scc_fd_t* fd,scc_cost_t* c) {
  714.   int off,n,len;
  715.   scc_cost_anim_t* a;
  716.   uint16_t limbs[16],*anims;
  717.   int num_anim;
  718.   off_t start_pos;
  719.  
  720.   scc_fd_w32(fd,MKID('C','O','S','T'));
  721.   scc_fd_w32be(fd,8+scc_cost_size(c));
  722.  
  723.   start_pos = scc_fd_pos(fd);
  724.  
  725.   // strange size
  726.   if(c->flags & SCC_COST_HAS_SIZE)
  727.     scc_fd_w32le(fd,scc_cost_size_intern(c));
  728.   else
  729.     scc_fd_w32le(fd,0);
  730.  
  731.   // CO header
  732.   scc_fd_w8(fd,'C');
  733.   scc_fd_w8(fd,'O');
  734.  
  735.   // Num anims
  736.   for(num_anim = 0, a = c->anims ; a ; a = a->next) {
  737.     if(a->id > num_anim) num_anim = a->id;
  738.   }
  739.   num_anim++;
  740.  
  741.   scc_fd_w8(fd, (c->flags & SCC_COST_HAS_SIZE) ? num_anim-1 : num_anim );
  742.  
  743.   // format
  744.   scc_fd_w8(fd,c->format);
  745.   // palette
  746.   scc_fd_write(fd,c->pal,c->pal_size);
  747.   // cmds off
  748.   off = scc_cost_get_cmds_offset(c);
  749.   scc_fd_w16le(fd,off);
  750.  
  751.   // limbs offset
  752.   off += c->cmds_size;
  753.   len = 0;
  754.   // we may need a 2 pass approch to support all redirect
  755.   for(n = 15 ; n >= 0 ; n--) {
  756.     scc_cost_pic_t* p = c->limb_pic[n];
  757.     int i;    
  758.  
  759.     if(p && p->id == 0xFF) {
  760.       if(p->redir_limb >= n) {
  761.     limbs[n] = limbs[p->redir_limb];
  762.     // this doesn't seems to be needed
  763.     //off += len;
  764.     //len = 0;
  765.       } else {
  766.       printf("Limb %d has an invalid redirect\n",n);
  767.       }
  768.      
  769.     } else {
  770.  
  771.       // if we have some length left look what's comming next
  772.       // we should add this length now only if there is no
  773.       // other limb after or the next limb is not a redirect
  774.       if(len) {
  775.     // find the next element
  776.     for(i = n-1 ; i >= 0 ; i--) {
  777.       if(c->limb_pic[i]) break;
  778.     }
  779.     // look if we need to add the length now
  780.     if(c->limb_pic[i]->id != 0xFF || i < 0) {
  781.       off += len;
  782.       len = 0;
  783.     }
  784.       }
  785.  
  786.       if(p) {
  787.     //limbs[n] = off;
  788.     off += len;
  789.     // count the pictures
  790.     for(i = -1 ; p ; p = p->next) {
  791.       if(i < p->id) i = p->id;
  792.     }
  793.     // add them
  794.     if(i >= 0) {
  795.       len = (i+1)*2;
  796.     } else
  797.       len = 0;
  798.       }
  799.       limbs[n] = off;
  800.     }
  801.   }
  802.  
  803.   for(n = 15 ; n >= 0 ; n--)
  804.     scc_fd_w16le(fd,limbs[n]);
  805.  
  806.   anims = calloc(num_anim,2);
  807.   off = 4 + // cost size (repeated apparently)
  808.     2 + // CO header
  809.     1 + // num anim
  810.     1 + // format
  811.     c->pal_size +
  812.     2 + // anim cmds offset
  813.     16*2 + // limbs offset
  814.     num_anim*2;
  815.  
  816.   for(a = c->anims ; a ; a = a->next) {
  817.     if(a->redir) {
  818.       if(a->redir < a->id)
  819.     anims[a->id] = anims[a->redir];
  820.       else
  821.     printf("Anim %d has an invalid redirect\n",a->id);
  822.       
  823.     } else {
  824.       anims[a->id] = off;
  825.       off += scc_cost_anim_size(a);
  826.     }
  827.   }
  828.     
  829.   for(n = 0 ; n < num_anim ; n++)
  830.     scc_fd_w16le(fd,anims[n]);
  831.     
  832.   free(anims);
  833.  
  834.   // anim definitions
  835.   for(a = c->anims ; a ; a = a->next) {
  836.     if(a->redir) continue;
  837.  
  838.     scc_fd_w16le(fd,a->mask);
  839.     for(n = 15 ; n >= 0 ; n--) {
  840.       if(!(a->mask & (1<<n))) continue;
  841.       scc_fd_w16le(fd,a->limb[n].start);
  842.       if(a->limb[n].start != 0xFFFF)
  843.     scc_fd_w8(fd,(a->limb[n].end - a->limb[n].start) | 
  844.           (a->limb[n].flags << 7));
  845.     }
  846.   }
  847.  
  848.   // cmds
  849. #ifdef TESTING
  850.   if(scc_cost_get_cmds_offset(c) != scc_fd_pos(fd) - start_pos)
  851.     printf("Cmds start at wrong offset: %d / %d\n",scc_fd_pos(fd) - start_pos,
  852.          (int)scc_cost_get_cmds_offset(c));
  853. #endif
  854.  
  855.   scc_fd_write(fd,c->cmds,c->cmds_size);
  856.  
  857.   off = scc_cost_get_cmds_offset(c) + c->cmds_size;
  858.  
  859.   // limb tables, first we need to find the start of the first pic
  860.   for(n = 15 ; n >= 0 ; n--) { 
  861.     scc_cost_pic_t* pic = c->limb_pic[n];
  862.     int num_pic = -1;
  863.     if(!pic || pic->id == 0xFF) continue;
  864.  
  865.     for( ; pic ; pic = pic->next) {
  866.       if(pic->id > num_pic) num_pic = pic->id;
  867.     }
  868.     if(num_pic >= 0) off += (num_pic+1)*2;
  869.   }
  870.     
  871.   // now we can write the tables
  872.   for(n = 15 ; n >= 0 ; n--) { 
  873.     scc_cost_pic_t* pic = c->limb_pic[n];
  874.     int last_id = -1;
  875.  
  876.     if(!pic || pic->id == 0xFF) continue;
  877.  
  878. #ifdef TESTING
  879.     if(limbs[n] != scc_fd_pos(fd) - start_pos)
  880.       printf("Limb table starts at the wrong place: %d / %d\n",
  881.          (int)scc_fd_pos(fd) - start_pos,limbs[n]);
  882. #endif
  883.  
  884.     for( ; pic ; pic = pic->next) {
  885.       if(pic->id > last_id+1) {
  886.     for( ; last_id+1 < pic->id ; last_id++)
  887.       scc_fd_w16le(fd,0);
  888.       }
  889.       last_id = pic->id;
  890.  
  891.       scc_fd_w16le(fd,off);
  892.       off += 2 + 2 + // width,height
  893.     2 + 2 + // rel_x, rel_y
  894.     2 + 2; // move_x, move_y
  895.  
  896.       if((c->format & ~(0x81)) == 0x60) 
  897.     off += 1 + 1; // redir_limb, redir_pic
  898.     
  899.       off += pic->data_size;
  900.     }
  901.   }
  902.  
  903.   // and finnaly write the pics
  904.   for(n = 15 ; n >= 0 ; n--) { 
  905.     scc_cost_pic_t* pic = c->limb_pic[n];
  906.  
  907.     if(!pic || pic->id == 0xFF) continue;
  908.  
  909.     for( ; pic ; pic = pic->next) {
  910.       // the header
  911.       scc_fd_w16le(fd,pic->width);
  912.       scc_fd_w16le(fd,pic->height);
  913.       scc_fd_w16le(fd,pic->rel_x);
  914.       scc_fd_w16le(fd,pic->rel_y);
  915.       scc_fd_w16le(fd,pic->move_x);
  916.       scc_fd_w16le(fd,pic->move_y);
  917.       if((c->format & ~(0x81)) == 0x60) {
  918.     scc_fd_w8(fd,pic->redir_limb);
  919.     scc_fd_w8(fd,pic->redir_pic);
  920.       }
  921.       scc_fd_write(fd,pic->data,pic->data_size);
  922.     }
  923.   }
  924.  
  925.   n = scc_fd_pos(fd) - start_pos;
  926.   if(n % 2) scc_fd_w8(fd,0);
  927.  
  928. #ifdef TESTING
  929.   n = scc_fd_pos(fd) - start_pos;
  930.   off = scc_cost_size(c);
  931.   if(n != off)
  932.     printf("Failed to write costume (%d / %d => %d )????\n",n,off,n-off);
  933. #endif
  934.  
  935.   return 1;
  936. }
  937.  
  938. int scc_write_lfl(scc_fd_t* fd,scc_lfl_t* lfl) {
  939.   scc_cost_t* c;
  940.  
  941.   printf("Writing LFLF %d\n",lfl->room.idx);
  942.  
  943.   scc_fd_w32(fd,MKID('R','O','O','M'));
  944.   scc_fd_w32be(fd,8+scc_room_size(&lfl->room));
  945.  
  946.   scc_write_room(fd,&lfl->room);
  947.  
  948.   if(lfl->scr) scc_write_data_list(fd,MKID('S','C','R','P'),lfl->scr);
  949.   if(lfl->snd) scc_write_data_list(fd,MKID('S','O','U','N'),lfl->snd);
  950.   //  FIXME
  951.   for(c = lfl->cost ; c ; c = c->next)
  952.     scc_write_cost(fd,c);
  953.  
  954.   //  if(lfl->cost) scc_write_data_list(fd,MKID('C','O','S','T'),lfl->cost);
  955.   if(lfl->chr) scc_write_data_list(fd,MKID('C','H','A','R'),lfl->chr);
  956.  
  957.   return 1;
  958. }
  959.  
  960.  
  961. int scc_write_lecf(scc_fd_t* fd,scc_res_t* r) {
  962.   scc_lfl_t* i;
  963.   int s,j;
  964.   // LECF block
  965.   scc_fd_w32(fd,MKID('L','E','C','F'));
  966.   scc_fd_w32be(fd,8+scc_lecf_size(r));
  967.  
  968.   // LOFF block
  969.   s = scc_loff_size(r->idx);
  970.   scc_fd_w32(fd,MKID('L','O','F','F'));
  971.   scc_fd_w32be(fd,8+s);
  972.   // num of block :)
  973.   s -= 1;
  974.   s /= 5;
  975.   scc_fd_w8(fd,s);
  976.   for(j = 0 ; j < r->idx->room_list->size ; j++) {
  977.     if(!r->idx->room_list->room_off[j]) continue;
  978.     scc_fd_w8(fd,j);
  979.     scc_fd_w32le(fd,r->idx->room_list->room_off[j]);
  980.   }
  981.  
  982.   for(i = r->lfl ; i ; i = i->next) {
  983.     scc_fd_w32(fd,MKID('L','F','L','F'));
  984.     scc_fd_w32be(fd,8+scc_lfl_size(i));
  985.     scc_write_lfl(fd,i);
  986.   }
  987.  
  988.   return 1;
  989. }
  990.   
  991.  
  992.  
  993. int scc_write_res_list(scc_fd_t* fd,uint32_t type,scc_res_list_t* list) {
  994.   int i,size = 8 + scc_res_list_size(list);
  995.  
  996.   scc_fd_w32(fd,type);
  997.   scc_fd_w32be(fd,size);
  998.  
  999.   scc_fd_w16le(fd,list->size);
  1000.   for(i = 0 ; i < list->size ; i++)
  1001.     scc_fd_w8(fd,list->room_no[i]);
  1002.   for(i = 0 ; i < list->size ; i++)
  1003.     scc_fd_w32le(fd,list->room_off[i]);
  1004.  
  1005.   return size;
  1006. }
  1007.  
  1008. int scc_write_res_idx(scc_fd_t* fd,scc_res_idx_t* idx) {
  1009.  
  1010.   scc_fd_w32(fd,MKID('R','N','A','M'));
  1011.   scc_fd_w32be(fd,8+1);
  1012.   scc_fd_w8(fd,idx->rnam);
  1013.  
  1014.   scc_fd_w32(fd,MKID('M','A','X','S'));
  1015.   scc_fd_w32be(fd,8+30);
  1016.   scc_fd_w16le(fd,idx->num_vars);
  1017.   scc_fd_w16le(fd,idx->unk1);
  1018.   scc_fd_w16le(fd,idx->num_bit_vars);
  1019.   scc_fd_w16le(fd,idx->num_local_objs);
  1020.   scc_fd_w16le(fd,idx->num_array);
  1021.   scc_fd_w16le(fd,idx->unk2);
  1022.   scc_fd_w16le(fd,idx->num_verbs);
  1023.   scc_fd_w16le(fd,idx->num_fl_objs);
  1024.   scc_fd_w16le(fd,idx->num_inv);
  1025.   scc_fd_w16le(fd,idx->num_rooms);
  1026.   scc_fd_w16le(fd,idx->num_scr);
  1027.   scc_fd_w16le(fd,idx->num_snds);
  1028.   scc_fd_w16le(fd,idx->num_chst);
  1029.   scc_fd_w16le(fd,idx->num_cost);
  1030.   scc_fd_w16le(fd,idx->num_glob_objs);
  1031.  
  1032.   // Check me room are different
  1033.   // i think offset here indicate the disk
  1034.   if(idx->room_list)
  1035.     scc_write_res_list(fd,MKID('D','R','O','O'),idx->room_list);
  1036.  
  1037.   if(idx->scr_list)
  1038.     scc_write_res_list(fd,MKID('D','S','C','R'),idx->scr_list);
  1039.  
  1040.   if(idx->snd_list)
  1041.     scc_write_res_list(fd,MKID('D','S','O','U'),idx->snd_list);
  1042.  
  1043.   if(idx->cost_list)
  1044.     scc_write_res_list(fd,MKID('D','C','O','S'),idx->cost_list);
  1045.   
  1046.   if(idx->chst_list)
  1047.     scc_write_res_list(fd,MKID('D','C','H','R'),idx->chst_list);
  1048.  
  1049.   if(idx->num_obj_owners > 0) {
  1050.     scc_fd_w32(fd,MKID('D','O','B','J'));
  1051.     scc_fd_w32be(fd,8+2+5*idx->num_obj_owners);
  1052.     scc_fd_w16le(fd,idx->num_obj_owners);
  1053.     if(scc_fd_write(fd,idx->obj_owners,idx->num_obj_owners) !=
  1054.        idx->num_obj_owners) {
  1055.       printf("Write error???\n");
  1056.       return 0;
  1057.     }
  1058.     if(scc_fd_write(fd,idx->class_data,idx->num_obj_owners*4) !=
  1059.        idx->num_obj_owners*4) {
  1060.       printf("Write error???\n");
  1061.       return 0;
  1062.     }
  1063.   }
  1064.  
  1065.   if(idx->aary) {
  1066.     scc_aary_t* iter;
  1067.     scc_fd_w32(fd,MKID('A','A','R','Y'));
  1068.     scc_fd_w32be(fd,8 + scc_aary_size(idx->aary));
  1069.     for(iter = idx->aary ; iter ; iter = iter->next) {
  1070.       scc_fd_w16le(fd,iter->idx);
  1071.       scc_fd_w16le(fd,iter->a);
  1072.       scc_fd_w16le(fd,iter->b);
  1073.       scc_fd_w16le(fd,iter->c);
  1074.     }
  1075.     scc_fd_w16le(fd,0);
  1076.   }
  1077.  
  1078.   return 1;
  1079. }
  1080.  
  1081.  
  1082.