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 / scvm_view.c < prev    next >
Encoding:
C/C++ Source or Header  |  2008-01-14  |  9.1 KB  |  334 lines

  1.  
  2. /* ScummC
  3.  * Copyright (C) 2006  Alban Bedel
  4.  *
  5.  * This program is free software; you can redistribute it and/or
  6.  * modify it under the terms of the GNU General Public License
  7.  * as published by the Free Software Foundation; either version 2
  8.  * of the License, or (at your option) any later version.
  9.  
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  18.  *
  19.  */
  20.  
  21. /**
  22.  * @file scvm_view.c
  23.  * @ingroup scvm
  24.  * @brief SCVM rendering
  25.  */
  26.  
  27. #include "config.h"
  28.  
  29. #include <stdlib.h>
  30. #include <stdio.h>
  31. #include <string.h>
  32. #include <inttypes.h>
  33. #include <errno.h>
  34. #include <sys/types.h>
  35. #include <sys/stat.h>
  36. #include <fcntl.h>
  37.  
  38. #include "scc_fd.h"
  39. #include "scc_util.h"
  40. #include "scc_param.h"
  41. #include "scc_cost.h"
  42. #include "scc_box.h"
  43. #include "scvm_res.h"
  44. #include "scvm_thread.h"
  45. #include "scvm.h"
  46.  
  47.  
  48. static void scale_copy(uint8_t* dst, int dst_stride,
  49.                        unsigned clip_width, unsigned clip_height,
  50.                        int x, int y,
  51.                        int dst_width, int dst_height,
  52.                        uint8_t* src, int src_stride,
  53.                        int src_width, int src_height,
  54.                        int trans) {
  55.   int sx = 0,sy = 0,dx = 0,dy = 0,xerr = 0,yerr = 0,skip = 0;
  56.  
  57.   dst += dst_stride*y;
  58.   dst += x;
  59.  
  60.   while(dy < dst_height && dy+y < clip_height) {
  61.     if(!skip && dy+y >= 0) {
  62.       dx = sx = 0;
  63.       while(dx < dst_width) {
  64.         if(!skip && dx+x >= 0 && dx+x < clip_width &&
  65.            (trans < 0 || trans != src[sx]))
  66.           dst[dx] = src[sx];
  67.         xerr += dst_width;
  68.         if(xerr<<1 >= src_width) {
  69.           xerr -= src_width;
  70.           dx++;
  71.           skip = 0;
  72.           if(xerr<<1 >= src_width) {
  73.             xerr -= dst_width;
  74.             continue;
  75.           }
  76.         } else
  77.           skip = 1;
  78.         sx++;
  79.       }
  80.     }
  81.     yerr += dst_height;
  82.     if(yerr<<1 >= src_height) {
  83.       yerr -= src_height;
  84.       dy++;
  85.       dst += dst_stride;
  86.       skip = 0;
  87.       if(yerr<<1 >= src_height) {
  88.         yerr -= dst_height;
  89.         continue;
  90.       }
  91.     } else
  92.       skip = 1;
  93.     sy++;
  94.     src += src_stride;
  95.   }
  96. }
  97.  
  98. uint8_t* make_zplane(scvm_t* vm, scvm_view_t* view,
  99.                      unsigned dst_width, unsigned dst_height,
  100.                      unsigned src_width, unsigned src_height,
  101.                      unsigned src_x, unsigned zid) {
  102.   uint8_t* zplane = malloc(dst_width*dst_height);
  103.   scale_copy(zplane,dst_width,dst_width,dst_height,
  104.              0,0,dst_width,dst_height,
  105.              vm->room->image.zplane[zid] + src_x,vm->room->width,
  106.              src_width, src_height,-1);
  107.   // TODO: copy objects zplanes from the visible area
  108.   return zplane;
  109. }
  110.  
  111.  
  112. int scvm_view_draw(scvm_t* vm, scvm_view_t* view,
  113.                    uint8_t* buffer, int stride,
  114.                    unsigned width, unsigned height) {
  115.   int sx,dx,dy,w,h,dw,dh,a;
  116.  
  117.   if(!vm->room) return 0;
  118.  
  119.   h = vm->room->height;
  120.   if(view->room_start + h != view->room_end)
  121.     scc_log(LOG_WARN,"View setup doesn't match the room height.\n");
  122.   
  123.   if(view->room_start + h > height)
  124.     h = height - view->room_start;
  125.   
  126.   if(h <= 0) return 0;  
  127.   w = vm->room->width;
  128.   if(w > view->screen_width) w = view->screen_width;
  129.   
  130.   sx = vm->view->camera_x-w/2;
  131.   if(sx + w/2 > vm->room->width) sx = vm->room->width-w;
  132.   if(sx < 0) sx = 0;
  133.   
  134.   dw = w*width/view->screen_width;
  135.   dh = h*height/view->screen_height;
  136.   dx = (view->screen_width-w)*width/view->screen_width/2;
  137.   dy = view->room_start*height/view->screen_height;
  138.  
  139.   scale_copy(buffer,stride,width,height,
  140.              dx,dy,dw,dh,
  141.              vm->room->image.data+sx, vm->room->width,
  142.              w,h,-1);
  143.  
  144.   for(a = 0 ; a < vm->room->num_object ; a++) {
  145.     scvm_object_t* obj = vm->room->object[a];
  146.     scvm_image_t* img;
  147.     int obj_w,obj_h;
  148.     if(!obj->pdata->state ||
  149.        obj->pdata->state > obj->num_image)
  150.       continue;
  151.     img = &obj->image[obj->pdata->state];
  152.     obj_w = obj->width;
  153.     obj_h = obj->height;
  154.     if(obj->x >= sx + vm->room->width ||
  155.        obj->x + obj->width < sx ||
  156.        obj->y >= h ||
  157.        obj->y + obj_h < 0)
  158.       continue;
  159.  
  160.     scale_copy(buffer,stride,width,height,
  161.                dx + (obj->x-sx)*width/view->screen_width,
  162.                dy + obj->y*height/view->screen_height,
  163.                obj_w*width/view->screen_width,
  164.                obj_h*height/view->screen_height,
  165.                img->data, obj_w, obj_w, obj_h,
  166.                img->have_trans ? vm->room->trans : -1);
  167.   }
  168.   
  169.   for(a = 0 ; a < vm->num_actor ; a++) {
  170.     uint8_t* zplane = NULL;
  171.     if(!vm->actor[a].room ||
  172.        vm->actor[a].room != vm->room->id ||
  173.        !vm->actor[a].costdec.cost) continue;
  174.     scc_log(LOG_MSG,"Draw actor %d at %dx%d\n",a,vm->actor[a].x,vm->actor[a].y);
  175.     if(vm->actor[a].box) {
  176.       int mask = vm->room->box[vm->actor[a].box].mask;
  177.       if(mask <= vm->room->num_zplane) {
  178.         if(!vm->room->zplane[mask])
  179.           vm->room->zplane[mask] = make_zplane(vm,view,
  180.                                                dw,dh,
  181.                                                w,h,sx,mask);
  182.         zplane = vm->room->zplane[mask];
  183.       }
  184.     }
  185.     scc_cost_dec_frame(&vm->actor[a].costdec,
  186.                        buffer + dy*stride + dx,
  187.                        (vm->actor[a].x-sx)*width/view->screen_width,
  188.                        vm->actor[a].y*height/view->screen_height,
  189.                        dw,dh,stride,
  190.                        zplane,dw,
  191.                        vm->actor[a].scale_x*width/view->screen_width,
  192.                        vm->actor[a].scale_y*height/view->screen_height);
  193.   }
  194.  
  195.   // TODO: Use some invalidation to avoid recomputing the
  196.   //       whole thing when not needed
  197.   for(a = 0 ; a <= vm->room->num_zplane ; a++)
  198.     if(vm->room->zplane[a]) {
  199.       free(vm->room->zplane[a]);
  200.       vm->room->zplane[a] = NULL;
  201.     }
  202.  
  203.   return 1;
  204. }
  205.  
  206. void scvm_view_scale_palette(scvm_view_t* view, scvm_color_t* palette,
  207.                              unsigned red, unsigned green, unsigned blue,
  208.                              unsigned start, unsigned end) {
  209.   if(start > 0xFF) return;
  210.   if(start < 0) start = 0;
  211.   if(end > 0xFF) end = 0xFF;
  212.   
  213.   while(start <= end) {
  214.     int color = palette[start].r;
  215.     color = color * red / 0xFF;
  216.     if(color > 0xFF) color = 0xFF;
  217.     view->palette[start].r = color;
  218.     
  219.     color = palette[start].g;
  220.     color = color * green / 0xFF;
  221.     if(color > 0xFF) color = 0xFF;
  222.     view->palette[start].g = color;
  223.     
  224.     color = palette[start].b;
  225.     color = color * blue / 0xFF;
  226.     if(color > 0xFF) color = 0xFF;
  227.     view->palette[start].b = color;
  228.     
  229.     view->flags |= SCVM_VIEW_PALETTE_CHANGED;
  230.     start++;
  231.   }
  232.   
  233. }
  234.  
  235. int scvm_abs_position_to_virtual(scvm_t* vm, int* dx, int* dy) {
  236.     int x = *dx, y = *dy;
  237.     if(y < vm->view->room_start || y >= vm->view->room_end) return -1;
  238.     y -= vm->view->room_start;
  239.     x += (vm->view->camera_x-vm->view->screen_width/2);
  240.     if(x < 0 || x > vm->room->width) return -1;
  241.     *dx = x;
  242.     *dy = y;
  243.     return 0;
  244. }
  245.  
  246. void scvm_pan_camera_to(scvm_t* vm, int x) {
  247.   if(x < vm->var->camera_min_x)
  248.     x = vm->var->camera_min_x;
  249.   if(x > vm->var->camera_max_x)
  250.     x = vm->var->camera_max_x;
  251.   vm->view->camera_dst_x = x & ~7;
  252.   vm->view->flags |= SCVM_VIEW_PAN;
  253. }
  254.  
  255.  
  256. int scvm_set_camera_at(scvm_t* vm, int x) {
  257.   int r;
  258.   if(x < vm->var->camera_min_x)
  259.     x = vm->var->camera_min_x;
  260.   if(x > vm->var->camera_max_x)
  261.     x = vm->var->camera_max_x;
  262.   vm->view->camera_x = x & ~7;
  263.   if(vm->var->camera_script) {
  264.     vm->var->camera_pos_x = vm->view->camera_x;
  265.     if((r = scvm_start_script(vm,0,vm->var->camera_script,NULL)) < 0)
  266.       return r;
  267.     return r+1;
  268.   }
  269.   return 0;
  270. }
  271.  
  272. int scvm_move_camera(scvm_t* vm) {
  273.   int fast = vm->var->camera_fast_x;
  274.   int r, x = vm->view->camera_x;
  275.   // Keep into range. Such adjustement are not
  276.   // calling the camera script
  277.   if(x < vm->var->camera_min_x) {
  278.     if(fast)
  279.       vm->view->camera_x = vm->var->camera_min_x & ~7;
  280.     else
  281.       vm->view->camera_x += 8;
  282.     return 0;
  283.   }
  284.  
  285.   if(x > vm->var->camera_max_x) {
  286.     if(fast)
  287.       vm->view->camera_x = vm->var->camera_max_x & ~7;
  288.     else
  289.       vm->view->camera_x -= 8;
  290.     return 0;
  291.   }
  292.  
  293.   if(vm->view->follow) {
  294.     scvm_actor_t* a = &vm->actor[vm->view->follow];
  295.     // In wich strip is the actor
  296.     int stripe = (a->x-x)/8;
  297.     if(abs(stripe) < vm->view->screen_width/8/2-10)
  298.       return 0;
  299.  
  300.     vm->view->camera_dst_x = a->x & ~7;
  301.   } else {
  302.     if(!(vm->view->flags & SCVM_VIEW_PAN))
  303.       return 0;
  304.  
  305.     if(vm->view->camera_dst_x == vm->view->camera_x) {
  306.       vm->view->flags &= ~SCVM_VIEW_PAN;
  307.       return 0;
  308.     }
  309.   }
  310.  
  311.   if(fast)
  312.     x = vm->view->camera_dst_x;
  313.   else {
  314.     if(x < vm->view->camera_dst_x)
  315.       x += 8;
  316.     else
  317.       x -= 8;
  318.   }
  319.  
  320.   if(x < vm->var->camera_min_x)
  321.     x = vm->var->camera_min_x;
  322.   if(x > vm->var->camera_max_x)
  323.     x = vm->var->camera_max_x;
  324.  
  325.   x &= ~7;
  326.  
  327.   if(x == vm->view->camera_x) {
  328.     vm->view->flags &= ~SCVM_VIEW_PAN;
  329.     return 0;
  330.   }
  331.  
  332.   return scvm_set_camera_at(vm,x);
  333. }
  334.