diff options
author | Paul Duncan <pabs@pablotron.org> | 2018-06-27 21:16:17 -0400 |
---|---|---|
committer | Paul Duncan <pabs@pablotron.org> | 2018-06-27 21:16:17 -0400 |
commit | 0448ec0a87f8688d93be38e5a92de79cbc672017 (patch) | |
tree | bbf98f2519f00239aec3b6e1959a8b0e95fba210 | |
parent | 3da68a59dffec91cb832d8b2f1d703ed2004f28f (diff) | |
download | gb-c-0448ec0a87f8688d93be38e5a92de79cbc672017.tar.bz2 gb-c-0448ec0a87f8688d93be38e5a92de79cbc672017.zip |
add gpu_draw_objs()
-rw-r--r-- | ops.yaml | 143 |
1 files changed, 94 insertions, 49 deletions
@@ -10247,6 +10247,16 @@ templates: } static uint16_t + obj_get_tile_addr( + gb_t * const ctx, + const uint8_t tile + ) { + UNUSED(ctx); + // base: 0x8000, tile is unsigned + return 0x8000 + 16 * tile; + } + + static uint16_t bg_get_tile_addr( gb_t * const ctx, const uint8_t ty, @@ -10311,41 +10321,97 @@ templates: } static void + gpu_draw_objs( + gb_t * const ctx, + const bool priority + ) { + for (uint8_t i = 0; i < 40; i++) { + if ( + // sprite has correct priority + (ctx->gpu.oam_cache[i].priority == priority) && + + // sprite is on screen and visible + BETWEEN(ctx->gpu.oam_cache[i].y, 0, 144) && + BETWEEN(ctx->gpu.oam_cache[i].x, 0, 160) && + + // sprite is on current line + BETWEEN(ctx->gpu.line, ctx->gpu.oam_cache[i].y, ctx->gpu.oam_cache[i].y + 8) + ) { + // get tile row data + const uint16_t row = mmu_rw(ctx, ( + // get tile data address + obj_get_tile_addr(ctx, ctx->gpu.oam_cache[i].tile) + + + // calculate row offset within tile data + (2 * (ctx->gpu.line - ctx->gpu.oam_cache[i].y)) + )); + + for (uint8_t j = 0; j < 8; j++) { + const int16_t sx = ctx->gpu.oam_cache[i].x + j; + + if (BETWEEN(sx, 0, 160)) { + // get palette offset for pixel + const uint8_t p_ofs = ( + ((row >> (8 + (7 - j)) & 0x01) << 1) | + ((row >> (7 - j)) & 0x01) + ); + + // get pixel color + if (p_ofs > 0) { + // get object palette + const uint8_t obp = ((ctx->gpu.oam_cache[i].palette) ? ctx->gpu.obp1 : ctx->gpu.obp0); + // get pixel color + const uint8_t pc = (obp >> (2 * p_ofs)) & 0x03; + + // calculate framebuffer offset + const uint16_t fb_ofs = 3 * (160 * ctx->gpu.line + sx); + + // convert from 0-3 to RGB + switch (pc) { + case 0: + ctx->gpu.fb[fb_ofs + 0] = 0xFF; + ctx->gpu.fb[fb_ofs + 1] = 0xFF; + ctx->gpu.fb[fb_ofs + 2] = 0xFF; + break; + case 1: + ctx->gpu.fb[fb_ofs + 0] = 0xC0; + ctx->gpu.fb[fb_ofs + 1] = 0xC0; + ctx->gpu.fb[fb_ofs + 2] = 0xC0; + break; + case 2: + ctx->gpu.fb[fb_ofs + 0] = 0x40; + ctx->gpu.fb[fb_ofs + 1] = 0x40; + ctx->gpu.fb[fb_ofs + 2] = 0x40; + break; + case 3: + ctx->gpu.fb[fb_ofs + 0] = 0x00; + ctx->gpu.fb[fb_ofs + 1] = 0x00; + ctx->gpu.fb[fb_ofs + 2] = 0x00; + break; + } + } + } + } + } + } + } + + static void gpu_draw_line( gb_t * const ctx ) { if (gpu_is_active(ctx)) { gpu_oam_cache(ctx); - // draw sprites behind bg - for (uint8_t i = 0; i < 40; i++) { - if ( - // sprite is below bg - ctx->gpu.oam_cache[i].priority && - - // sprite is on screen - BETWEEN(ctx->gpu.oam_cache[i].y, 0, 144) && - BETWEEN(ctx->gpu.oam_cache[i].x, 0, 160) && - - // sprite is on current line - BETWEEN(ctx->gpu.line, ctx->gpu.oam_cache[i].y, ctx->gpu.oam_cache[i].y + 8) - ) { - const uint8_t max_j = MIN(8, 160 - ctx->gpu.oam_cache[i].x); - - for (uint8_t j = 0; j < max_j; j++) { - const uint32_t ofs = 3 * (ctx->gpu.oam_cache[i].y * 160 + ctx->gpu.oam_cache[i].x + j); - - // TODO: draw sprite scanline - ctx->gpu.fb[ofs + 0] = 0xff; - ctx->gpu.fb[ofs + 1] = 0xff; - ctx->gpu.fb[ofs + 2] = 0xff; - } - } + if (ctx->gpu.lcdc & (1 << 1)) { + // obj display is on, draw bg sprites + gpu_draw_objs(ctx, true); } if (ctx->gpu.lcdc & 1) { + // draw backgrond for (uint8_t i = 0; i < 160; i++) { - // get pixel color + // get bg pixel color const uint8_t c = bg_get_color(ctx, ctx->gpu.line, i); // populate framebuffer @@ -10355,30 +10421,9 @@ templates: } } - // draw foreground sprites - for (uint8_t i = 0; i < 40; i++) { - if ( - // sprite is above bg - !ctx->gpu.oam_cache[i].priority && - - // sprite is on screen - BETWEEN(ctx->gpu.oam_cache[i].y, 0, 144) && - BETWEEN(ctx->gpu.oam_cache[i].x, 0, 160) && - - // sprite is on current line - BETWEEN(ctx->gpu.line, ctx->gpu.oam_cache[i].y, ctx->gpu.oam_cache[i].y + 8) - ) { - const uint8_t max_j = MIN(8, 160 - ctx->gpu.oam_cache[i].x); - - for (int j = 0; j < max_j; j++) { - const uint32_t ofs = 3 * (ctx->gpu.oam_cache[i].y * 160 + ctx->gpu.oam_cache[i].x + j); - - // TODO: draw sprite scanline - ctx->gpu.fb[ofs + 0] = 0xff; - ctx->gpu.fb[ofs + 1] = 0xff; - ctx->gpu.fb[ofs + 2] = 0xff; - } - } + if (ctx->gpu.lcdc & (1 << 1)) { + // obj display is on, draw fg sprites + gpu_draw_objs(ctx, false); } } else { // write blank line |