cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

paint.c (19404B)


      1#include <gb/gb.h>
      2#include <stdint.h>
      3#include <gb/drawing.h>
      4
      5#define NB_TOOLS 18
      6#define NB_DATA_TILES 48
      7
      8#define ARROW 0
      9#define PEN 1
     10#define BRUSH 2
     11#define FILL 3
     12#define ERASER 4
     13#define CROSS 5
     14
     15#define UNSELECTED 0
     16#define SELECTED 1
     17
     18#define FIRST_TOOL 0
     19#define LAST_TOOL 9
     20#define FIRST_COLOR 10
     21#define LAST_COLOR 13
     22#define FIRST_MODE 14
     23#define LAST_MODE 17
     24
     25typedef struct icon_info_
     26{
     27  uint8_t data_idx; /* Index of data in the data array */
     28  uint8_t x, y, w, h; /* Position and size (in tiles) */
     29  uint8_t up, down, left, right; /* Index of next icons (for cursor movements) */
     30  uint8_t cursor; /* Cursor associated with icon */
     31} icon_info;
     32
     33typedef struct cursor_info_
     34{
     35  uint8_t data_idx; /* Index of data in the data array */
     36  uint8_t w, h; /* Size (in tiles) */
     37  uint8_t hot_x, hot_y; /* Position of hot point, relatice to top-left of sprite (in pixels) */
     38} cursor_info;
     39
     40const icon_info icons[] =
     41{
     42  /* Pen */
     43  { 0, 0, 0, 2, 2, 10, 2, 1, 1, 1 }, /* 0 */
     44  /* Brush */
     45  { 4, 2, 0, 2, 2, 14, 3, 0, 0, 2 }, /* 1 */
     46  /* Fill */
     47  { 8, 0, 2, 2, 2, 0, 4, 3, 3, 3 }, /* 2 */
     48  /* Eraser */
     49  { 12, 2, 2, 2, 2, 1, 5, 2, 2, 4 }, /* 3 */
     50  /* Line */
     51  { 16, 0, 4, 2, 2, 2, 6, 5, 5, 5 }, /* 4 */
     52  /* Line */
     53  { 20, 2, 4, 2, 2, 3, 7, 4, 4, 5 }, /* 5 */
     54  /* Rectangle */
     55  { 24, 0, 6, 2, 2, 4, 8, 7, 7, 5 }, /* 6 */
     56  /* Oval */
     57  { 28, 2, 6, 2, 2, 5, 9, 6, 6, 5 }, /* 7 */
     58  /* Filled rectangle */
     59  { 32, 0, 8, 2, 2, 6, 10, 9, 9, 5 }, /* 8 */
     60  /* Filled oval */
     61  { 36, 2, 8, 2, 2, 7, 14, 8, 8, 5 }, /* 9 */
     62  /* Color */
     63  { 40, 0, 10, 1, 1, 8, 11, 16, 12, 0 }, /* 10 */
     64  { 41, 0, 11, 1, 1, 10, 0, 17, 13, 0 }, /* 11 */
     65  { 42, 1, 10, 1, 1, 8, 13, 10, 14, 0 }, /* 12 */
     66  { 43, 1, 11, 1, 1, 12, 0, 11, 15, 0 }, /* 13 */
     67  /* Mode */
     68  { 44, 2, 10, 1, 1, 9, 15, 12, 16, 0 }, /* 14 */
     69  { 45, 2, 11, 1, 1, 14, 1, 13, 17, 0 }, /* 15 */
     70  { 46, 3, 10, 1, 1, 9, 17, 14, 10, 0 }, /* 16 */
     71  { 47, 3, 11, 1, 1, 16, 1, 15, 11, 0 } /* 17 */
     72};
     73
     74const unsigned char data[NB_DATA_TILES][0x10] =
     75{
     76  /* Pen */
     77  { 0x00,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x01 },
     78  { 0x7E,0x02,0x7D,0x05,0x7B,0x0A,0x77,0x14,0x7F,0x18,0x7F,0x27,0x7F,0x00,0x00,0x7F },
     79  { 0x00,0x00,0xFE,0x01,0xFE,0x0D,0xF6,0x15,0xEE,0x29,0xDE,0x51,0xBE,0xA1,0x7E,0x41 },
     80  { 0xFE,0x81,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0xFD,0xFE,0x01,0x00,0xFF },
     81  /* Brush */
     82  { 0x00,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x01 },
     83  { 0x7E,0x02,0x7D,0x0D,0x7F,0x1E,0x7F,0x1E,0x7F,0x1D,0x7F,0x11,0x7F,0x00,0x00,0x7F },
     84  { 0x00,0x00,0xFE,0x01,0xFE,0x0D,0xF6,0x15,0xEE,0x29,0xDE,0x51,0xBE,0xA1,0x7E,0x41 },
     85  { 0xFE,0x81,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0xFD,0xFE,0xFD,0xFE,0x01,0x00,0xFF },
     86  /* Fill */
     87  { 0x00,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x01,0x7F,0x02,0x7E,0x0C,0x7D,0x18,0x7E,0x1D },
     88  { 0x7F,0x1B,0x7F,0x19,0x7F,0x18,0x7F,0x08,0x7F,0x08,0x7F,0x08,0x7F,0x00,0x00,0x7F },
     89  { 0x00,0x00,0xFE,0x01,0xFE,0x81,0xFE,0x41,0x7E,0x21,0xBE,0x71,0x5E,0xE9,0xAE,0xC5 },
     90  { 0x5E,0x89,0xBE,0x11,0xFE,0xA1,0xFE,0x41,0xFE,0x01,0xFE,0x01,0xFE,0x01,0x00,0xFF },
     91  /* Eraser */
     92  { 0x00,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x01,0x7E,0x02,0x7C,0x04 },
     93  { 0x78,0x08,0x7F,0x1F,0x71,0x11,0x7F,0x1F,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x00,0x7F },
     94  { 0x00,0x00,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0xF9,0x1E,0x19,0x2E,0x29,0x5E,0x51 },
     95  { 0xBE,0xA1,0x7E,0x41,0xFE,0x81,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0x00,0xFF },
     96  /* Line */
     97  { 0x00,0x00,0x7F,0x00,0x7F,0x20,0x7F,0x10,0x7F,0x08,0x7F,0x04,0x7F,0x02,0x7F,0x01 },
     98  { 0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x00,0x7F },
     99  { 0x00,0x00,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01 },
    100  { 0xFE,0x81,0xFE,0x41,0xFE,0x21,0xFE,0x11,0xFE,0x09,0xFE,0x05,0xFE,0x01,0x00,0xFF },
    101  /* Arc */
    102  { 0x00,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x1E,0x7F,0x01,0x7F,0x00,0x7F,0x00,0x7F,0x00 },
    103  { 0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x00,0x00,0x7F },
    104  { 0x00,0x00,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x81,0xFE,0x41,0xFE,0x21,0xFE,0x11 },
    105  { 0xFE,0x11,0xFE,0x09,0xFE,0x09,0xFE,0x09,0xFE,0x09,0xFE,0x01,0xFE,0x01,0x00,0xFF },
    106  /* Rectangle */
    107  { 0x00,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x3F,0x7F,0x20,0x7F,0x20,0x7F,0x20,0x7F,0x20 },
    108  { 0x7F,0x20,0x7F,0x20,0x7F,0x20,0x7F,0x20,0x7F,0x3F,0x7F,0x00,0x7F,0x00,0x00,0x7F },
    109  { 0x00,0x00,0xFE,0x01,0xFE,0x01,0xFE,0xFD,0xFE,0x05,0xFE,0x05,0xFE,0x05,0xFE,0x05 },
    110  { 0xFE,0x05,0xFE,0x05,0xFE,0x05,0xFE,0x05,0xFE,0xFD,0xFE,0x01,0xFE,0x01,0x00,0xFF },
    111  /* Oval */
    112  { 0x00,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x03,0x7F,0x0C,0x7F,0x10,0x7F,0x20,0x7F,0x20 },
    113  { 0x7F,0x20,0x7F,0x20,0x7F,0x10,0x7F,0x0C,0x7F,0x03,0x7F,0x00,0x7F,0x00,0x00,0x7F },
    114  { 0x00,0x00,0xFE,0x01,0xFE,0x01,0xFE,0xC1,0xFE,0x31,0xFE,0x09,0xFE,0x05,0xFE,0x05 },
    115  { 0xFE,0x05,0xFE,0x05,0xFE,0x09,0xFE,0x31,0xFE,0xC1,0xFE,0x01,0xFE,0x01,0x00,0xFF },
    116  /* Filled rectangle */
    117  { 0x00,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x3F,0x6A,0x3F,0x75,0x3F,0x6A,0x3F,0x75,0x3F },
    118  { 0x6A,0x3F,0x75,0x3F,0x6A,0x3F,0x75,0x3F,0x7F,0x3F,0x7F,0x00,0x7F,0x00,0x00,0x7F },
    119  { 0x00,0x00,0xFE,0x01,0xFE,0x01,0xFE,0xFD,0xAE,0xFD,0x56,0xFD,0xAE,0xFD,0x56,0xFD },
    120  { 0xAE,0xFD,0x56,0xFD,0xAE,0xFD,0x56,0xFD,0xFE,0xFD,0xFE,0x01,0xFE,0x01,0x00,0xFF },
    121  /* Filled oval */
    122  { 0x00,0x00,0x7F,0x00,0x7F,0x00,0x7F,0x03,0x7E,0x0F,0x75,0x1F,0x6A,0x3F,0x75,0x3F },
    123  { 0x6A,0x3F,0x75,0x3F,0x7A,0x1F,0x7D,0x0F,0x7F,0x03,0x7F,0x00,0x7F,0x00,0x00,0x7F },
    124  { 0x00,0x00,0xFE,0x01,0xFE,0x01,0xFE,0xC1,0xBE,0xF1,0x5E,0xF9,0xAE,0xFD,0x56,0xFD },
    125  { 0xAE,0xFD,0x56,0xFD,0xAE,0xF9,0x7E,0xF1,0xFE,0xC1,0xFE,0x01,0xFE,0x01,0x00,0xFF },
    126  /* Color */
    127  { 0x00,0x00,0x7F,0x7F,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 },
    128  { 0x40,0x7F,0x40,0x7F,0x40,0x7F,0x40,0x7F,0x40,0x7F,0x40,0x7F,0x7F,0x7F,0x00,0x7F },
    129  { 0x00,0x00,0xFE,0xFF,0xFE,0x03,0xFE,0x03,0xFE,0x03,0xFE,0x03,0xFE,0x03,0xFE,0x03 },
    130  { 0xFE,0xFF,0xFE,0xFF,0xFE,0xFF,0xFE,0xFF,0xFE,0xFF,0xFE,0xFF,0xFE,0xFF,0x00,0xFF },
    131  /* Mode */
    132  { 0x00,0x00,0x7F,0x00,0x7F,0x0C,0x7F,0x10,0x7F,0x08,0x7F,0x04,0x7F,0x18,0x7F,0x00 },
    133  { 0x7F,0x00,0x7F,0x08,0x7F,0x14,0x7F,0x14,0x7F,0x14,0x7F,0x08,0x7F,0x00,0x00,0x7F },
    134  { 0x00,0x01,0xFE,0x01,0xFE,0x29,0xFE,0x29,0xFE,0x11,0xFE,0x29,0xFE,0x29,0xFE,0x01 },
    135  { 0xFE,0x01,0xFE,0x11,0xFE,0x29,0xFE,0x39,0xFE,0x29,0xFE,0x29,0xFE,0x01,0x00,0xFF }
    136};
    137
    138const unsigned char selected_data[NB_DATA_TILES][0x10] =
    139{
    140  /* Pen */
    141  { 0xFF,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFE },
    142  { 0x81,0xFD,0x82,0xFA,0x84,0xF5,0x88,0xEB,0x80,0xE7,0x80,0xD8,0x80,0xFF,0xFF,0x80 },
    143  { 0xFF,0xFF,0x01,0xFE,0x01,0xF2,0x09,0xEA,0x11,0xD6,0x21,0xAE,0x41,0x5E,0x81,0xBE },
    144  { 0x01,0x7E,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0x02,0x01,0xFE,0xFF,0x00 },
    145  /* Brush */
    146  { 0xFF,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFE },
    147  { 0x81,0xFD,0x82,0xF2,0x80,0xE1,0x80,0xE1,0x80,0xE2,0x80,0xEE,0x80,0xFF,0xFF,0x80 },
    148  { 0xFF,0xFF,0x01,0xFE,0x01,0xF2,0x09,0xEA,0x11,0xD6,0x21,0xAE,0x41,0x5E,0x81,0xBE },
    149  { 0x01,0x7E,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0x02,0x01,0x02,0x01,0xFE,0xFF,0x00 },
    150  /* Fill */
    151  { 0xFF,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFE,0x80,0xFD,0x81,0xF3,0x82,0xE7,0x81,0xE2 },
    152  { 0x80,0xE4,0x80,0xE7,0x80,0xE7,0x80,0xF7,0x80,0xF7,0x80,0xF7,0x80,0xFF,0xFF,0x80 },
    153  { 0xFF,0xFF,0x01,0xFE,0x01,0x7E,0x01,0xBE,0x81,0xDE,0x41,0x8E,0xA1,0x16,0x51,0x3A },
    154  { 0xA1,0x76,0x41,0xEE,0x01,0x5E,0x01,0xBE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0xFF,0x00 },
    155  /* Eraser */
    156  { 0xFF,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFE,0x81,0xFD,0x83,0xFB },
    157  { 0x87,0xF7,0x80,0xE0,0x8E,0xEE,0x80,0xE0,0x80,0xFF,0x80,0xFF,0x80,0xFF,0xFF,0x80 },
    158  { 0xFF,0xFF,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0x06,0xE1,0xE6,0xD1,0xD6,0xA1,0xAE },
    159  { 0x41,0x5E,0x81,0xBE,0x01,0x7E,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0xFF,0x00 },
    160  /* Line */
    161  { 0xFF,0xFF,0x80,0xFF,0x80,0xDF,0x80,0xEF,0x80,0xF7,0x80,0xFB,0x80,0xFD,0x80,0xFE },
    162  { 0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0xFF,0x80 },
    163  { 0xFF,0xFF,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE },
    164  { 0x01,0x7E,0x01,0xBE,0x01,0xDE,0x01,0xEE,0x01,0xF6,0x01,0xFA,0x01,0xFE,0xFF,0x00 },
    165  /* Arc */
    166  { 0xFF,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xE1,0x80,0xFE,0x80,0xFF,0x80,0xFF,0x80,0xFF },
    167  { 0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFF,0xFF,0x80 },
    168  { 0xFF,0xFF,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0x7E,0x01,0xBE,0x01,0xDE,0x01,0xEE },
    169  { 0x01,0xEE,0x01,0xF6,0x01,0xF6,0x01,0xF6,0x01,0xF6,0x01,0xFE,0x01,0xFE,0xFF,0x00 },
    170  /* Rectangle */
    171  { 0xFF,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xC0,0x80,0xDF,0x80,0xDF,0x80,0xDF,0x80,0xDF },
    172  { 0x80,0xDF,0x80,0xDF,0x80,0xDF,0x80,0xDF,0x80,0xC0,0x80,0xFF,0x80,0xFF,0xFF,0x80 },
    173  { 0xFF,0xFF,0x01,0xFE,0x01,0xFE,0x01,0x02,0x01,0xFA,0x01,0xFA,0x01,0xFA,0x01,0xFA },
    174  { 0x01,0xFA,0x01,0xFA,0x01,0xFA,0x01,0xFA,0x01,0x02,0x01,0xFE,0x01,0xFE,0xFF,0x00 },
    175  /* Oval */
    176  { 0xFF,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFC,0x80,0xF3,0x80,0xEF,0x80,0xDF,0x80,0xDF },
    177  { 0x80,0xDF,0x80,0xDF,0x80,0xEF,0x80,0xF3,0x80,0xFC,0x80,0xFF,0x80,0xFF,0xFF,0x80 },
    178  { 0xFF,0xFF,0x01,0xFE,0x01,0xFE,0x01,0x3E,0x01,0xCE,0x01,0xF6,0x01,0xFA,0x01,0xFA },
    179  { 0x01,0xFA,0x01,0xFA,0x01,0xF6,0x01,0xCE,0x01,0x3E,0x01,0xFE,0x01,0xFE,0xFF,0x00 },
    180  /* Filled rectangle */
    181  { 0xFF,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xC0,0x9F,0xC0,0x9F,0xC0,0x9F,0xC0,0x9F,0xC0 },
    182  { 0x9F,0xC0,0x9F,0xC0,0x9F,0xC0,0x9F,0xC0,0x80,0xC0,0x80,0xFF,0x80,0xFF,0xFF,0x80 },
    183  { 0xFF,0xFF,0x01,0xFE,0x01,0xFE,0x01,0x02,0xF9,0x02,0xF9,0x02,0xF9,0x02,0xF9,0x02 },
    184  { 0xF9,0x02,0xF9,0x02,0xF9,0x02,0xF9,0x02,0x01,0x02,0x01,0xFE,0x01,0xFE,0xFF,0x00 },
    185  /* Filled oval */
    186  { 0xFF,0xFF,0x80,0xFF,0x80,0xFF,0x80,0xFC,0x83,0xF0,0x8F,0xE0,0x9F,0xC0,0x9F,0xC0 },
    187  { 0x9F,0xC0,0x9F,0xC0,0x8F,0xE0,0x83,0xF0,0x80,0xFC,0x80,0xFF,0x80,0xFF,0xFF,0x80 },
    188  { 0xFF,0xFF,0x01,0xFE,0x01,0xFE,0x01,0x3E,0xC1,0x0E,0xF1,0x06,0xF9,0x02,0xF9,0x02 },
    189  { 0xF9,0x02,0xF9,0x02,0xF1,0x06,0xC1,0x0E,0x01,0x3E,0x01,0xFE,0x01,0xFE,0xFF,0x00 },
    190  /* Color */
    191  { 0x00,0x00,0x7F,0x7F,0x61,0x61,0x52,0x52,0x4C,0x4C,0x4C,0x4C,0x52,0x52,0x61,0x61 },
    192  { 0x40,0x5E,0x40,0x6D,0x40,0x73,0x40,0x73,0x40,0x6D,0x40,0x5E,0x7F,0x7F,0x00,0x7F },
    193  { 0x00,0x00,0xFE,0xFF,0xFE,0x87,0xFE,0x4B,0xFE,0x33,0xFE,0x33,0xFE,0x4B,0xFE,0x87 },
    194  { 0x7A,0x7B,0xB6,0xB7,0xCE,0xCF,0xCE,0xCF,0xB6,0xB7,0x7A,0x7B,0xFE,0xFF,0x00,0xFF },
    195  /* Mode */
    196  { 0x00,0x00,0x7F,0x7F,0x73,0x73,0x6F,0x6F,0x77,0x77,0x7B,0x7B,0x67,0x67,0x7F,0x7F },
    197  { 0x7F,0x7F,0x77,0x77,0x6B,0x6B,0x6B,0x6B,0x6B,0x6B,0x77,0x77,0x7F,0x7F,0x00,0x7F },
    198  { 0x00,0x01,0xFE,0xFF,0xD6,0xD7,0xD6,0xD7,0xEE,0xEF,0xD6,0xD7,0xD6,0xD7,0xFE,0xFF },
    199  { 0xFE,0xFF,0xEE,0xEF,0xD6,0xD7,0xC6,0xC7,0xD6,0xD7,0xD6,0xD7,0xFE,0xFF,0x00,0xFF }
    200};
    201
    202const cursor_info cursors[] =
    203{
    204  /* Arrow */
    205  { 0, 1, 1, 0, 0 },
    206  /* Pen */
    207  { 1, 2, 2, 0, 15 },
    208  /* Brush */
    209  { 5, 2, 2, 0, 15 },
    210  /* Fill */
    211  { 9, 2, 2, 2, 15 },
    212  /* Eraser */
    213  { 13, 2, 2, 0, 15 },
    214  /* Cross */
    215  { 17, 2, 2, 5, 10 }
    216};
    217
    218const unsigned char cursors_data[][0x10] = {
    219  /* Arrow */
    220  { 0xFF,0x00,0xFF,0x7E,0xFF,0x7C,0xFE,0x78,0xFF,0x7C,0xFF,0x6E,0xFF,0x46,0xEF,0x00 },
    221  /* Pen */
    222  { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x00,0x07,0x01 },
    223  { 0x0F,0x02,0x1F,0x05,0x3F,0x0A,0x7F,0x14,0x7E,0x28,0xFC,0x30,0xF8,0x40,0x60,0x00 },
    224  { 0x00,0x00,0x00,0x00,0x3C,0x00,0x7C,0x18,0xFC,0x28,0xFC,0x50,0xF8,0xA0,0xF0,0x40 },
    225  { 0xE0,0x80,0xC0,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
    226  /* Brush */
    227  { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x00,0x07,0x01,0x0F,0x02 },
    228  { 0x1F,0x05,0x7F,0x0A,0xFF,0x34,0xFE,0x78,0xFC,0x78,0xFC,0x70,0xF8,0x40,0x60,0x00 },
    229  { 0x00,0x00,0x00,0x00,0x78,0x00,0xF8,0x30,0xF8,0x50,0xF8,0xA0,0xF0,0x40,0xE0,0x80 },
    230  { 0xC0,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
    231  /* Fill */
    232  { 0x00,0x00,0x00,0x00,0x07,0x00,0x0F,0x02,0x1F,0x05,0x7F,0x08,0xFE,0x31,0xFD,0x63 },
    233  { 0xFA,0x77,0xFD,0x6E,0xFF,0x64,0xFF,0x62,0xF7,0x21,0x73,0x20,0x70,0x20,0x50,0x00 },
    234  { 0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xC0,0x00,0xE0,0x80,0xF0,0xC0,0x78,0xA0 },
    235  { 0xF8,0x10,0xF8,0x20,0xF0,0x40,0xE0,0x80,0xC0,0x00,0x80,0x00,0x00,0x00,0x00,0x00 },
    236  /* Eraser */
    237  { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x0F,0x03 },
    238  { 0x1F,0x04,0x3F,0x08,0x7F,0x11,0xFF,0x22,0xFF,0x7D,0xFF,0x46,0xFF,0x7C,0x7E,0x00 },
    239  { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0xF0,0xE0 },
    240  { 0xF0,0x60,0xF0,0xA0,0xF0,0x40,0xE0,0x80,0xC0,0x00,0x80,0x00,0x00,0x00,0x00,0x00 },
    241  /* Cross */
    242  { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x0E,0x04,0x0E,0x04 },
    243  { 0x0E,0x04,0xFF,0x04,0xFB,0x7B,0xFF,0x04,0x0E,0x04,0x0E,0x04,0x0E,0x04,0x0E,0x00 },
    244  { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
    245  { 0x00,0x00,0xE0,0x00,0xE0,0xC0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
    246};
    247
    248unsigned char data_buffer[NB_DATA_TILES][0x10];
    249
    250const uint8_t colors[] = { WHITE, DKGREY, LTGREY, BLACK };
    251const uint8_t modes[] = { SOLID, OR, XOR, AND };
    252
    253uint8_t current_tool;
    254uint8_t current_color;
    255uint8_t current_mode;
    256uint8_t current_cursor;
    257uint8_t menu_cursor_pos;
    258
    259uint8_t cursor_x;
    260uint8_t cursor_y;
    261
    262void set_cursor()
    263{
    264    uint8_t x, y, i;
    265
    266    i = 0;
    267    for(x = 0; x < cursors[current_cursor].w; x++)
    268	for(y = 0; y < cursors[current_cursor].h; y++) {
    269	    set_sprite_data(i,
    270			    1,
    271			    cursors_data[cursors[current_cursor].data_idx+i]);
    272	    set_sprite_tile(i, i);
    273	    set_sprite_prop(i, 0x10);
    274	    i++;
    275	}
    276    /* Hide unused sprites */
    277    for(; i < 4; i++) {
    278	move_sprite(i, 0, 0);
    279    }
    280}
    281
    282void move_cursor()
    283{
    284  uint8_t x, y;
    285
    286  for(x = 0; x < cursors[current_cursor].w; x++)
    287    for(y = 0; y < cursors[current_cursor].h; y++)
    288      move_sprite((x<<1)+y,
    289		  cursor_x+8 - cursors[current_cursor].hot_x + (x<<3),
    290		  cursor_y+16 - cursors[current_cursor].hot_y + (y<<3));
    291}
    292
    293void move_menu_cursor()
    294{
    295  move_sprite(0,
    296	      ((icons[menu_cursor_pos].x+icons[menu_cursor_pos].w)<<3) + 4,
    297	      ((icons[menu_cursor_pos].y+icons[menu_cursor_pos].h)<<3) + 12);
    298}
    299
    300void set_icon(uint8_t icon, uint8_t selected)
    301{
    302    uint8_t x, y;
    303
    304    for(x = 0; x < icons[icon].w; x++)
    305	for(y = 0; y < icons[icon].h; y++) {
    306	    uint16_t index = icons[icon].data_idx+((uint16_t)x<<1)+y;
    307	    switch_data(icons[icon].x + x,
    308			icons[icon].y + y,
    309			selected ? selected_data[index] : data[index],
    310			data_buffer[index]);
    311	}
    312}
    313
    314void change_icon(uint8_t icon, uint8_t selected)
    315{
    316  uint8_t x, y;
    317
    318  for(x = 0; x < icons[icon].w; x++)
    319    for(y = 0; y < icons[icon].h; y++)
    320      switch_data(icons[icon].x + x,
    321		  icons[icon].y + y,
    322		  (selected ?
    323		   selected_data[icons[icon].data_idx+((uint16_t)x<<1)+y] :
    324		   data[icons[icon].data_idx+((uint16_t)x<<1)+y]),
    325		  NULL);
    326}
    327
    328void reset_icon(uint8_t icon)
    329{
    330  uint8_t x, y;
    331
    332  for(x = 0; x < icons[icon].w; x++)
    333    for(y = 0; y < icons[icon].h; y++)
    334      switch_data(icons[icon].x + x,
    335		  icons[icon].y + y,
    336		  data_buffer[icons[icon].data_idx+(x<<1)+y],
    337		  NULL);
    338}
    339
    340void splash()
    341{
    342  uint8_t x, y;
    343
    344  cursor_x = 40;
    345  cursor_y = 50;
    346  current_cursor = PEN;
    347  set_cursor();
    348  move_cursor();
    349  SHOW_SPRITES;
    350
    351  for(; cursor_x < 120; cursor_x++) {
    352    wait_vbl_done();
    353    move_cursor();
    354    plot(cursor_x, cursor_y, BLACK, SOLID);
    355  }
    356  for(; cursor_y < 94; cursor_y++) {
    357    wait_vbl_done();
    358    move_cursor();
    359    plot(cursor_x, cursor_y, BLACK, SOLID);
    360  }
    361  for(; cursor_x > 40; cursor_x--) {
    362    wait_vbl_done();
    363    move_cursor();
    364    plot(cursor_x, cursor_y, BLACK, SOLID);
    365  }
    366  for(; cursor_y > 50; cursor_y--) {
    367    wait_vbl_done();
    368    move_cursor();
    369    plot(cursor_x, cursor_y, BLACK, SOLID);
    370  }
    371  cursor_x = 160/2;
    372  cursor_y = 144/2;
    373  current_cursor = FILL;
    374  set_cursor();
    375  move_cursor();
    376
    377  for(y = 51; y < 94; y++)
    378    for(x = 41; x < 120; x++)
    379      plot(x, y, LTGREY, SOLID);
    380
    381  // HIDE_SPRITES;
    382}
    383
    384void menu()
    385{
    386  uint8_t i, key;
    387  uint8_t slowdown;
    388  uint8_t cursor;
    389
    390  slowdown = 50;
    391
    392  for(i = 0; i < NB_TOOLS; i++)
    393    set_icon(i,
    394	     i == FIRST_TOOL + current_tool ||
    395	     i == FIRST_COLOR + current_color ||
    396	     i == FIRST_MODE + current_mode);
    397
    398  cursor = current_cursor;
    399  current_cursor = ARROW;
    400  set_cursor();
    401  move_menu_cursor();
    402  SHOW_SPRITES;
    403  waitpadup();
    404  do {
    405    wait_vbl_done();
    406    key = joypad();
    407    if(key & (J_UP|J_DOWN|J_LEFT|J_RIGHT)) {
    408      if(key & J_UP)
    409	menu_cursor_pos = icons[menu_cursor_pos].up;
    410      if(key & J_DOWN)
    411	menu_cursor_pos = icons[menu_cursor_pos].down;
    412      if(key & J_LEFT)
    413	menu_cursor_pos = icons[menu_cursor_pos].left;
    414      if(key & J_RIGHT)
    415	menu_cursor_pos = icons[menu_cursor_pos].right;
    416      move_menu_cursor();
    417      while(slowdown && key == joypad()) {
    418	wait_vbl_done();
    419	slowdown--;
    420      }
    421      slowdown = 10;
    422    } else
    423      slowdown = 50;
    424    if(key & J_A) {
    425      if( /* menu_cursor_pos >= FIRST_TOOL && */ menu_cursor_pos <= LAST_TOOL) {
    426	if(menu_cursor_pos != /* FIRST_TOOL + */ current_tool) {
    427	  change_icon(/* FIRST_TOOL + */ current_tool, UNSELECTED);
    428	  current_tool = menu_cursor_pos /* - FIRST_TOOL */;
    429	  change_icon(/* FIRST_TOOL + */ current_tool, SELECTED);
    430	  cursor = icons[/* FIRST_TOOL + */ current_tool].cursor;
    431	}
    432      } else if(menu_cursor_pos >= FIRST_COLOR && menu_cursor_pos <= LAST_COLOR) {
    433	if(menu_cursor_pos != FIRST_COLOR + current_color) {
    434	  change_icon(FIRST_COLOR + current_color, UNSELECTED);
    435	  current_color = menu_cursor_pos - FIRST_COLOR;
    436	  change_icon(FIRST_COLOR + current_color, SELECTED);
    437	}
    438      } else if(menu_cursor_pos >= FIRST_MODE && menu_cursor_pos <= LAST_MODE) {
    439	if(menu_cursor_pos != FIRST_MODE + current_mode) {
    440	  change_icon(FIRST_MODE + current_mode, UNSELECTED);
    441	  current_mode = menu_cursor_pos - FIRST_MODE;
    442	  change_icon(FIRST_MODE + current_mode, SELECTED);
    443	}
    444      }
    445    }
    446  } while(key != J_SELECT);
    447  waitpadup();
    448  for(i = 0; i < NB_TOOLS; i++)
    449    reset_icon(i);
    450  HIDE_SPRITES;
    451  current_cursor = cursor;
    452}
    453
    454void run()
    455{
    456  uint8_t key;
    457  uint8_t slowdown;
    458  uint8_t drawn, erased;
    459
    460  slowdown = 10;
    461  drawn = erased = 0;
    462
    463  set_cursor();
    464  move_cursor();
    465  SHOW_SPRITES;
    466
    467  while(1) {
    468    wait_vbl_done();
    469    key = joypad();
    470    if(key & (J_UP|J_DOWN|J_LEFT|J_RIGHT)) {
    471      if(key & J_UP && cursor_y > 0)
    472	cursor_y--;
    473      if(key & J_DOWN && cursor_y < 143)
    474	cursor_y++;
    475      if(key & J_LEFT && cursor_x > 0)
    476	cursor_x--;
    477      if(key & J_RIGHT && cursor_x < 159)
    478	cursor_x++;
    479      move_cursor();
    480      while(slowdown && key == joypad()) {
    481	wait_vbl_done();
    482	slowdown--;
    483      }
    484      slowdown = 1;
    485      drawn = erased = 0;
    486    } else
    487      slowdown = 10;
    488    if(key & J_SELECT) {
    489      HIDE_SPRITES;
    490      menu();
    491      set_cursor();
    492      move_cursor();
    493      SHOW_SPRITES;
    494    }
    495    if((key & (J_A|J_B)) == J_A) {
    496      if(!drawn) {
    497	drawn++;
    498	plot(cursor_x, cursor_y, colors[current_color], modes[current_mode]);
    499      }
    500    } else
    501      drawn = 0;
    502    if((key & (J_A|J_B)) == J_B) {
    503      if(!erased) {
    504	erased++;
    505	plot(cursor_x, cursor_y, WHITE, SOLID);
    506      }
    507    } else
    508      erased = 0;
    509  }
    510}
    511
    512void main()
    513{
    514  /* Initialize sprite palette */
    515  OBP1_REG = 0xE0U;
    516
    517  splash();
    518
    519  current_tool = 0;
    520  current_color = BLACK;
    521  current_mode = SOLID;
    522  current_cursor = PEN;
    523  menu_cursor_pos = 0;
    524  cursor_x = 160/2;
    525  cursor_y = 144/2;
    526
    527  run();
    528}