diff options
Diffstat (limited to 'arm9/source/devices/screen.c')
-rw-r--r-- | arm9/source/devices/screen.c | 421 |
1 files changed, 230 insertions, 191 deletions
diff --git a/arm9/source/devices/screen.c b/arm9/source/devices/screen.c index 698b754..bca436d 100644 --- a/arm9/source/devices/screen.c +++ b/arm9/source/devices/screen.c @@ -1,114 +1,123 @@ +#include "screen.h" + + /* -A screen layer contains 768 tiles (32*24), requiring 24KB. Each tile is 32 bytes, -holding 2 pixels per byte. The upper four bits of a tile byte represent the -colour of the right pixel, and the lower four bits the colour of the left pixel. -The colour is a 4-bit reference into a 16-colour RGB15 palette. +Each screen layer is 24KB and contains 768 tiles (32*24). Each tile is 32 +bytes, and contains 64 pixels (8*8), holding 2 pixels per byte. The upper +four bits of a tile byte represent the colour of the right pixel, and the +lower four bits represent the colour of the left pixel. The colour is a +4-bit index into a 16-colour RGB15 palette. + +Four screen layers are used by each physical screen: a foreground layer, a +background layer, and then back buffers for each. Screen layers are stored +as u16* pointers to raw video memory. + +Each 'tile slot' of video memory is 16KB, so we need two slots per layer. We +can't use memory more efficiently by packing the layers more tightly into the +available slots, because we can only draw the contents of a layer by passing +a tile slot base address to the video system. We can, however, use the gaps to +store our tile map, because each map slot takes only 2KB with a corresponding +increase in address granularity. -Screen memory contains four layers: bg, fg, then the same but for double buffers. -Ignore double buffering for now. We keep these as u32* because a single 32-bit -integer represents a single 8-pixel row. -TODO: This needs to be updated. We have double buffering, and we use u16*. +The tile map is shared by all foreground and background layers on a physical +screen, and is stored just past the contents of the first screen layer (at the +24KB offset in video memory). Each entry in the map is a 16-bit tile index. +The low 10 bits of the value represent the tile index, then h-flip, then +v-flip, then a 4-bit palette identifier. We don't flip any tiles, and we +always use palette zero. The map is initialised with an incrementing sequence, +and then never touched. -The tile map is shared by the foreground and background layers, and is stored -just past the first layer for both screens (at the 24KB offset). Each entry is -a 16-bit tile index (low 10 bits are tile index, then h-flip, then v-flip, then -4-bit palette identifier). +The memory bank system of the NDS is byzantine and most vexing, with banks being +identified by letters A through I, and in sizes of 128/128/128/128/64/16/16/32/16 +KB, respectively. The main 2D engine can use banks A/B/C/D/E for BG data (tiles), +and the sub 2D engine can use bank C for the same. */ -#include <nds.h> -#include "screen.h" -#include "../bang.h" -Screen scr_main = { - .bgv = BG_TILE_RAM(BG_SLOT_VIS), - .fgv = BG_TILE_RAM(FG_SLOT_VIS), - .bg = BG_TILE_RAM(BG_SLOT), - .fg = BG_TILE_RAM(FG_SLOT), +// ------ NDS SCREENS ---------------------------------------------------------- + +// VRAM addresses for the main 2D engine. +NDSScreen main_screen = { + .bgv = BG_TILE_RAM(BG_SLOT_FRONT), + .fgv = BG_TILE_RAM(FG_SLOT_FRONT), + .bg = BG_TILE_RAM(BG_SLOT_BACK), + .fg = BG_TILE_RAM(FG_SLOT_BACK), .map = BG_MAP_RAM(MAP_SLOT), .palv = BG_PALETTE, }; -Screen scr_sub = { - .bgv = BG_TILE_RAM_SUB(BG_SLOT_VIS), - .fgv = BG_TILE_RAM_SUB(FG_SLOT_VIS), - .bg = BG_TILE_RAM_SUB(BG_SLOT), - .fg = BG_TILE_RAM_SUB(FG_SLOT), + +// VRAM addresses for the sub 2D engine. +NDSScreen sub_screen = { + .bgv = BG_TILE_RAM_SUB(BG_SLOT_FRONT), + .fgv = BG_TILE_RAM_SUB(FG_SLOT_FRONT), + .bg = BG_TILE_RAM_SUB(BG_SLOT_BACK), + .fg = BG_TILE_RAM_SUB(FG_SLOT_BACK), .map = BG_MAP_RAM_SUB(MAP_SLOT), .palv = BG_PALETTE_SUB, }; -// TODO: Make an enum thing for main/sub, combine these functions -void scr_make_main(ScreenDevice *scr) { - scr->nds = &scr_main; - for (int i=0; i<16; i++) { - scr->nds->pal[i] = scr->palette[i]; - } - scr->wake = true; -} - -void scr_make_sub(ScreenDevice *scr) { - scr->nds = &scr_sub; - for (int i=0; i<16; i++) { - scr->nds->pal[i] = scr->palette[i]; - } - scr->wake = true; -} - -void scr_unmake(ScreenDevice *scr) { - if (scr->nds) { - black_screen(scr->nds); - scr->nds = NULL; - } -} - -void init_screens(void) { - // Allocate VRAM for screens +// Initialise the VRAM mappings and tile map for both NDS screens. +void init_nds_screens(void) { + // Allocate VRAM for screens. videoSetMode(DISPLAY_BG0_ACTIVE | DISPLAY_BG1_ACTIVE | MODE_0_2D); vramSetBankA(VRAM_A_MAIN_BG); videoSetModeSub(DISPLAY_BG0_ACTIVE | DISPLAY_BG1_ACTIVE | MODE_0_2D); vramSetBankC(VRAM_C_SUB_BG); - - /* Configure screen layers to use tile graphics. */ - REG_BG0CNT = BG_32x32 | BG_COLOR_16 | BG_PRIORITY_3 | BG_TILE_BASE(BG_SLOT_VIS) | BG_MAP_BASE(MAP_SLOT); - REG_BG1CNT = BG_32x32 | BG_COLOR_16 | BG_PRIORITY_2 | BG_TILE_BASE(FG_SLOT_VIS) | BG_MAP_BASE(MAP_SLOT); - REG_BG0CNT_SUB = BG_32x32 | BG_COLOR_16 | BG_PRIORITY_3 | BG_TILE_BASE(BG_SLOT_VIS) | BG_MAP_BASE(MAP_SLOT); - REG_BG1CNT_SUB = BG_32x32 | BG_COLOR_16 | BG_PRIORITY_2 | BG_TILE_BASE(FG_SLOT_VIS) | BG_MAP_BASE(MAP_SLOT); - - /* Populate tile maps with tile indices. */ - int i; + // Configure screen layers to use tile graphics. + REG_BG0CNT = BG_32x32 | BG_COLOR_16 | BG_PRIORITY_3 | BG_TILE_BASE(BG_SLOT_FRONT) | BG_MAP_BASE(MAP_SLOT); + REG_BG1CNT = BG_32x32 | BG_COLOR_16 | BG_PRIORITY_2 | BG_TILE_BASE(FG_SLOT_FRONT) | BG_MAP_BASE(MAP_SLOT); + REG_BG0CNT_SUB = BG_32x32 | BG_COLOR_16 | BG_PRIORITY_3 | BG_TILE_BASE(BG_SLOT_FRONT) | BG_MAP_BASE(MAP_SLOT); + REG_BG1CNT_SUB = BG_32x32 | BG_COLOR_16 | BG_PRIORITY_2 | BG_TILE_BASE(FG_SLOT_FRONT) | BG_MAP_BASE(MAP_SLOT); + // Populate tile maps. u16 *main_map = BG_MAP_RAM(12); u16 *sub_map = BG_MAP_RAM_SUB(12); - for (i = 0; i < TILES_SIZE; i++) { + for (int i=0; i<TILES_COUNT; i++) { *(main_map++) = i; *(sub_map++) = i; } } - -void set_palette_high(ScreenDevice *scr, u8 high) { - SET_HIGH(scr->palette_write, high); +// Copy the contents of the back buffer to the front buffer. +void ndsscreen_flip_buffers(NDSScreen *nds) { + if (nds) { + dmaCopyWords(0, nds->bg, nds->bgv, LAYER_MEM); + dmaCopyWords(0, nds->fg, nds->fgv, LAYER_MEM); + for (int i=0; i<16; i++) nds->palv[i] = nds->pal[i]; + } } -void set_palette_low(ScreenDevice *scr, u8 low) { - SET_LOW(scr->palette_write, low); - u8 i = scr->palette_write >> 12 & 0x0f; - u8 r = scr->palette_write >> 7 & 0x1e; - u8 g = scr->palette_write >> 3 & 0x1e; - u8 b = scr->palette_write << 1 & 0x1e; - scr->palette[i] = RGB15(r,g,b); - if (scr->nds) { - scr->nds->pal[i] = RGB15(r,g,b); + +// Erase both buffers and set every colour to black. +void ndsscreen_clear(NDSScreen *nds) { + if (nds) { + dmaFillWords(0, nds->bgv, LAYER_MEM); + dmaFillWords(0, nds->fgv, LAYER_MEM); + dmaFillWords(0, nds->bg, LAYER_MEM); + dmaFillWords(0, nds->fg, LAYER_MEM); + for (int i=0; i<16; i++) nds->palv[i] = RGB15(0,0,0); } } -void push_sprite(SpriteBuffer *b, u8 row) { - b->mem[b->p] = row; - b->p = (b->p + 1) % 16; + +// ------ SPRITE BUFFER -------------------------------------------------------- + +// Reset a sprite buffer. +void spritebuf_reset(SpriteBuffer *b) { + for (int i=0; i<16; i++) b->mem[i] = 0; + b->cached = false; +} + +// Push a byte to a sprite buffer. +void spritebuf_push(SpriteBuffer *b, u8 row) { + b->mem[b->p++] = row; + b->p %= 16; b->cached = FALSE; } -void prepare_1bit_sprite(SpriteBuffer *b, u8 draw) { +// Parse, transform, and cache a 1-bit sprite. +void spritebuf_prepare_1bit(SpriteBuffer *b, u8 draw) { u8 l,p,x,y; if (b->cached && draw == b->draw) return; - + // Parse and transform the sprite if not already cached. switch (draw & 0x07) { case 0x0: p=b->p+8; for (y=0;y<8;y++) { l=b->mem[p++ % 16]; for (x=0;x<8;x++) { b->sprite[y][x] = l>>(7-x) & 1; } }; break; case 0x1: p=b->p+8; for (y=0;y<8;y++) { l=b->mem[p++ % 16]; for (x=0;x<8;x++) { b->sprite[y][x] = l>>( x) & 1; } }; break; @@ -119,15 +128,15 @@ void prepare_1bit_sprite(SpriteBuffer *b, u8 draw) { case 0x6: p=b->p; for (y=0;y<8;y++) { l=b->mem[--p % 16]; for (x=0;x<8;x++) { b->sprite[x][y] = l>>(7-x) & 1; } }; break; case 0x7: p=b->p; for (y=0;y<8;y++) { l=b->mem[--p % 16]; for (x=0;x<8;x++) { b->sprite[x][y] = l>>( x) & 1; } }; break; } - - b->cached = TRUE; b->draw = draw; + b->cached = true; } -void prepare_2bit_sprite(SpriteBuffer *b, u8 draw) { +// Parse, transform, and cache a 2-bit sprite. +void spritebuf_prepare_2bit(SpriteBuffer *b, u8 draw) { u8 l,h,i,p,s,x,y; if (b->cached && draw == b->draw) return; - + // Parse and transform the sprite if not already cached. switch (draw & 0x07) { case 0x0: p=b->p+8; s=p+8; for (y=0;y<8;y++) { l=b->mem[p++ % 16]; h=b->mem[s++ % 16]; for (x=0;x<8;x++) { i=(7-x); b->sprite[y][x] = (l>>i & 1) | (h>>i & 1) << 1; } }; break; case 0x1: p=b->p+8; s=p+8; for (y=0;y<8;y++) { l=b->mem[p++ % 16]; h=b->mem[s++ % 16]; for (x=0;x<8;x++) { i=( x); b->sprite[y][x] = (l>>i & 1) | (h>>i & 1) << 1; } }; break; @@ -138,14 +147,77 @@ void prepare_2bit_sprite(SpriteBuffer *b, u8 draw) { case 0x6: p=b->p; s=p+8; for (y=0;y<8;y++) { l=b->mem[--p % 16]; h=b->mem[--s % 16]; for (x=0;x<8;x++) { i=(7-x); b->sprite[x][y] = (l>>i & 1) | (h>>i & 1) << 1; } }; break; case 0x7: p=b->p; s=p+8; for (y=0;y<8;y++) { l=b->mem[--p % 16]; h=b->mem[--s % 16]; for (x=0;x<8;x++) { i=( x); b->sprite[x][y] = (l>>i & 1) | (h>>i & 1) << 1; } }; break; } - - b->cached = TRUE; b->draw = draw; + b->cached = true; +} + + +// ------ BEDROCK SCREEN ------------------------------------------------------- + +// Reset a screen device. +void screen_reset(ScreenDevice *screen) { + screen->x = 0; + screen->y = 0; + screen->px = 0; + screen->py = 0; + screen->selected = 0; + spritebuf_reset(&screen->sprite); + screen->colour = 0; + for (int i=0; i<16; i++) screen->pal[i] = 0; + ndsscreen_clear(screen->nds); + screen->wake = false; + screen->dirty = false; } +// Unmap a screen device from a screen. +void screen_map_to_none(ScreenDevice *screen) { + if (screen->nds) { + ndsscreen_clear(screen->nds); + screen->nds = NULL; + } +} + +// Map a screen device to the main screen. +void screen_map_to_main(ScreenDevice *screen) { + screen->nds = &main_screen; + memcpy(&screen->nds->pal, &screen->pal, 32); + screen->wake = true; +} + +// Map a screen device to the sub screen. +void screen_map_to_sub(ScreenDevice *screen) { + screen->nds = &sub_screen; + memcpy(&screen->nds->pal, &screen->pal, 32); + screen->wake = true; +} + +// Commit a new colour to the colour palette. +void screen_commit_colour(ScreenDevice *screen) { + u8 i = screen->colour >> 12 & 0x0f; + // Extract 5-bit channel values. + u8 r = screen->colour >> 7 & 0x1e; + u8 g = screen->colour >> 3 & 0x1e; + u8 b = screen->colour << 1 & 0x1e; + screen->pal[i] = RGB15(r,g,b); + if (screen->nds) screen->nds->pal[i] = RGB15(r,g,b); + screen->dirty = true; +} + +// Move the screen cursor. +void screen_move_cursor(ScreenDevice *screen, u8 move) { + switch (move >> 6) { + case 0b00: screen->x += move & 0x3f; return; + case 0b01: screen->y += move & 0x3f; return; + case 0b10: screen->x -= move & 0x3f; return; + case 0b11: screen->y -= move & 0x3f; return; + } +} + + -// --------------------------------------------------------------------------- +// ------ RAW DRAW OPERATIONS -------------------------------------------------- +// Draw a pixel to a screen layer. void draw_pixel(u16 *layer, u16 x, u16 y, u8 colour) { if (x < PIXELS_WIDTH && y < PIXELS_HEIGHT) { u32 addr = \ @@ -156,109 +228,58 @@ void draw_pixel(u16 *layer, u16 x, u16 y, u8 colour) { } } +// Fill a screen layer with a solid colour. void fill_layer(u16 *layer, u8 colour) { u8 byte = colour << 4 | colour; u32 word = byte << 24 | byte << 16 | byte << 8 | byte; - dmaFillWords(word, layer, TILES_MEM); -} - -void erase_screen(Screen *nds) { - if (nds) { - dmaFillWords(0, nds->bg, TILES_MEM); - dmaFillWords(0, nds->fg, TILES_MEM); - } -}; - -void flip_buffer(Screen *nds) { - if (nds) { - dmaCopyWords(0, nds->bg, nds->bgv, TILES_MEM); - dmaCopyWords(0, nds->fg, nds->fgv, TILES_MEM); - for (int i=0; i<16; i++) { - nds->palv[i] = nds->pal[i]; - } - } + dmaFillWords(word, layer, LAYER_MEM); } -void black_screen(Screen *nds) { - if (nds) { - for (int i=0; i<16; i++) { - nds->palv[i] = RGB15(0,0,0); - } - dmaFillWords(0, nds->bgv, TILES_MEM); - dmaFillWords(0, nds->fgv, TILES_MEM); - } -} -// --------------------------------------------------------------------------- -void draw_dispatch(ScreenDevice *scr, u8 draw) { - if (scr->nds) { - switch (draw >> 4) { - case 0x0: scr_draw_pixel(scr, scr->nds->bg, draw); break; - case 0x1: scr_draw_sprite(scr, scr->nds->bg, draw); break; - case 0x2: scr_fill_layer(scr, scr->nds->bg, draw); break; - case 0x3: scr_draw_sprite(scr, scr->nds->bg, draw); break; - case 0x4: scr_draw_line(scr, scr->nds->bg, draw); break; - case 0x5: scr_draw_line(scr, scr->nds->bg, draw); break; - case 0x6: scr_draw_rect(scr, scr->nds->bg, draw); break; - case 0x7: scr_draw_rect(scr, scr->nds->bg, draw); break; - case 0x8: scr_draw_pixel(scr, scr->nds->fg, draw); break; - case 0x9: scr_draw_sprite(scr, scr->nds->fg, draw); break; - case 0xA: scr_fill_layer(scr, scr->nds->fg, draw); break; - case 0xB: scr_draw_sprite(scr, scr->nds->fg, draw); break; - case 0xC: scr_draw_line(scr, scr->nds->fg, draw); break; - case 0xD: scr_draw_line(scr, scr->nds->fg, draw); break; - case 0xE: scr_draw_rect(scr, scr->nds->fg, draw); break; - case 0xF: scr_draw_rect(scr, scr->nds->fg, draw); break; - } - scr->dirty = true; - } - scr->px = scr->x; - scr->py = scr->y; -} +// ------ DRAW OPERATIONS ------------------------------------------------------ -void scr_draw_pixel(ScreenDevice *scr, u16 *layer, u8 draw) { - draw_pixel(layer, scr->x, scr->y, draw&0xf); +void op_draw_pixel(ScreenDevice *screen, u16 *layer, u8 draw) { + draw_pixel(layer, screen->x, screen->y, draw&0xf); } -void scr_fill_layer(ScreenDevice *scr, u16 *layer, u8 draw) { +void op_fill_layer(ScreenDevice *screen, u16 *layer, u8 draw) { fill_layer(layer, draw&0xf); } -void scr_draw_sprite(ScreenDevice *scr, u16 *layer, u8 draw) { - if (draw & 0x20) { prepare_2bit_sprite(&scr->sprite, draw); } - else { prepare_1bit_sprite(&scr->sprite, draw); } - - u8 colours[4] = { - scr->colours >> 12 & 0x000f, - scr->colours >> 8 & 0x000f, - scr->colours >> 4 & 0x000f, - scr->colours & 0x000f, +void op_draw_sprite(ScreenDevice *screen, u16 *layer, u8 draw) { + if (draw & 0x20) { spritebuf_prepare_2bit(&screen->sprite, draw); } + else { spritebuf_prepare_1bit(&screen->sprite, draw); } + // Parse sprite colours. + u8 selected[4] = { + screen->selected >> 12 & 0x000f, + screen->selected >> 8 & 0x000f, + screen->selected >> 4 & 0x000f, + screen->selected & 0x000f, }; - if (draw & 0x08) { - // Draw sprite with transparent background + // Draw sprite with transparent background. for (u8 y=0;y<8;y++) { for (u8 x=0;x<8;x++) { - u8 i = scr->sprite.sprite[y][x]; - if (i) draw_pixel(layer, scr->x+x, scr->y+y, colours[i]); + u8 i = screen->sprite.sprite[y][x]; + if (i) draw_pixel(layer, screen->x+x, screen->y+y, selected[i]); } } } else { - // Draw sprite with opaque background + // Draw sprite with opaque background. for (u8 y=0;y<8;y++) { for (u8 x=0;x<8;x++) { - u8 i = scr->sprite.sprite[y][x]; - draw_pixel(layer, scr->x+x, scr->y+y, colours[i]); + u8 i = screen->sprite.sprite[y][x]; + draw_pixel(layer, screen->x+x, screen->y+y, selected[i]); } } } } -void scr_draw_line(ScreenDevice *scr, u16 *layer, u8 draw) { - s16 x = (s16) scr->x; - s16 y = (s16) scr->y; - s16 x_end = (s16) scr->px; - s16 y_end = (s16) scr->py; +void op_draw_line(ScreenDevice *screen, u16 *layer, u8 draw) { + s16 x = (s16) screen->x; + s16 y = (s16) screen->y; + s16 x_end = (s16) screen->px; + s16 y_end = (s16) screen->py; s32 dx = abs(x_end - x); s32 dy = -abs(y_end - y); @@ -267,24 +288,24 @@ void scr_draw_line(ScreenDevice *scr, u16 *layer, u8 draw) { s32 e1 = dx + dy; if (draw & 0x10) { - // Draw 1-bit textured line. - prepare_1bit_sprite(&scr->sprite, draw); - u8 c1 = scr->colours >> 8 & 0xf; - u8 c0 = scr->colours >> 12 & 0xf; + // Draw 1-bit textured line. + spritebuf_prepare_1bit(&screen->sprite, draw); + u8 c1 = screen->selected >> 8 & 0xf; + u8 c0 = screen->selected >> 12 & 0xf; bool opaque = !(draw & 0x08); while (1) { - if (scr->sprite.sprite[y%8][x%8]) { draw_pixel(layer, x, y, c1); } - else if (opaque) { draw_pixel(layer, x, y, c0); } + if (screen->sprite.sprite[y%8][x%8]) { draw_pixel(layer, x, y, c1); } + else if (opaque) { draw_pixel(layer, x, y, c0); } if (x == x_end && y == y_end) return; s32 e2 = e1 << 1; if (e2 >= dy) { e1 += dy; x += sx; } if (e2 <= dx) { e1 += dx; y += sy; } } } else { - // Draw solid line. - u8 colour = draw & 0xf; + // Draw solid line. + u8 c0 = draw & 0xf; while (1) { - draw_pixel(layer, x, y, colour); + draw_pixel(layer, x, y, c0); if (x == x_end && y == y_end) return; s32 e2 = e1 << 1; if (e2 >= dy) { e1 += dy; x += sx; } @@ -293,46 +314,64 @@ void scr_draw_line(ScreenDevice *scr, u16 *layer, u8 draw) { } } -void scr_draw_rect(ScreenDevice *scr, u16 *layer, u8 draw) { +void op_draw_rect(ScreenDevice *screen, u16 *layer, u8 draw) { #define SWAP(x,y) {u8 temp=x; x=y; y=temp;} #define CLAMP(v,m) {v>0x7fff ? 0 : v>m ? m : v} // Get bounding box. - u16 l = CLAMP(scr->px, PIXELS_WIDTH -1); - u16 r = CLAMP(scr->x , PIXELS_WIDTH -1); - u16 t = CLAMP(scr->py, PIXELS_HEIGHT-1); - u16 b = CLAMP(scr->y , PIXELS_HEIGHT-1); + u16 l = CLAMP(screen->px, PIXELS_WIDTH -1); + u16 r = CLAMP(screen->x , PIXELS_WIDTH -1); + u16 t = CLAMP(screen->py, PIXELS_HEIGHT-1); + u16 b = CLAMP(screen->y , PIXELS_HEIGHT-1); if (l>r) SWAP(l,r); if (t>b) SWAP(t,b); if (draw & 0x10) { - // Draw 1-bit textured rectangle. - prepare_1bit_sprite(&scr->sprite, draw); - u8 c1 = scr->colours >> 8 & 0xf; - u8 c0 = scr->colours >> 12 & 0xf; + // Draw 1-bit textured rectangle. + spritebuf_prepare_1bit(&screen->sprite, draw); + u8 c1 = screen->selected >> 8 & 0xf; + u8 c0 = screen->selected >> 12 & 0xf; bool opaque = !(draw & 0x08); for (u16 x=l; x<r+1; x++) { for (u16 y=t; y<b+1; y++) { - if (scr->sprite.sprite[y%8][x%8]) { draw_pixel(layer, x, y, c1); } - else if (opaque) { draw_pixel(layer, x, y, c0); } + if (screen->sprite.sprite[y%8][x%8]) { draw_pixel(layer, x, y, c1); } + else if (opaque) { draw_pixel(layer, x, y, c0); } } } } else { - // Draw solid rectangle. - u8 colour = draw & 0xf; + // Draw solid rectangle. + u8 c0 = draw & 0xf; for (u16 x=l; x<r+1; x++) { for (u16 y=t; y<b+1; y++) { - draw_pixel(layer, x, y, colour); + draw_pixel(layer, x, y, c0); } } } } -void move_cursor(ScreenDevice *scr, u8 move) { - switch (move >> 6) { - case 0b00: scr->x += move & 0x3f; return; - case 0b01: scr->y += move & 0x3f; return; - case 0b10: scr->x -= move & 0x3f; return; - case 0b11: scr->y -= move & 0x3f; return; +// Dispatch to the correct drawing operation. +void screen_draw(ScreenDevice *screen, u8 draw) { + if (screen->nds) { + switch (draw >> 4) { + case 0x0: op_draw_pixel(screen, screen->nds->bg, draw); break; + case 0x1: op_draw_sprite(screen, screen->nds->bg, draw); break; + case 0x2: op_fill_layer(screen, screen->nds->bg, draw); break; + case 0x3: op_draw_sprite(screen, screen->nds->bg, draw); break; + case 0x4: op_draw_line(screen, screen->nds->bg, draw); break; + case 0x5: op_draw_line(screen, screen->nds->bg, draw); break; + case 0x6: op_draw_rect(screen, screen->nds->bg, draw); break; + case 0x7: op_draw_rect(screen, screen->nds->bg, draw); break; + case 0x8: op_draw_pixel(screen, screen->nds->fg, draw); break; + case 0x9: op_draw_sprite(screen, screen->nds->fg, draw); break; + case 0xA: op_fill_layer(screen, screen->nds->fg, draw); break; + case 0xB: op_draw_sprite(screen, screen->nds->fg, draw); break; + case 0xC: op_draw_line(screen, screen->nds->fg, draw); break; + case 0xD: op_draw_line(screen, screen->nds->fg, draw); break; + case 0xE: op_draw_rect(screen, screen->nds->fg, draw); break; + case 0xF: op_draw_rect(screen, screen->nds->fg, draw); break; + } + screen->dirty = true; } + screen->px = screen->x; + screen->py = screen->y; } |