#include #include #include #include #include #include #include #include #include // Moving the VIC into the third bank and making // room for double buffering+ byte * const Screen0 = (byte *)0xc800; byte * const Screen1 = (byte *)0xcc00; byte * const Font = (byte *)0xd000; byte * const Color = (byte *)0xd800; byte * const Color1 = (byte *)0xc400; // Just to get started a mini maze static const char * maze[16] = { "################", "#..........#...#", "#.###.####.###.#", "#........#.#.#.#", "##.#####.###.#.#", "#..#......##.#.#", "#.##.####......#", "#.#.....#.####.#", "#.#####.#....#.#", "#.......######.#", "#.##.####......#", "#.#..##...####.#", "#.##....#....#.#", "#.#####.######.#", "#..............#", "################", }; // Character set including some ramps for the upper edge char charset[2048] = { #embed "../resources/maze3dchars.bin" }; // Current target screen char * DrawScreen; // Current target index bool FlipIndex; // Position and direction inside the maze sbyte px = 1, py = 3, dx = 1, dy = 0; // Distance of blocks to the side, relative to the center ot the screen // for full and half step static const char zxdist0[] = {18, 6, 4, 3, 2, 1, 0}; static const char zxdist1[] = { 9, 5, 3, 2, 1, 0, 0}; // Flip double buffer, copying the color ram void screen_flip(void) { // Change idnex of screen FlipIndex = !FlipIndex; // Wait until raster beam reaches bottom vic_waitBottom(); // Change vic start address vic_setmode(VICM_TEXT, FlipIndex ? Screen0 : Screen1, Font); // Copy the color ram in four chunks, to avoid // colliding with the beam char i = 0; do { Color[0x000 + i] = Color1[0x000 + i]; i++; } while (i != 0); do { Color[0x100 + i] = Color1[0x100 + i]; i++; } while (i != 0); do { Color[0x200 + i] = Color1[0x200 + i]; i++; } while (i != 0); do { Color[0x300 + i] = Color1[0x300 + i]; i++; } while (i != 0); // Change target buffer for next frame DrawScreen = FlipIndex ? Screen1 : Screen0; } // Rotating left or right is simulated by scrolling. For // performance reasons, we have four different scroll routines // due to two buffers and two directions // Loop over the two buffers #assign si 0 #repeat // other buffer #assign ri 1 - si // pointers of the two screen buffers, from and to #define dst Screen##si #define src Screen##ri // scroll left Screen0 or Screen1 void screen_left_##si(void) { for(char sx=0; sx<40; sx+=4) { // Wait for the beam to be just below the first line vic_waitLine(58); // Unroll for each row of screen and color ram #assign ry 0 #repeat // Copy one row by four chars for(char x=0; x<36; x++) { dst[40 * ry + x] = dst[40 * ry + x + 4]; Color[40 * ry + x] = Color[40 * ry + x + 4]; } // Fill in new screen and color data dst[40 * ry + 36] = src[40 * ry + sx + 0]; dst[40 * ry + 37] = src[40 * ry + sx + 1]; dst[40 * ry + 38] = src[40 * ry + sx + 2]; dst[40 * ry + 39] = src[40 * ry + sx + 3]; Color[40 * ry + 36] = Color1[40 * ry + sx + 0]; Color[40 * ry + 37] = Color1[40 * ry + sx + 1]; Color[40 * ry + 38] = Color1[40 * ry + sx + 2]; Color[40 * ry + 39] = Color1[40 * ry + sx + 3]; // repeat for each row #assign ry ry + 1 #until ry == 25 #undef ry } } // scroll right Screen0 or Screen1 void screen_right_##si(void) { for(char sx=40; sx>0; sx-=4) { vic_waitLine(58); #assign ry 0 #repeat for(char x=39; x>=4; x--) { dst[40 * ry + x] = dst[40 * ry - 4 + x]; Color[40 * ry + x] = Color[40 * ry - 4 + x]; } dst[40 * ry + 0] = src[40 * ry + sx - 4]; dst[40 * ry + 1] = src[40 * ry + sx - 3]; dst[40 * ry + 2] = src[40 * ry + sx - 2]; dst[40 * ry + 3] = src[40 * ry + sx - 1]; Color[40 * ry + 0] = Color1[40 * ry + sx - 4]; Color[40 * ry + 1] = Color1[40 * ry + sx - 3]; Color[40 * ry + 2] = Color1[40 * ry + sx - 2]; Color[40 * ry + 3] = Color1[40 * ry + sx - 1]; #assign ry ry + 1 #until ry == 25 #undef ry } } #assign si si + 1 #until si == 2 #undef si #undef ri // Scroll current screen left void screen_left(void) { if (FlipIndex) screen_left_0(); else screen_left_1(); } // Scroll current screen right void screen_right(void) { if (FlipIndex) screen_right_0(); else screen_right_1(); } // Fill one color column void color_column(char cx, char color) { #assign ry 0 #repeat Color1[40 * ry + cx] = color; #assign ry ry + 1 #until ry == 25 #undef ry } // Fill one screen column void screen_column(char cx, char sx, char tc, char mc, char bc) { // Calculate top and bottom row char ty = sx / 4; char by = 25 - sx; // Target pointer char * dp = DrawScreen + cx; // Check for non empty column if (by > ty) { // Space above for(char cy=0; cy 0 ? VCOL_LT_GREY : VCOL_DARK_GREY; } // Start position of player sbyte ix = px, iy = py; // Starting at first screen column sbyte sx = 0; for(char i=0; i<7; i++) { // Next screen column sbyte tx = 20 - zxdist[i]; // View blocked by wall if (maze[iy][ix] == '#') { // Fill with wall color for(char cx=sx; cx<40-sx; cx++) { color_column(cx, cfront); screen_column(cx, sx, 96 + (sx & 3), 96, 96); } // And be done return ; } // Check for left wall if (maze[iy - dx][ix + dy] == '#') { // Draw left wall for(char cx=sx; cx