aboutsummaryrefslogtreecommitdiff
path: root/arm9/source/devices/screen.c
diff options
context:
space:
mode:
Diffstat (limited to 'arm9/source/devices/screen.c')
-rw-r--r--arm9/source/devices/screen.c421
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;
}