Retro Invaders a space invaders clone by Chris Favreau. Written for the RetroMbuino development board from outrageouscircuits.com for the game programming contest.

Dependencies:   mbed

This is a space invaders clone written for the Retro Mbuino from outrageous circuits.

Development board: http://www.outrageouscircuits.com/shop/product/15 ).

The game itself is basic space invaders. Shoot them before they get to the bottom of the screen. It has a UFO saucer which you can shoot for extra points. You get 4 shields and each shield can be hit up to 4 times before it is gone. Hmm... as each level increases the speed of the invaders shots goes up. The invaders only speed up when there is less of them. You complete the level when you shoot all the invaders. The game ends when a) you run out of lives (you start with 3) or the invaders get to the bottom.

The LEDs turned out to be a pretty cool addition to the game. I wrote a class that blinks them and turns them on for a specified amount of time. They add a nice extra to the game. I use them on the intro screen and when the UFO is present.

The sound turned out to be really difficult for a few reasons. The biggest was that I had never written a sound engine before. The interrupt service routine working off the timer was the easier part. I also had a lot of trouble because there is no filter to filter out the PWM frequency to the speaker... so I had to run the PWM frequency way up there 30 kHz.

The graphics turned out to be a bit of a bear too. Thanks to Chris Taylor for his really great LCD API. I picked up a couple of frames per second from that. I had modified the DisplayN18 class for blitting a single line buffer to the LCD panel however his is a little faster for some reason? I used a different approach to doing the graphics (as I have very little experience with anything other than double buffered displays). I have a tile map and a list of sprites. Each tile/sprite is 1 bit 8x8. They could be bigger. I ran out of time. That much is not special. What is different from what I can tell is that I use a 1 line buffer that is 160 shorts long. The render function first adds the tile map data into the line buffer first. Then the sprites are added over the existing data. You can have a great deal of different sprites and maps going to the screen and just have to rewrite the LCD memory once per frame. After each line is composited, the line is then drawn to the LCD. Kind of like an Atari 2600. Each sprite/tile has a foreground and background color and can be different from the other tiles/sprites. There is one color reserved for Transparency.

There are 16 colors to choose from. I chose a palette based on the Macintosh OS 4.1 palette I found on WikiPedia. It is a very nice mix of colors.

I found a sprite editor called SpriteX ( https://code.google.com/p/spritesx-ed/ )... it works nicely except that the 16x16 sprites are in a weird format. Time limited me to 8x8 sprites. Oh well.

I used nokring to make the music. It makes RTTTL formatted ring tones which my sound api can play. Here is a useful site that has lots of arcade/video game ring tones with a link to nokring in the utilities page. http://arcadetones.emuunlim.com/files.htm

Other than all that stuff I used state machines to do most of the game logic. Please excuse the horrible coding as I tried to comment a lot of it however it is not very nice to look at. Lots of long functions...

Committer:
cfavreau
Date:
Tue Mar 03 04:26:01 2015 +0000
Revision:
0:c79e1f29f029
Retro Invaders by Chris Favreau for the RetroMbuino Platform - outrageouscircuits.com game programming contest.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
cfavreau 0:c79e1f29f029 1 #include <stdarg.h> // va_list
cfavreau 0:c79e1f29f029 2 #include "display.h"
cfavreau 0:c79e1f29f029 3 #include "font8x8.h" // default 8x8 bitmap font
cfavreau 0:c79e1f29f029 4 #include "colors.h" // predefined colors
cfavreau 0:c79e1f29f029 5
cfavreau 0:c79e1f29f029 6 #define COLOR(fore, back) ((fore << 4) | (back & 0x0F))
cfavreau 0:c79e1f29f029 7
cfavreau 0:c79e1f29f029 8 display::display() : LCD_ST7735(P0_19, P0_20, P0_7, P0_21, P0_22, P1_15, P0_2, LCD_ST7735::RGB)
cfavreau 0:c79e1f29f029 9 {
cfavreau 0:c79e1f29f029 10 // Fill out the default color palette - use the MSX/Coleco default 16 color palette
cfavreau 0:c79e1f29f029 11 // Found them here: http://theadamresource.com/articles/misc/wk970202.html
cfavreau 0:c79e1f29f029 12 memset(m_color_pal, 0, COLOR_PAL_LEN * sizeof(uint16_t));
cfavreau 0:c79e1f29f029 13 /*
cfavreau 0:c79e1f29f029 14 m_color_pal[0] = RGB2SHORT(0, 0, 0); // BLACK - Transparent (support in display code)
cfavreau 0:c79e1f29f029 15 m_color_pal[1] = RGB2SHORT(0, 0, 0); // BLACK - Opaque
cfavreau 0:c79e1f29f029 16 m_color_pal[2] = RGB2SHORT(71, 183, 59); // Medium Green
cfavreau 0:c79e1f29f029 17 m_color_pal[3] = RGB2SHORT(124, 207, 111); // Light Green
cfavreau 0:c79e1f29f029 18 m_color_pal[4] = RGB2SHORT(93, 18, 255); // Dark Blue
cfavreau 0:c79e1f29f029 19 m_color_pal[5] = RGB2SHORT(128, 114, 255); // Light Blue
cfavreau 0:c79e1f29f029 20 m_color_pal[6] = RGB2SHORT(182, 91, 71); // Dark Red (maybe brown)
cfavreau 0:c79e1f29f029 21 m_color_pal[7] = RGB2SHORT(93, 200, 237); // Cyan
cfavreau 0:c79e1f29f029 22 m_color_pal[8] = RGB2SHORT(215, 107, 72); // Medium Red
cfavreau 0:c79e1f29f029 23 m_color_pal[9] = RGB2SHORT(251, 143, 108); // Light Red
cfavreau 0:c79e1f29f029 24 m_color_pal[10] = RGB2SHORT(195, 205, 65); // Dark Yellow
cfavreau 0:c79e1f29f029 25 m_color_pal[11] = RGB2SHORT(211, 218, 118); // Light Yellow
cfavreau 0:c79e1f29f029 26 m_color_pal[12] = RGB2SHORT(62, 159, 47); // Dark Green
cfavreau 0:c79e1f29f029 27 m_color_pal[13] = RGB2SHORT(182, 100, 199); // Magenta
cfavreau 0:c79e1f29f029 28 m_color_pal[14] = RGB2SHORT(204, 204, 204); // Grey
cfavreau 0:c79e1f29f029 29 m_color_pal[15] = RGB2SHORT(255, 255, 255); // White
cfavreau 0:c79e1f29f029 30 */
cfavreau 0:c79e1f29f029 31 /*
cfavreau 0:c79e1f29f029 32 m_color_pal[0] = RGB2SHORT(0, 0, 0); // BLACK - Transparent (support in display code)
cfavreau 0:c79e1f29f029 33 m_color_pal[1] = RGB2SHORT(0, 0, 0); // BLACK - Opaque
cfavreau 0:c79e1f29f029 34 m_color_pal[2] = RGB2SHORT(32, 192, 32); // Medium Green
cfavreau 0:c79e1f29f029 35 m_color_pal[3] = RGB2SHORT(96, 224, 96); // Light Green
cfavreau 0:c79e1f29f029 36 m_color_pal[4] = RGB2SHORT(32, 32, 224); // Dark Blue
cfavreau 0:c79e1f29f029 37 m_color_pal[5] = RGB2SHORT(64, 96, 224); // Light Blue
cfavreau 0:c79e1f29f029 38 m_color_pal[6] = RGB2SHORT(160, 32, 32); // Dark Red (maybe brown)
cfavreau 0:c79e1f29f029 39 m_color_pal[7] = RGB2SHORT(64, 192, 224); // Cyan
cfavreau 0:c79e1f29f029 40 m_color_pal[8] = RGB2SHORT(224, 32, 32); // Medium Red
cfavreau 0:c79e1f29f029 41 m_color_pal[9] = RGB2SHORT(224, 96, 96); // Light Red
cfavreau 0:c79e1f29f029 42 m_color_pal[10] = RGB2SHORT(192, 192, 32); // Dark Yellow
cfavreau 0:c79e1f29f029 43 m_color_pal[11] = RGB2SHORT(192, 192, 128); // Light Yellow
cfavreau 0:c79e1f29f029 44 m_color_pal[12] = RGB2SHORT(32, 128, 32); // Dark Green
cfavreau 0:c79e1f29f029 45 m_color_pal[13] = RGB2SHORT(192, 64, 160); // Magenta
cfavreau 0:c79e1f29f029 46 m_color_pal[14] = RGB2SHORT(160, 160, 160); // Grey
cfavreau 0:c79e1f29f029 47 m_color_pal[15] = RGB2SHORT(255, 255, 255); // White
cfavreau 0:c79e1f29f029 48 */
cfavreau 0:c79e1f29f029 49
cfavreau 0:c79e1f29f029 50 // Mac OS4.1 16 Color Palette (modified for transparent)
cfavreau 0:c79e1f29f029 51 // Found here: http://upload.wikimedia.org/wikipedia/commons/5/57/Mac_16colors_palette.png
cfavreau 0:c79e1f29f029 52 m_color_pal[0] = RGB2SHORT(255, 255, 255); // White
cfavreau 0:c79e1f29f029 53 m_color_pal[1] = RGB2SHORT(255, 255, 0); // Yellow
cfavreau 0:c79e1f29f029 54 m_color_pal[2] = RGB2SHORT(255, 102, 0); // Orange
cfavreau 0:c79e1f29f029 55 m_color_pal[3] = RGB2SHORT(255, 0, 0); // Red
cfavreau 0:c79e1f29f029 56 m_color_pal[4] = RGB2SHORT(255, 0, 103); // Magenta
cfavreau 0:c79e1f29f029 57 m_color_pal[5] = RGB2SHORT(51, 0, 153); // Dark Blue
cfavreau 0:c79e1f29f029 58 m_color_pal[6] = RGB2SHORT(0, 0, 204); // Blue
cfavreau 0:c79e1f29f029 59 m_color_pal[7] = RGB2SHORT(0, 153, 255); // Light Blue
cfavreau 0:c79e1f29f029 60 m_color_pal[8] = RGB2SHORT(0, 255, 0); // Green
cfavreau 0:c79e1f29f029 61 m_color_pal[9] = RGB2SHORT(0, 102, 0); // Dark Green
cfavreau 0:c79e1f29f029 62 m_color_pal[10] = RGB2SHORT(102, 51, 0); // Brown
cfavreau 0:c79e1f29f029 63 m_color_pal[11] = RGB2SHORT(153, 102, 51); // Light Brown
cfavreau 0:c79e1f29f029 64 m_color_pal[12] = RGB2SHORT(187, 187, 187); // Light Grey
cfavreau 0:c79e1f29f029 65 m_color_pal[13] = RGB2SHORT(136, 136, 136); // Grey
cfavreau 0:c79e1f29f029 66 m_color_pal[14] = RGB2SHORT(0, 0, 0); // White
cfavreau 0:c79e1f29f029 67 m_color_pal[15] = RGB2SHORT(0, 0, 0); // Transparent (black)
cfavreau 0:c79e1f29f029 68
cfavreau 0:c79e1f29f029 69 // Allocate our line buffer
cfavreau 0:c79e1f29f029 70 m_line_buffer = new uint8_t[LINE_BUFFER_LEN];
cfavreau 0:c79e1f29f029 71
cfavreau 0:c79e1f29f029 72 // Set our default colors
cfavreau 0:c79e1f29f029 73 m_fore_color = PAL_WHITE;
cfavreau 0:c79e1f29f029 74 m_back_color = PAL_TRANSPARENT;
cfavreau 0:c79e1f29f029 75
cfavreau 0:c79e1f29f029 76 clear();
cfavreau 0:c79e1f29f029 77
cfavreau 0:c79e1f29f029 78 // Initialize our sprite list
cfavreau 0:c79e1f29f029 79 for (int i = 0; i < MAX_SPRITES; i++)
cfavreau 0:c79e1f29f029 80 memset(&sprite_list[i], 0, sizeof(SPRITE));
cfavreau 0:c79e1f29f029 81
cfavreau 0:c79e1f29f029 82 // Clear our user character buffer
cfavreau 0:c79e1f29f029 83 memset(user_char, 0, MAX_USER_CHAR_BUF_LEN);
cfavreau 0:c79e1f29f029 84 }
cfavreau 0:c79e1f29f029 85
cfavreau 0:c79e1f29f029 86 display::~display()
cfavreau 0:c79e1f29f029 87 {
cfavreau 0:c79e1f29f029 88 }
cfavreau 0:c79e1f29f029 89
cfavreau 0:c79e1f29f029 90 void display::clear()
cfavreau 0:c79e1f29f029 91 {
cfavreau 0:c79e1f29f029 92 // Clear our character map buffer
cfavreau 0:c79e1f29f029 93 memset(m_char_map, 0, CHAR_MAP_LEN);
cfavreau 0:c79e1f29f029 94 // Clear our color map buffer
cfavreau 0:c79e1f29f029 95 memset(m_color_map, COLOR(m_fore_color, m_back_color), CHAR_MAP_LEN);
cfavreau 0:c79e1f29f029 96
cfavreau 0:c79e1f29f029 97 // Set the cursor position back to 0
cfavreau 0:c79e1f29f029 98 m_cursor_x = 0;
cfavreau 0:c79e1f29f029 99 m_cursor_y = 0;
cfavreau 0:c79e1f29f029 100 }
cfavreau 0:c79e1f29f029 101
cfavreau 0:c79e1f29f029 102 void display::bounds_check_and_scroll()
cfavreau 0:c79e1f29f029 103 {
cfavreau 0:c79e1f29f029 104 // Check to see if our Y cursor location is beyond our map height
cfavreau 0:c79e1f29f029 105 if (m_cursor_y >= CHAR_MAP_HEIGHT)
cfavreau 0:c79e1f29f029 106 {
cfavreau 0:c79e1f29f029 107 // Check to see if we are
cfavreau 0:c79e1f29f029 108 // Scroll everything up 1 line
cfavreau 0:c79e1f29f029 109 memcpy(m_char_map, &m_char_map[CHAR_MAP_WIDTH], CHAR_MAP_LAST_LINE);
cfavreau 0:c79e1f29f029 110 memcpy(m_color_map, &m_color_map[CHAR_MAP_WIDTH], CHAR_MAP_LAST_LINE);
cfavreau 0:c79e1f29f029 111 // Clear the bottom line
cfavreau 0:c79e1f29f029 112 memset(&m_char_map[CHAR_MAP_LAST_LINE], 0, CHAR_MAP_WIDTH);
cfavreau 0:c79e1f29f029 113 memset(&m_color_map[CHAR_MAP_LAST_LINE], COLOR(m_fore_color, m_back_color), CHAR_MAP_WIDTH);
cfavreau 0:c79e1f29f029 114 // Put the position of the cursor on the last line
cfavreau 0:c79e1f29f029 115 m_cursor_y = CHAR_MAP_HEIGHT - 1;
cfavreau 0:c79e1f29f029 116 m_cursor_x = 0;
cfavreau 0:c79e1f29f029 117 }
cfavreau 0:c79e1f29f029 118 }
cfavreau 0:c79e1f29f029 119
cfavreau 0:c79e1f29f029 120 void display::crlf()
cfavreau 0:c79e1f29f029 121 {
cfavreau 0:c79e1f29f029 122 // Advance our cursor to the next line
cfavreau 0:c79e1f29f029 123 m_cursor_x = 0;
cfavreau 0:c79e1f29f029 124 m_cursor_y++;
cfavreau 0:c79e1f29f029 125 }
cfavreau 0:c79e1f29f029 126
cfavreau 0:c79e1f29f029 127 void display::print(char *pString)
cfavreau 0:c79e1f29f029 128 {
cfavreau 0:c79e1f29f029 129 // Bounds check the cursor position (and do scrolling if we need to)
cfavreau 0:c79e1f29f029 130 // before we put any characters in the map
cfavreau 0:c79e1f29f029 131 bounds_check_and_scroll();
cfavreau 0:c79e1f29f029 132
cfavreau 0:c79e1f29f029 133 // Calculate the current linear cursor position
cfavreau 0:c79e1f29f029 134 int pos = get_linear_cursor_pos();
cfavreau 0:c79e1f29f029 135
cfavreau 0:c79e1f29f029 136 // Loop through the string and put it into the character map
cfavreau 0:c79e1f29f029 137 while (*pString)
cfavreau 0:c79e1f29f029 138 {
cfavreau 0:c79e1f29f029 139 char character = *pString;
cfavreau 0:c79e1f29f029 140
cfavreau 0:c79e1f29f029 141 /*
cfavreau 0:c79e1f29f029 142 // Handle a carriage return
cfavreau 0:c79e1f29f029 143 if (character == 10)
cfavreau 0:c79e1f29f029 144 {
cfavreau 0:c79e1f29f029 145 m_cursor_x = 0;
cfavreau 0:c79e1f29f029 146 pos = get_linear_cursor_pos();
cfavreau 0:c79e1f29f029 147 }
cfavreau 0:c79e1f29f029 148 else
cfavreau 0:c79e1f29f029 149 // Handle a line feed
cfavreau 0:c79e1f29f029 150 if (character == 13)
cfavreau 0:c79e1f29f029 151 {
cfavreau 0:c79e1f29f029 152 m_cursor_y++;
cfavreau 0:c79e1f29f029 153 bounds_check_and_scroll();
cfavreau 0:c79e1f29f029 154 pos = get_linear_cursor_pos();
cfavreau 0:c79e1f29f029 155 }
cfavreau 0:c79e1f29f029 156 else
cfavreau 0:c79e1f29f029 157 */
cfavreau 0:c79e1f29f029 158 {
cfavreau 0:c79e1f29f029 159 if ((character < 32) || (character > 126))
cfavreau 0:c79e1f29f029 160 {
cfavreau 0:c79e1f29f029 161 // Some other special character
cfavreau 0:c79e1f29f029 162 character = 95; // substitue a solid block if there is a special character
cfavreau 0:c79e1f29f029 163 }
cfavreau 0:c79e1f29f029 164 else
cfavreau 0:c79e1f29f029 165 {
cfavreau 0:c79e1f29f029 166 // Just subtract out the special character offset
cfavreau 0:c79e1f29f029 167 character -= 32;
cfavreau 0:c79e1f29f029 168 }
cfavreau 0:c79e1f29f029 169
cfavreau 0:c79e1f29f029 170 // Place the character into the map
cfavreau 0:c79e1f29f029 171 m_char_map[pos] = character;
cfavreau 0:c79e1f29f029 172 // Copy the forecolor into the map
cfavreau 0:c79e1f29f029 173 m_color_map[pos] = COLOR(m_fore_color, m_back_color);
cfavreau 0:c79e1f29f029 174 // Next linear position
cfavreau 0:c79e1f29f029 175 pos++;
cfavreau 0:c79e1f29f029 176 // Advance the cursor position
cfavreau 0:c79e1f29f029 177 m_cursor_x++;
cfavreau 0:c79e1f29f029 178 if (m_cursor_x >= CHAR_MAP_WIDTH)
cfavreau 0:c79e1f29f029 179 {
cfavreau 0:c79e1f29f029 180 if (m_word_wrap)
cfavreau 0:c79e1f29f029 181 {
cfavreau 0:c79e1f29f029 182 // Next line
cfavreau 0:c79e1f29f029 183 crlf();
cfavreau 0:c79e1f29f029 184 pos = get_linear_cursor_pos();
cfavreau 0:c79e1f29f029 185 }
cfavreau 0:c79e1f29f029 186 else
cfavreau 0:c79e1f29f029 187 {
cfavreau 0:c79e1f29f029 188 // Stop putting the characters in the map
cfavreau 0:c79e1f29f029 189 // we have hit the end of the line
cfavreau 0:c79e1f29f029 190 break;
cfavreau 0:c79e1f29f029 191 }
cfavreau 0:c79e1f29f029 192
cfavreau 0:c79e1f29f029 193 }
cfavreau 0:c79e1f29f029 194 }
cfavreau 0:c79e1f29f029 195 // Next character
cfavreau 0:c79e1f29f029 196 pString++;
cfavreau 0:c79e1f29f029 197 }
cfavreau 0:c79e1f29f029 198 }
cfavreau 0:c79e1f29f029 199
cfavreau 0:c79e1f29f029 200 void display::print(int iNumber)
cfavreau 0:c79e1f29f029 201 {
cfavreau 0:c79e1f29f029 202 char sTemp[CHAR_MAP_WIDTH];
cfavreau 0:c79e1f29f029 203 snprintf(sTemp, CHAR_MAP_WIDTH, "%d", iNumber);
cfavreau 0:c79e1f29f029 204 print(sTemp);
cfavreau 0:c79e1f29f029 205 }
cfavreau 0:c79e1f29f029 206
cfavreau 0:c79e1f29f029 207 void display::print(float fNumber)
cfavreau 0:c79e1f29f029 208 {
cfavreau 0:c79e1f29f029 209 char sTemp[CHAR_MAP_WIDTH];
cfavreau 0:c79e1f29f029 210 snprintf(sTemp, CHAR_MAP_WIDTH, "%0.2f", fNumber);
cfavreau 0:c79e1f29f029 211 print(sTemp);
cfavreau 0:c79e1f29f029 212 }
cfavreau 0:c79e1f29f029 213
cfavreau 0:c79e1f29f029 214 void display::print(const char *format, ...)
cfavreau 0:c79e1f29f029 215 {
cfavreau 0:c79e1f29f029 216 char sTemp[CHAR_MAP_WIDTH];
cfavreau 0:c79e1f29f029 217
cfavreau 0:c79e1f29f029 218 va_list list;
cfavreau 0:c79e1f29f029 219 va_start(list, format);
cfavreau 0:c79e1f29f029 220
cfavreau 0:c79e1f29f029 221 // Print something in the file
cfavreau 0:c79e1f29f029 222 vsnprintf(sTemp, CHAR_MAP_WIDTH, format, list);
cfavreau 0:c79e1f29f029 223
cfavreau 0:c79e1f29f029 224 print(sTemp);
cfavreau 0:c79e1f29f029 225 }
cfavreau 0:c79e1f29f029 226
cfavreau 0:c79e1f29f029 227 void display::println(char *pString)
cfavreau 0:c79e1f29f029 228 {
cfavreau 0:c79e1f29f029 229 print(pString);
cfavreau 0:c79e1f29f029 230 crlf();
cfavreau 0:c79e1f29f029 231
cfavreau 0:c79e1f29f029 232 }
cfavreau 0:c79e1f29f029 233
cfavreau 0:c79e1f29f029 234 void display::println(int iNumber)
cfavreau 0:c79e1f29f029 235 {
cfavreau 0:c79e1f29f029 236 print(iNumber);
cfavreau 0:c79e1f29f029 237 crlf();
cfavreau 0:c79e1f29f029 238 }
cfavreau 0:c79e1f29f029 239
cfavreau 0:c79e1f29f029 240 void display::println(float fNumber)
cfavreau 0:c79e1f29f029 241 {
cfavreau 0:c79e1f29f029 242 print(fNumber);
cfavreau 0:c79e1f29f029 243 crlf();
cfavreau 0:c79e1f29f029 244 }
cfavreau 0:c79e1f29f029 245
cfavreau 0:c79e1f29f029 246 void display::println(const char *format, ...)
cfavreau 0:c79e1f29f029 247 {
cfavreau 0:c79e1f29f029 248 char sTemp[CHAR_MAP_WIDTH];
cfavreau 0:c79e1f29f029 249
cfavreau 0:c79e1f29f029 250 va_list list;
cfavreau 0:c79e1f29f029 251 va_start(list, format);
cfavreau 0:c79e1f29f029 252
cfavreau 0:c79e1f29f029 253 // Print something in the file
cfavreau 0:c79e1f29f029 254 vsnprintf(sTemp, CHAR_MAP_WIDTH, format, list);
cfavreau 0:c79e1f29f029 255
cfavreau 0:c79e1f29f029 256 println(sTemp);
cfavreau 0:c79e1f29f029 257 }
cfavreau 0:c79e1f29f029 258
cfavreau 0:c79e1f29f029 259 void display::printat(uint8_t x, uint8_t y, char *pString)
cfavreau 0:c79e1f29f029 260 {
cfavreau 0:c79e1f29f029 261 // Bounds check the coordinates
cfavreau 0:c79e1f29f029 262 if (x >= CHAR_MAP_WIDTH) return;
cfavreau 0:c79e1f29f029 263 if (y >= CHAR_MAP_HEIGHT) return;
cfavreau 0:c79e1f29f029 264
cfavreau 0:c79e1f29f029 265 // Get the starting linear position
cfavreau 0:c79e1f29f029 266 int pos = get_linear_pos(x, y);
cfavreau 0:c79e1f29f029 267
cfavreau 0:c79e1f29f029 268 // Loop through the string and put it into the character map
cfavreau 0:c79e1f29f029 269 while (*pString)
cfavreau 0:c79e1f29f029 270 {
cfavreau 0:c79e1f29f029 271 char character = *pString;
cfavreau 0:c79e1f29f029 272
cfavreau 0:c79e1f29f029 273 // Ignore CR and LF
cfavreau 0:c79e1f29f029 274 if ((character == 10) || (character == 13))
cfavreau 0:c79e1f29f029 275 {
cfavreau 0:c79e1f29f029 276 pString++;
cfavreau 0:c79e1f29f029 277 continue;
cfavreau 0:c79e1f29f029 278 }
cfavreau 0:c79e1f29f029 279
cfavreau 0:c79e1f29f029 280 if ((character < 32) || (character > 126))
cfavreau 0:c79e1f29f029 281 {
cfavreau 0:c79e1f29f029 282 // Some other special character
cfavreau 0:c79e1f29f029 283 character = 95; // substitue a solid block if there is a special character
cfavreau 0:c79e1f29f029 284 }
cfavreau 0:c79e1f29f029 285 else
cfavreau 0:c79e1f29f029 286 {
cfavreau 0:c79e1f29f029 287 // Just subtract out the special character offset
cfavreau 0:c79e1f29f029 288 character -= 32;
cfavreau 0:c79e1f29f029 289 }
cfavreau 0:c79e1f29f029 290
cfavreau 0:c79e1f29f029 291 // Place the character into the map
cfavreau 0:c79e1f29f029 292 m_char_map[pos] = character;
cfavreau 0:c79e1f29f029 293 // Copy the forecolor into the map
cfavreau 0:c79e1f29f029 294 m_color_map[pos] = COLOR(m_fore_color, m_back_color);
cfavreau 0:c79e1f29f029 295 // Next linear position
cfavreau 0:c79e1f29f029 296 pos++;
cfavreau 0:c79e1f29f029 297 // Advance the cursor position
cfavreau 0:c79e1f29f029 298 x++;
cfavreau 0:c79e1f29f029 299 // Check for out of bounds in which case we just exit
cfavreau 0:c79e1f29f029 300 if (x >= CHAR_MAP_WIDTH) return;
cfavreau 0:c79e1f29f029 301 if (pos >= CHAR_MAP_LEN) return;
cfavreau 0:c79e1f29f029 302 // Next character
cfavreau 0:c79e1f29f029 303 pString++;
cfavreau 0:c79e1f29f029 304 }
cfavreau 0:c79e1f29f029 305 }
cfavreau 0:c79e1f29f029 306
cfavreau 0:c79e1f29f029 307 void display::printat(uint8_t x, uint8_t y, int iNumber)
cfavreau 0:c79e1f29f029 308 {
cfavreau 0:c79e1f29f029 309 char sTemp[CHAR_MAP_WIDTH];
cfavreau 0:c79e1f29f029 310 snprintf(sTemp, CHAR_MAP_WIDTH, "%d", iNumber);
cfavreau 0:c79e1f29f029 311 printat(x, y, sTemp);
cfavreau 0:c79e1f29f029 312 }
cfavreau 0:c79e1f29f029 313
cfavreau 0:c79e1f29f029 314 void display::printat(uint8_t x, uint8_t y, float fNumber)
cfavreau 0:c79e1f29f029 315 {
cfavreau 0:c79e1f29f029 316 char sTemp[CHAR_MAP_WIDTH];
cfavreau 0:c79e1f29f029 317 snprintf(sTemp, CHAR_MAP_WIDTH, "%0.2f", fNumber);
cfavreau 0:c79e1f29f029 318 printat(x, y, sTemp);
cfavreau 0:c79e1f29f029 319 }
cfavreau 0:c79e1f29f029 320
cfavreau 0:c79e1f29f029 321 void display::printat(uint8_t x, uint8_t y, const char *format, ...)
cfavreau 0:c79e1f29f029 322 {
cfavreau 0:c79e1f29f029 323 char sTemp[CHAR_MAP_WIDTH];
cfavreau 0:c79e1f29f029 324
cfavreau 0:c79e1f29f029 325 va_list list;
cfavreau 0:c79e1f29f029 326 va_start(list, format);
cfavreau 0:c79e1f29f029 327
cfavreau 0:c79e1f29f029 328 // Print something in the file
cfavreau 0:c79e1f29f029 329 vsnprintf(sTemp, CHAR_MAP_WIDTH, format, list);
cfavreau 0:c79e1f29f029 330
cfavreau 0:c79e1f29f029 331 printat(x, y, sTemp);
cfavreau 0:c79e1f29f029 332 }
cfavreau 0:c79e1f29f029 333
cfavreau 0:c79e1f29f029 334 void display::setcharat(uint8_t x, uint8_t y, uint8_t character, uint8_t fore_color, uint8_t back_color)
cfavreau 0:c79e1f29f029 335 {
cfavreau 0:c79e1f29f029 336 // Bounds check the coordinates
cfavreau 0:c79e1f29f029 337 if (x >= CHAR_MAP_WIDTH) return;
cfavreau 0:c79e1f29f029 338 if (y >= CHAR_MAP_HEIGHT) return;
cfavreau 0:c79e1f29f029 339
cfavreau 0:c79e1f29f029 340 // Get the starting linear position
cfavreau 0:c79e1f29f029 341 int pos = get_linear_pos(x, y);
cfavreau 0:c79e1f29f029 342
cfavreau 0:c79e1f29f029 343 // Place the character into the map
cfavreau 0:c79e1f29f029 344 m_char_map[pos] = character;
cfavreau 0:c79e1f29f029 345
cfavreau 0:c79e1f29f029 346 // Check the colors
cfavreau 0:c79e1f29f029 347 if (fore_color >= 16) fore_color = m_fore_color;
cfavreau 0:c79e1f29f029 348 if (back_color >= 16) back_color = m_back_color;
cfavreau 0:c79e1f29f029 349
cfavreau 0:c79e1f29f029 350 // Copy the forecolor into the map
cfavreau 0:c79e1f29f029 351 m_color_map[pos] = COLOR(fore_color, back_color);
cfavreau 0:c79e1f29f029 352
cfavreau 0:c79e1f29f029 353 }
cfavreau 0:c79e1f29f029 354
cfavreau 0:c79e1f29f029 355 void display::blit_line(uint8_t line)
cfavreau 0:c79e1f29f029 356 {
cfavreau 0:c79e1f29f029 357 if (line >= LCD_HEIGHT) return;
cfavreau 0:c79e1f29f029 358
cfavreau 0:c79e1f29f029 359 // LCD_ST7735
cfavreau 0:c79e1f29f029 360 clip(0, line, 159, 0);
cfavreau 0:c79e1f29f029 361 write(0x2C, m_line_buffer, LINE_BUFFER_LEN);
cfavreau 0:c79e1f29f029 362
cfavreau 0:c79e1f29f029 363 // DisplayN18
cfavreau 0:c79e1f29f029 364 //setClippingArea(0, line, 159, 0);
cfavreau 0:c79e1f29f029 365 //writeCommand(0x2C);
cfavreau 0:c79e1f29f029 366 //writeData(m_line_buffer, LINE_BUFFER_LEN);
cfavreau 0:c79e1f29f029 367 }
cfavreau 0:c79e1f29f029 368
cfavreau 0:c79e1f29f029 369 void display::render()
cfavreau 0:c79e1f29f029 370 {
cfavreau 0:c79e1f29f029 371 uint16_t *line_buf = (uint16_t *)m_line_buffer;
cfavreau 0:c79e1f29f029 372 uint8_t *char_buf = font8x8_basic;
cfavreau 0:c79e1f29f029 373 register uint8_t data = 0;
cfavreau 0:c79e1f29f029 374
cfavreau 0:c79e1f29f029 375 int cindex = 0;
cfavreau 0:c79e1f29f029 376 int char_line = 0;
cfavreau 0:c79e1f29f029 377 int line_x = 0;
cfavreau 0:c79e1f29f029 378
cfavreau 0:c79e1f29f029 379 for (int line = 0; line < LCD_HEIGHT; line++)
cfavreau 0:c79e1f29f029 380 {
cfavreau 0:c79e1f29f029 381 line_x = 0;
cfavreau 0:c79e1f29f029 382 cindex = (line >> 3) * CHAR_MAP_WIDTH;
cfavreau 0:c79e1f29f029 383 for (int map_x = 0; map_x < CHAR_MAP_WIDTH; map_x++)
cfavreau 0:c79e1f29f029 384 {
cfavreau 0:c79e1f29f029 385 register uint8_t data_index = m_char_map[cindex];
cfavreau 0:c79e1f29f029 386 if (data_index < 128)
cfavreau 0:c79e1f29f029 387 data = char_buf[(data_index << 3) + char_line];
cfavreau 0:c79e1f29f029 388 else
cfavreau 0:c79e1f29f029 389 data = user_char[((data_index - 128) << 3) + char_line];
cfavreau 0:c79e1f29f029 390 register uint16_t fore_color = m_color_pal[m_color_map[cindex] >> 4];
cfavreau 0:c79e1f29f029 391 register uint16_t back_color = m_color_pal[(m_color_map[cindex] & 0x0F)];
cfavreau 0:c79e1f29f029 392 line_buf[line_x++] = (data & 0x01) ? fore_color : back_color;
cfavreau 0:c79e1f29f029 393 line_buf[line_x++] = (data & 0x02) ? fore_color : back_color;
cfavreau 0:c79e1f29f029 394 line_buf[line_x++] = (data & 0x04) ? fore_color : back_color;
cfavreau 0:c79e1f29f029 395 line_buf[line_x++] = (data & 0x08) ? fore_color : back_color;
cfavreau 0:c79e1f29f029 396 line_buf[line_x++] = (data & 0x10) ? fore_color : back_color;
cfavreau 0:c79e1f29f029 397 line_buf[line_x++] = (data & 0x20) ? fore_color : back_color;
cfavreau 0:c79e1f29f029 398 line_buf[line_x++] = (data & 0x40) ? fore_color : back_color;
cfavreau 0:c79e1f29f029 399 line_buf[line_x++] = (data & 0x80) ? fore_color : back_color;
cfavreau 0:c79e1f29f029 400 // Next character in our map
cfavreau 0:c79e1f29f029 401 cindex++;
cfavreau 0:c79e1f29f029 402 }
cfavreau 0:c79e1f29f029 403
cfavreau 0:c79e1f29f029 404 char_line++;
cfavreau 0:c79e1f29f029 405 if (char_line >= CHAR_HEIGHT) char_line = 0;
cfavreau 0:c79e1f29f029 406
cfavreau 0:c79e1f29f029 407 // Add in the sprites ... they are the TOP layer
cfavreau 0:c79e1f29f029 408 for (int iSprite = 0; iSprite < MAX_SPRITES; iSprite++)
cfavreau 0:c79e1f29f029 409 {
cfavreau 0:c79e1f29f029 410 // Check to see if the sprite is enabled
cfavreau 0:c79e1f29f029 411 if (!sprite_list[iSprite].enabled) continue;
cfavreau 0:c79e1f29f029 412
cfavreau 0:c79e1f29f029 413 // Check to see if the sprite is within our current line
cfavreau 0:c79e1f29f029 414 if (line < sprite_list[iSprite].y) continue;
cfavreau 0:c79e1f29f029 415 if (line >= (sprite_list[iSprite].y + 8)) continue;
cfavreau 0:c79e1f29f029 416
cfavreau 0:c79e1f29f029 417 // Get the row of the sprite we are blitting
cfavreau 0:c79e1f29f029 418 register uint8_t row = line - sprite_list[iSprite].y;
cfavreau 0:c79e1f29f029 419 // Get the x position
cfavreau 0:c79e1f29f029 420 register uint8_t x = sprite_list[iSprite].x;
cfavreau 0:c79e1f29f029 421 // Get the foreground color
cfavreau 0:c79e1f29f029 422 register uint16_t fc = m_color_pal[sprite_list[iSprite].fore_color];
cfavreau 0:c79e1f29f029 423 register uint16_t bc = m_color_pal[sprite_list[iSprite].back_color];
cfavreau 0:c79e1f29f029 424 // Get the starting index for the sprite into the user character buffer
cfavreau 0:c79e1f29f029 425 register uint8_t data = user_char[(sprite_list[iSprite].char_index << 3) + row];
cfavreau 0:c79e1f29f029 426
cfavreau 0:c79e1f29f029 427 if (sprite_list[iSprite].back_color != PAL_TRANSPARENT)
cfavreau 0:c79e1f29f029 428 {
cfavreau 0:c79e1f29f029 429 line_buf[x] = (data & 0x01) ? fc : bc; x++;
cfavreau 0:c79e1f29f029 430 line_buf[x] = (data & 0x02) ? fc : bc; x++;
cfavreau 0:c79e1f29f029 431 line_buf[x] = (data & 0x04) ? fc : bc; x++;
cfavreau 0:c79e1f29f029 432 line_buf[x] = (data & 0x08) ? fc : bc; x++;
cfavreau 0:c79e1f29f029 433 line_buf[x] = (data & 0x10) ? fc : bc; x++;
cfavreau 0:c79e1f29f029 434 line_buf[x] = (data & 0x20) ? fc : bc; x++;
cfavreau 0:c79e1f29f029 435 line_buf[x] = (data & 0x40) ? fc : bc; x++;
cfavreau 0:c79e1f29f029 436 line_buf[x] = (data & 0x80) ? fc : bc; x++;
cfavreau 0:c79e1f29f029 437 }
cfavreau 0:c79e1f29f029 438 else
cfavreau 0:c79e1f29f029 439 {
cfavreau 0:c79e1f29f029 440 if (data & 0x01) line_buf[x] = fc; x++;
cfavreau 0:c79e1f29f029 441 if (data & 0x02) line_buf[x] = fc; x++;
cfavreau 0:c79e1f29f029 442 if (data & 0x04) line_buf[x] = fc; x++;
cfavreau 0:c79e1f29f029 443 if (data & 0x08) line_buf[x] = fc; x++;
cfavreau 0:c79e1f29f029 444 if (data & 0x10) line_buf[x] = fc; x++;
cfavreau 0:c79e1f29f029 445 if (data & 0x20) line_buf[x] = fc; x++;
cfavreau 0:c79e1f29f029 446 if (data & 0x40) line_buf[x] = fc; x++;
cfavreau 0:c79e1f29f029 447 if (data & 0x80) line_buf[x] = fc; x++;
cfavreau 0:c79e1f29f029 448 }
cfavreau 0:c79e1f29f029 449 }
cfavreau 0:c79e1f29f029 450
cfavreau 0:c79e1f29f029 451 // Draw the line
cfavreau 0:c79e1f29f029 452 blit_line(line);
cfavreau 0:c79e1f29f029 453 }
cfavreau 0:c79e1f29f029 454 }
cfavreau 0:c79e1f29f029 455
cfavreau 0:c79e1f29f029 456 void display::AddSprite(int iSpriteNum, int iChar, int x, int y, int fore_color, int back_color, bool midhandle)
cfavreau 0:c79e1f29f029 457 {
cfavreau 0:c79e1f29f029 458 if (iSpriteNum < 0) return;
cfavreau 0:c79e1f29f029 459 if (iSpriteNum >= MAX_SPRITES) return;
cfavreau 0:c79e1f29f029 460 if (iChar >= MAX_USER_CHAR) return;
cfavreau 0:c79e1f29f029 461
cfavreau 0:c79e1f29f029 462 sprite_list[iSpriteNum].char_index = iChar;
cfavreau 0:c79e1f29f029 463 sprite_list[iSpriteNum].x = x;
cfavreau 0:c79e1f29f029 464 sprite_list[iSpriteNum].y = y;
cfavreau 0:c79e1f29f029 465 sprite_list[iSpriteNum].fore_color = fore_color;
cfavreau 0:c79e1f29f029 466 sprite_list[iSpriteNum].back_color = back_color;
cfavreau 0:c79e1f29f029 467 sprite_list[iSpriteNum].midhandle = midhandle;
cfavreau 0:c79e1f29f029 468
cfavreau 0:c79e1f29f029 469 // CHeck to see if we treat the X and Y coordinates as the middle of the sprite...
cfavreau 0:c79e1f29f029 470 if (midhandle)
cfavreau 0:c79e1f29f029 471 {
cfavreau 0:c79e1f29f029 472 // Redo the XY coordinates
cfavreau 0:c79e1f29f029 473 SetSpritePos(iSpriteNum, x, y);
cfavreau 0:c79e1f29f029 474 }
cfavreau 0:c79e1f29f029 475
cfavreau 0:c79e1f29f029 476 // Set the enabled flag last just in case we get called from an interrupt or we are interrupted
cfavreau 0:c79e1f29f029 477 sprite_list[iSpriteNum].enabled = true;
cfavreau 0:c79e1f29f029 478 }
cfavreau 0:c79e1f29f029 479
cfavreau 0:c79e1f29f029 480 void display::EnableSprite(int iSpriteNum, bool bEnable)
cfavreau 0:c79e1f29f029 481 {
cfavreau 0:c79e1f29f029 482 if (iSpriteNum < 0) return;
cfavreau 0:c79e1f29f029 483 if (iSpriteNum >= MAX_SPRITES) return;
cfavreau 0:c79e1f29f029 484
cfavreau 0:c79e1f29f029 485 sprite_list[iSpriteNum].enabled = bEnable;
cfavreau 0:c79e1f29f029 486 }
cfavreau 0:c79e1f29f029 487
cfavreau 0:c79e1f29f029 488 void display::RemoveSprite(int iSpriteNum)
cfavreau 0:c79e1f29f029 489 {
cfavreau 0:c79e1f29f029 490 EnableSprite(iSpriteNum, false);
cfavreau 0:c79e1f29f029 491 }
cfavreau 0:c79e1f29f029 492
cfavreau 0:c79e1f29f029 493 void display::SetSpriteChar(int iSpriteNum, int iChar)
cfavreau 0:c79e1f29f029 494 {
cfavreau 0:c79e1f29f029 495 if (iSpriteNum < 0) return;
cfavreau 0:c79e1f29f029 496 if (iSpriteNum >= MAX_SPRITES) return;
cfavreau 0:c79e1f29f029 497 if (iChar >= MAX_USER_CHAR) return;
cfavreau 0:c79e1f29f029 498
cfavreau 0:c79e1f29f029 499 sprite_list[iSpriteNum].char_index = iChar;
cfavreau 0:c79e1f29f029 500 }
cfavreau 0:c79e1f29f029 501
cfavreau 0:c79e1f29f029 502 void display::SetSpritePos(int iSpriteNum, int x, int y)
cfavreau 0:c79e1f29f029 503 {
cfavreau 0:c79e1f29f029 504 if (iSpriteNum < 0) return;
cfavreau 0:c79e1f29f029 505 if (iSpriteNum >= MAX_SPRITES) return;
cfavreau 0:c79e1f29f029 506
cfavreau 0:c79e1f29f029 507 if (sprite_list[iSpriteNum].midhandle)
cfavreau 0:c79e1f29f029 508 {
cfavreau 0:c79e1f29f029 509 x -= 4;
cfavreau 0:c79e1f29f029 510 y -= 4;
cfavreau 0:c79e1f29f029 511 }
cfavreau 0:c79e1f29f029 512
cfavreau 0:c79e1f29f029 513 sprite_list[iSpriteNum].x = x;
cfavreau 0:c79e1f29f029 514 sprite_list[iSpriteNum].y = y;
cfavreau 0:c79e1f29f029 515 }
cfavreau 0:c79e1f29f029 516
cfavreau 0:c79e1f29f029 517 void display::SetSpriteColor(int iSpriteNum, int fore_color, int back_color)
cfavreau 0:c79e1f29f029 518 {
cfavreau 0:c79e1f29f029 519 if (iSpriteNum < 0) return;
cfavreau 0:c79e1f29f029 520 if (iSpriteNum >= MAX_SPRITES) return;
cfavreau 0:c79e1f29f029 521
cfavreau 0:c79e1f29f029 522 sprite_list[iSpriteNum].fore_color = fore_color;
cfavreau 0:c79e1f29f029 523 sprite_list[iSpriteNum].back_color = back_color;
cfavreau 0:c79e1f29f029 524 }
cfavreau 0:c79e1f29f029 525
cfavreau 0:c79e1f29f029 526 void display::SetMidHandle(int iSpriteNum, bool bEnable)
cfavreau 0:c79e1f29f029 527 {
cfavreau 0:c79e1f29f029 528 if (iSpriteNum < 0) return;
cfavreau 0:c79e1f29f029 529 if (iSpriteNum >= MAX_SPRITES) return;
cfavreau 0:c79e1f29f029 530
cfavreau 0:c79e1f29f029 531 sprite_list[iSpriteNum].midhandle = bEnable;
cfavreau 0:c79e1f29f029 532 }
cfavreau 0:c79e1f29f029 533
cfavreau 0:c79e1f29f029 534 void display::SetCustomChar(int iCharNum, uint8_t *pBuf, int iNum, bool isMSX)
cfavreau 0:c79e1f29f029 535 {
cfavreau 0:c79e1f29f029 536 if (iCharNum >= MAX_USER_CHAR) return;
cfavreau 0:c79e1f29f029 537 if ((iNum + iCharNum) > MAX_USER_CHAR) return;
cfavreau 0:c79e1f29f029 538
cfavreau 0:c79e1f29f029 539 for (int i = 0; i < iNum; i++)
cfavreau 0:c79e1f29f029 540 {
cfavreau 0:c79e1f29f029 541 if (isMSX)
cfavreau 0:c79e1f29f029 542 SetCustomChar8x8MSX(iCharNum + i, pBuf);
cfavreau 0:c79e1f29f029 543 else
cfavreau 0:c79e1f29f029 544 SetCustomChar8x8Norm(iCharNum + i, pBuf);
cfavreau 0:c79e1f29f029 545 pBuf += 8;
cfavreau 0:c79e1f29f029 546 }
cfavreau 0:c79e1f29f029 547 }
cfavreau 0:c79e1f29f029 548
cfavreau 0:c79e1f29f029 549 void display::SetCustomChar8x8Norm(int iCharNum, uint8_t *pBuf)
cfavreau 0:c79e1f29f029 550 {
cfavreau 0:c79e1f29f029 551 if (iCharNum >= MAX_USER_CHAR) return;
cfavreau 0:c79e1f29f029 552
cfavreau 0:c79e1f29f029 553 memcpy(&user_char[iCharNum * 8], pBuf, 8);
cfavreau 0:c79e1f29f029 554 }
cfavreau 0:c79e1f29f029 555
cfavreau 0:c79e1f29f029 556 void display::SetCustomChar8x8MSX(int iCharNum, uint8_t *pBuf)
cfavreau 0:c79e1f29f029 557 {
cfavreau 0:c79e1f29f029 558 if (iCharNum >= MAX_USER_CHAR) return;
cfavreau 0:c79e1f29f029 559
cfavreau 0:c79e1f29f029 560 // 8x8 MSX tiles have the bit order reversed
cfavreau 0:c79e1f29f029 561 for (int i = 0; i < 8; i++)
cfavreau 0:c79e1f29f029 562 {
cfavreau 0:c79e1f29f029 563 uint8_t temp2 = 0;
cfavreau 0:c79e1f29f029 564 uint8_t temp1 = pBuf[i];
cfavreau 0:c79e1f29f029 565 for (int bit = 0; bit < 8; bit++)
cfavreau 0:c79e1f29f029 566 {
cfavreau 0:c79e1f29f029 567 temp2 = temp2 << 1;
cfavreau 0:c79e1f29f029 568 temp2 |= (temp1 & 0x01);
cfavreau 0:c79e1f29f029 569 temp1 = temp1 >> 1;
cfavreau 0:c79e1f29f029 570 }
cfavreau 0:c79e1f29f029 571 user_char[iCharNum * 8 + i] = temp2;
cfavreau 0:c79e1f29f029 572 }
cfavreau 0:c79e1f29f029 573 }
cfavreau 0:c79e1f29f029 574
cfavreau 0:c79e1f29f029 575 void display::set_map(uint8_t char_index, uint8_t x, uint8_t y, uint8_t fore_color, uint8_t back_color)
cfavreau 0:c79e1f29f029 576 {
cfavreau 0:c79e1f29f029 577 if (x >= CHAR_MAP_WIDTH) return;
cfavreau 0:c79e1f29f029 578 if (y >= CHAR_MAP_HEIGHT) return;
cfavreau 0:c79e1f29f029 579
cfavreau 0:c79e1f29f029 580 int pos = get_linear_pos(x, y);
cfavreau 0:c79e1f29f029 581
cfavreau 0:c79e1f29f029 582 m_char_map[pos] = char_index;
cfavreau 0:c79e1f29f029 583 m_color_map[pos] = COLOR(fore_color, back_color);
cfavreau 0:c79e1f29f029 584
cfavreau 0:c79e1f29f029 585 }
cfavreau 0:c79e1f29f029 586
cfavreau 0:c79e1f29f029 587 void display::set_map_info(uint16_t tile_info, uint8_t x, uint8_t y)
cfavreau 0:c79e1f29f029 588 {
cfavreau 0:c79e1f29f029 589 if (x >= CHAR_MAP_WIDTH) return;
cfavreau 0:c79e1f29f029 590 if (y >= CHAR_MAP_HEIGHT) return;
cfavreau 0:c79e1f29f029 591
cfavreau 0:c79e1f29f029 592 int pos = get_linear_pos(x, y);
cfavreau 0:c79e1f29f029 593
cfavreau 0:c79e1f29f029 594 m_char_map[pos] = (tile_info >> 8);
cfavreau 0:c79e1f29f029 595 m_color_map[pos] = (tile_info & 0x00FF);
cfavreau 0:c79e1f29f029 596 }
cfavreau 0:c79e1f29f029 597
cfavreau 0:c79e1f29f029 598 uint8_t display::get_map(uint8_t x, uint8_t y)
cfavreau 0:c79e1f29f029 599 {
cfavreau 0:c79e1f29f029 600 return (get_map_info(x, y) >> 8);
cfavreau 0:c79e1f29f029 601 }
cfavreau 0:c79e1f29f029 602
cfavreau 0:c79e1f29f029 603 uint8_t display::get_map_color(uint8_t x, uint8_t y)
cfavreau 0:c79e1f29f029 604 {
cfavreau 0:c79e1f29f029 605 return (get_map_info(x, y) & 0x00FF);
cfavreau 0:c79e1f29f029 606 }
cfavreau 0:c79e1f29f029 607
cfavreau 0:c79e1f29f029 608 uint16_t display::get_map_info(uint8_t x, uint8_t y)
cfavreau 0:c79e1f29f029 609 {
cfavreau 0:c79e1f29f029 610 if (x >= CHAR_MAP_WIDTH) return 0;
cfavreau 0:c79e1f29f029 611 if (y >= CHAR_MAP_HEIGHT) return 0;
cfavreau 0:c79e1f29f029 612
cfavreau 0:c79e1f29f029 613 int pos = get_linear_pos(x, y);
cfavreau 0:c79e1f29f029 614
cfavreau 0:c79e1f29f029 615 return ((m_char_map[pos] << 8) | m_color_map[pos]);
cfavreau 0:c79e1f29f029 616 }
cfavreau 0:c79e1f29f029 617
cfavreau 0:c79e1f29f029 618 void display::shift_map(SHIFT_DIRECTION direction, int inc, bool clear_after_shift)
cfavreau 0:c79e1f29f029 619 {
cfavreau 0:c79e1f29f029 620 switch (direction)
cfavreau 0:c79e1f29f029 621 {
cfavreau 0:c79e1f29f029 622 case (eShiftUp):
cfavreau 0:c79e1f29f029 623 for (int i = 1; i < CHAR_MAP_HEIGHT; i++)
cfavreau 0:c79e1f29f029 624 {
cfavreau 0:c79e1f29f029 625 memcpy(&m_char_map[(i - 1) * CHAR_MAP_WIDTH], &m_char_map[i * CHAR_MAP_WIDTH], CHAR_MAP_WIDTH);
cfavreau 0:c79e1f29f029 626 memcpy(&m_color_map[(i - 1) * CHAR_MAP_WIDTH], &m_color_map[i * CHAR_MAP_WIDTH], CHAR_MAP_WIDTH);
cfavreau 0:c79e1f29f029 627 }
cfavreau 0:c79e1f29f029 628 if (clear_after_shift)
cfavreau 0:c79e1f29f029 629 {
cfavreau 0:c79e1f29f029 630 // Clear the bottom row
cfavreau 0:c79e1f29f029 631 memset(&m_char_map[CHAR_MAP_HEIGHT - 1], 0, CHAR_MAP_WIDTH);
cfavreau 0:c79e1f29f029 632 memset(&m_color_map[CHAR_MAP_HEIGHT - 1], COLOR(m_fore_color, m_back_color), CHAR_MAP_WIDTH);
cfavreau 0:c79e1f29f029 633 }
cfavreau 0:c79e1f29f029 634 break;
cfavreau 0:c79e1f29f029 635 case (eShiftDown):
cfavreau 0:c79e1f29f029 636 for (int i = (CHAR_MAP_HEIGHT - 1); i > 0; i--)
cfavreau 0:c79e1f29f029 637 {
cfavreau 0:c79e1f29f029 638 memcpy(&m_char_map[i * CHAR_MAP_WIDTH], &m_char_map[(i - 1) * CHAR_MAP_WIDTH], CHAR_MAP_WIDTH);
cfavreau 0:c79e1f29f029 639 memcpy(&m_color_map[i * CHAR_MAP_WIDTH], &m_color_map[(i - 1) * CHAR_MAP_WIDTH], CHAR_MAP_WIDTH);
cfavreau 0:c79e1f29f029 640 }
cfavreau 0:c79e1f29f029 641 if (clear_after_shift)
cfavreau 0:c79e1f29f029 642 {
cfavreau 0:c79e1f29f029 643 // Clear the top row
cfavreau 0:c79e1f29f029 644 memset(&m_char_map[0], 0, CHAR_MAP_WIDTH);
cfavreau 0:c79e1f29f029 645 memset(&m_color_map[0], COLOR(m_fore_color, m_back_color), CHAR_MAP_WIDTH);
cfavreau 0:c79e1f29f029 646 }
cfavreau 0:c79e1f29f029 647 break;
cfavreau 0:c79e1f29f029 648 case (eShiftLeft):
cfavreau 0:c79e1f29f029 649 for (int y = 0; y < CHAR_MAP_HEIGHT; y++)
cfavreau 0:c79e1f29f029 650 {
cfavreau 0:c79e1f29f029 651 for (int x = 1; x < CHAR_MAP_WIDTH; x++)
cfavreau 0:c79e1f29f029 652 {
cfavreau 0:c79e1f29f029 653 int pos = get_linear_pos(x, y);
cfavreau 0:c79e1f29f029 654 m_char_map[pos - 1] = m_char_map[pos];
cfavreau 0:c79e1f29f029 655 m_color_map[pos -1] = m_color_map[pos];
cfavreau 0:c79e1f29f029 656 }
cfavreau 0:c79e1f29f029 657 }
cfavreau 0:c79e1f29f029 658 if (clear_after_shift)
cfavreau 0:c79e1f29f029 659 {
cfavreau 0:c79e1f29f029 660 // Clear the right column
cfavreau 0:c79e1f29f029 661 for (int y = 0; y < CHAR_MAP_HEIGHT; y++)
cfavreau 0:c79e1f29f029 662 {
cfavreau 0:c79e1f29f029 663 m_char_map[get_linear_pos((CHAR_MAP_WIDTH - 1), y)] = 0;
cfavreau 0:c79e1f29f029 664 m_color_map[get_linear_pos((CHAR_MAP_WIDTH - 1), y)] = COLOR(m_fore_color, m_back_color);
cfavreau 0:c79e1f29f029 665 }
cfavreau 0:c79e1f29f029 666 }
cfavreau 0:c79e1f29f029 667 break;
cfavreau 0:c79e1f29f029 668 case (eShiftRight):
cfavreau 0:c79e1f29f029 669 for (int y = 0; y < CHAR_MAP_HEIGHT; y++)
cfavreau 0:c79e1f29f029 670 {
cfavreau 0:c79e1f29f029 671 for (int x = (CHAR_MAP_WIDTH - 1); x > 0; x--)
cfavreau 0:c79e1f29f029 672 {
cfavreau 0:c79e1f29f029 673 int pos = get_linear_pos(x, y);
cfavreau 0:c79e1f29f029 674 m_char_map[pos] = m_char_map[pos - 1];
cfavreau 0:c79e1f29f029 675 m_color_map[pos] = m_color_map[pos - 1];
cfavreau 0:c79e1f29f029 676 }
cfavreau 0:c79e1f29f029 677 }
cfavreau 0:c79e1f29f029 678 if (clear_after_shift)
cfavreau 0:c79e1f29f029 679 {
cfavreau 0:c79e1f29f029 680 // Clear the left column
cfavreau 0:c79e1f29f029 681 for (int y = 0; y < CHAR_MAP_HEIGHT; y++)
cfavreau 0:c79e1f29f029 682 {
cfavreau 0:c79e1f29f029 683 m_char_map[get_linear_pos(0, y)] = 0;
cfavreau 0:c79e1f29f029 684 m_color_map[get_linear_pos(0, y)] = COLOR(m_fore_color, m_back_color);
cfavreau 0:c79e1f29f029 685 }
cfavreau 0:c79e1f29f029 686 }
cfavreau 0:c79e1f29f029 687 break;
cfavreau 0:c79e1f29f029 688 }
cfavreau 0:c79e1f29f029 689 }
cfavreau 0:c79e1f29f029 690
cfavreau 0:c79e1f29f029 691 bool display::SpriteCollision(int iSpriteNum1, int iSpriteNum2)
cfavreau 0:c79e1f29f029 692 {
cfavreau 0:c79e1f29f029 693 if (iSpriteNum1 < 0) return false;
cfavreau 0:c79e1f29f029 694 if (iSpriteNum1 >= MAX_SPRITES) return false;
cfavreau 0:c79e1f29f029 695 if (iSpriteNum2 < 0) return false;
cfavreau 0:c79e1f29f029 696 if (iSpriteNum2 >= MAX_SPRITES) return false;
cfavreau 0:c79e1f29f029 697
cfavreau 0:c79e1f29f029 698 SPRITE *pSprite1 = &sprite_list[iSpriteNum1];
cfavreau 0:c79e1f29f029 699 SPRITE *pSprite2 = &sprite_list[iSpriteNum2];
cfavreau 0:c79e1f29f029 700
cfavreau 0:c79e1f29f029 701 if (!pSprite1->enabled) return false;
cfavreau 0:c79e1f29f029 702 if (!pSprite2->enabled) return false;
cfavreau 0:c79e1f29f029 703
cfavreau 0:c79e1f29f029 704 // Bounding box collision - might be broken
cfavreau 0:c79e1f29f029 705 /*
cfavreau 0:c79e1f29f029 706 int dx = pSprite1->x - pSprite2->x;
cfavreau 0:c79e1f29f029 707 if (dx < 0) dx *= -1;
cfavreau 0:c79e1f29f029 708 int dy = pSprite1->y - pSprite2->y;
cfavreau 0:c79e1f29f029 709 if (dy < 0) dy *= -1;
cfavreau 0:c79e1f29f029 710
cfavreau 0:c79e1f29f029 711 return ((dx < 16) && (dy < 16));
cfavreau 0:c79e1f29f029 712 */
cfavreau 0:c79e1f29f029 713
cfavreau 0:c79e1f29f029 714 // Circle based collision detection
cfavreau 0:c79e1f29f029 715 int dx = pSprite1->x - pSprite2->x;
cfavreau 0:c79e1f29f029 716 int dy = pSprite1->y - pSprite2->y;
cfavreau 0:c79e1f29f029 717 int dist = (dx * dx) + (dy * dy);
cfavreau 0:c79e1f29f029 718 int r = 3 + 3; // make the radius 4 - 1
cfavreau 0:c79e1f29f029 719 return (dist < (r * r));
cfavreau 0:c79e1f29f029 720
cfavreau 0:c79e1f29f029 721 // TODO - perhaps after the circle detection maybe we can do pixel perfect detection...
cfavreau 0:c79e1f29f029 722 // OR - do detection when we are rendering???
cfavreau 0:c79e1f29f029 723 }