[56] | 1 | /* |
---|
| 2 | * Abuse - dark 2D side-scrolling platform game |
---|
| 3 | * Copyright (c) 1995 Crack dot Com |
---|
[494] | 4 | * Copyright (c) 2005-2011 Sam Hocevar <sam@hocevar.net> |
---|
[56] | 5 | * |
---|
| 6 | * This software was released into the Public Domain. As with most public |
---|
| 7 | * domain software, no warranty is made or implied by Crack dot Com or |
---|
| 8 | * Jonathan Clark. |
---|
| 9 | */ |
---|
| 10 | |
---|
[115] | 11 | #ifndef _IMAGE_HPP_ |
---|
| 12 | #define _IMAGE_HPP_ |
---|
| 13 | |
---|
[2] | 14 | #include <stdlib.h> |
---|
[481] | 15 | #include "linked.h" |
---|
| 16 | #include "palette.h" |
---|
[2] | 17 | #include "system.h" |
---|
[481] | 18 | #include "specs.h" |
---|
[2] | 19 | #define MAX_DIRTY 200 |
---|
| 20 | |
---|
[39] | 21 | extern char const *imerr_messages[]; // correspond to imERRORS |
---|
[115] | 22 | #define imREAD_ERROR 1 |
---|
[2] | 23 | #define imINCORRECT_FILETYPE 2 |
---|
| 24 | #define imFILE_CORRUPTED 3 |
---|
| 25 | #define imFILE_NOT_FOUND 4 |
---|
| 26 | #define imMEMORY_ERROR 5 |
---|
| 27 | #define imNOT_SUPPORTED 6 |
---|
| 28 | #define imWRITE_ERROR 7 |
---|
[115] | 29 | #define imMAX_ERROR 7 |
---|
[2] | 30 | |
---|
[17] | 31 | int16_t current_error(); |
---|
[2] | 32 | void clear_errors(); |
---|
[17] | 33 | void set_error(int16_t x); |
---|
| 34 | int16_t last_error(); |
---|
[2] | 35 | void image_init(); |
---|
| 36 | void image_uninit(); |
---|
| 37 | extern linked_list image_list; |
---|
| 38 | |
---|
| 39 | typedef struct image_color_t |
---|
| 40 | { |
---|
[115] | 41 | uint16_t r; |
---|
| 42 | uint16_t g; |
---|
| 43 | uint16_t b; |
---|
[2] | 44 | } image_color; |
---|
| 45 | |
---|
| 46 | class filter; |
---|
| 47 | |
---|
| 48 | |
---|
| 49 | class dirty_rect : public linked_node |
---|
| 50 | { |
---|
| 51 | public : |
---|
[17] | 52 | int16_t dx1,dy1,dx2,dy2; |
---|
| 53 | dirty_rect(int16_t x1, int16_t y1, int16_t x2, int16_t y2) |
---|
[115] | 54 | { dx1=x1; dy1=y1; dx2=x2; dy2=y2; |
---|
| 55 | if(x2<x1 || y2<y1) |
---|
[515] | 56 | printf("add incorrect dirty\n"); |
---|
[2] | 57 | } |
---|
[17] | 58 | virtual int16_t compare(void *n1, int16_t field) |
---|
[115] | 59 | { return((dirty_rect *)n1)->dy1>dy1; } |
---|
[2] | 60 | } ; |
---|
| 61 | |
---|
| 62 | class image_descriptor |
---|
| 63 | { |
---|
[115] | 64 | private: |
---|
[518] | 65 | int m_l, m_h; |
---|
| 66 | int m_clipx1, m_clipy1, m_clipx2, m_clipy2; |
---|
[2] | 67 | |
---|
[115] | 68 | public: |
---|
| 69 | uint8_t keep_dirt, |
---|
| 70 | static_mem; // if set, don't free memory on exit |
---|
| 71 | |
---|
| 72 | linked_list dirties; |
---|
| 73 | void *extended_descriptor; |
---|
| 74 | |
---|
[513] | 75 | image_descriptor(vec2i size, int keep_dirties = 1, int static_memory = 0); |
---|
[518] | 76 | int bound_x1(int x1) { return x1 < m_clipx1 ? m_clipx1 : x1; } |
---|
| 77 | int bound_y1(int y1) { return y1 < m_clipy1 ? m_clipy1 : y1; } |
---|
| 78 | int bound_x2(int x2) { return x2 > m_clipx2 ? m_clipx2 : x2; } |
---|
| 79 | int bound_y2(int y2) { return y2 > m_clipy2 ? m_clipy2 : y2; } |
---|
| 80 | inline int x1_clip() { return m_clipx1; } |
---|
| 81 | inline int y1_clip() { return m_clipy1; } |
---|
| 82 | inline int x2_clip() { return m_clipx2; } |
---|
| 83 | inline int y2_clip() { return m_clipy2; } |
---|
| 84 | void ClearDirties(); |
---|
| 85 | void GetClip(int &x1, int &y1, int &x2, int &y2) |
---|
[115] | 86 | { |
---|
[518] | 87 | x1 = m_clipx1; y1 = m_clipy1; x2 = m_clipx2; y2 = m_clipy2; |
---|
[2] | 88 | } |
---|
[518] | 89 | void SetClip(int x1, int y1, int x2, int y2) |
---|
[115] | 90 | { |
---|
[518] | 91 | if(x2 < x1 + 1) x2 = x1 + 1; |
---|
| 92 | if(y2 < y1 + 1) y2 = y1 + 1; |
---|
| 93 | m_clipx1 = Max(x1, 0); m_clipy1 = Max(y1, 0); |
---|
| 94 | m_clipx2 = Min(x2, m_l); m_clipy2 = Min(y2, m_h); |
---|
[115] | 95 | } |
---|
[518] | 96 | void ReduceDirties(); |
---|
| 97 | void AddDirty(int x1, int y1, int x2, int y2); |
---|
[115] | 98 | void delete_dirty(int x1, int y1, int x2, int y2); |
---|
[518] | 99 | void Resize(vec2i size) |
---|
[115] | 100 | { |
---|
[518] | 101 | m_l = size.x; m_h = size.y; |
---|
| 102 | m_clipx1 = 0; m_clipy1 = 0; m_clipx2 = m_l; m_clipy2 = m_h; |
---|
[115] | 103 | } |
---|
| 104 | }; |
---|
[2] | 105 | |
---|
| 106 | class image : public linked_node |
---|
| 107 | { |
---|
[115] | 108 | private: |
---|
[513] | 109 | uint8_t *m_data; |
---|
| 110 | vec2i m_size; |
---|
| 111 | bool m_locked; |
---|
[2] | 112 | |
---|
[515] | 113 | void MakePage(vec2i size, uint8_t *page_buffer); |
---|
| 114 | void DeletePage(); |
---|
| 115 | |
---|
[115] | 116 | public: |
---|
[515] | 117 | image_descriptor *m_special; |
---|
[2] | 118 | |
---|
[115] | 119 | image(spec_entry *e, bFILE *fp); |
---|
| 120 | image(bFILE *fp); |
---|
[513] | 121 | image(vec2i size, uint8_t *page_buffer = NULL, int create_descriptor = 0); |
---|
[115] | 122 | ~image(); |
---|
[2] | 123 | |
---|
[515] | 124 | void Lock(); |
---|
| 125 | void Unlock(); |
---|
[2] | 126 | |
---|
[515] | 127 | uint8_t Pixel(vec2i pos); |
---|
| 128 | void PutPixel(vec2i pos, uint8_t color); |
---|
| 129 | |
---|
| 130 | inline uint8_t *scan_line(int16_t y) |
---|
[115] | 131 | { |
---|
[513] | 132 | return m_data + y * m_size.x; |
---|
[115] | 133 | } |
---|
[515] | 134 | inline uint8_t *next_line(int16_t lasty, uint8_t *last_scan) |
---|
[115] | 135 | { |
---|
[513] | 136 | return last_scan + m_size.x; |
---|
[115] | 137 | } |
---|
| 138 | int32_t total_pixels(uint8_t background=0); |
---|
| 139 | image *copy(); // makes a copy of an image |
---|
| 140 | void clear(int16_t color = -1); // -1 is background color |
---|
| 141 | void to_24bit(palette &pal); |
---|
[512] | 142 | |
---|
[513] | 143 | vec2i Size() const { return m_size; } |
---|
[512] | 144 | |
---|
[115] | 145 | void scroll(int16_t x1, int16_t y1, int16_t x2, int16_t y2, |
---|
| 146 | int16_t xd, int16_t yd); |
---|
| 147 | void fill_image(image *screen, int16_t x1, int16_t y1, |
---|
| 148 | int16_t x2, int16_t y2, int16_t align = 1); |
---|
| 149 | void put_image(image *screen, int16_t x, int16_t y, char transparent = 0); |
---|
| 150 | void put_part(image *screen, int16_t x, int16_t y, int16_t x1, int16_t y1, |
---|
| 151 | int16_t x2, int16_t y2, char transparent = 0); |
---|
| 152 | void put_part_xrev(image *screen, int16_t x, int16_t y, |
---|
| 153 | int16_t x1, int16_t y1, int16_t x2, int16_t y2, |
---|
| 154 | char transparent = 0); |
---|
| 155 | void put_part_masked(image *screen, image *mask, int16_t x, int16_t y, |
---|
| 156 | int16_t maskx, int16_t masky, int16_t x1, int16_t y1, |
---|
| 157 | int16_t x2, int16_t y2); |
---|
| 158 | image *copy_part_dithered(int16_t x1, int16_t y1, int16_t x2, int16_t y2); |
---|
| 159 | void bar(int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint8_t color); |
---|
| 160 | void xor_bar(int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint8_t color); |
---|
| 161 | void widget_bar(int16_t x1, int16_t y1, int16_t x2, int16_t y2, |
---|
| 162 | uint8_t light, uint8_t med, uint8_t dark); |
---|
| 163 | void line(int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint8_t color); |
---|
| 164 | void rectangle(int16_t x1, int16_t y1, int16_t x2, int16_t y2, |
---|
| 165 | uint8_t color); |
---|
| 166 | void burn_led(int16_t x, int16_t y, int32_t num, int16_t color, |
---|
| 167 | int16_t scale = 1); |
---|
[518] | 168 | void SetClip(int x1, int y1, int x2, int y2); |
---|
| 169 | void GetClip(int &x1, int &y1, int &x2, int &y2); |
---|
| 170 | void InClip(int x1, int y1, int x2, int y2); |
---|
[2] | 171 | |
---|
[115] | 172 | void dirt_off() |
---|
| 173 | { |
---|
[515] | 174 | if(m_special && m_special->keep_dirt) m_special->keep_dirt = 0; |
---|
[115] | 175 | } |
---|
| 176 | void dirt_on() |
---|
| 177 | { |
---|
[515] | 178 | if(m_special) m_special->keep_dirt = 1; |
---|
[115] | 179 | } |
---|
[2] | 180 | |
---|
[518] | 181 | void AddDirty(int x1, int y1, int x2, int y2) |
---|
[115] | 182 | { |
---|
[518] | 183 | if (m_special) m_special->AddDirty(x1, y1, x2, y2); |
---|
[115] | 184 | } |
---|
| 185 | void delete_dirty(int x1, int y1, int x2, int y2) |
---|
| 186 | { |
---|
[515] | 187 | if(m_special) m_special->delete_dirty(x1, y1, x2, y2); |
---|
[115] | 188 | } |
---|
[518] | 189 | void ClearDirties() |
---|
[115] | 190 | { |
---|
[518] | 191 | if (m_special) m_special->ClearDirties(); |
---|
[115] | 192 | } |
---|
| 193 | void dither(palette *pal); // use a b&w palette! |
---|
[513] | 194 | void Scale(vec2i size); |
---|
| 195 | void SetSize(vec2i size, uint8_t *page = NULL); |
---|
[115] | 196 | void flood_fill(int16_t x, int16_t y, uint8_t color); |
---|
| 197 | image *create_smooth(int16_t smoothness = 1); // 0 no smoothness |
---|
| 198 | void unpack_scanline(int16_t line, char bitsperpixel = 1); |
---|
| 199 | uint8_t brightest_color(palette *pal); |
---|
| 200 | void flip_x(); |
---|
| 201 | void flip_y(); |
---|
| 202 | uint8_t darkest_color(palette *pal, int16_t noblack = 0); |
---|
| 203 | }; |
---|
[2] | 204 | |
---|
[115] | 205 | class image_controller |
---|
| 206 | { |
---|
| 207 | public: |
---|
| 208 | image_controller() |
---|
| 209 | { |
---|
| 210 | image_init(); |
---|
| 211 | } |
---|
| 212 | ~image_controller() |
---|
| 213 | { |
---|
| 214 | image_uninit(); |
---|
| 215 | } |
---|
| 216 | }; |
---|
[2] | 217 | |
---|
[115] | 218 | #endif /* _IMAGE_HPP_ */ |
---|
[2] | 219 | |
---|