diff --git a/README.md b/README.md new file mode 100644 index 0000000..511d057 --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +# Almost-Empty Demo Collection + +### `2d_sprites.gba` +`grit` command: `grit sprite.bmp -ftc -pu32 -pn16 -gB4` \ No newline at end of file diff --git a/assets/generic/vertical/16x32/sprite.aseprite b/assets/generic/vertical/16x32/sprite.aseprite new file mode 100644 index 0000000..676ec3e Binary files /dev/null and b/assets/generic/vertical/16x32/sprite.aseprite differ diff --git a/assets/generic/vertical/32x64/sprite.aseprite b/assets/generic/vertical/32x64/sprite.aseprite new file mode 100644 index 0000000..0d33bde Binary files /dev/null and b/assets/generic/vertical/32x64/sprite.aseprite differ diff --git a/assets/generic/vertical/8x16/sprite.aseprite b/assets/generic/vertical/8x16/sprite.aseprite new file mode 100644 index 0000000..b93d59c Binary files /dev/null and b/assets/generic/vertical/8x16/sprite.aseprite differ diff --git a/assets/generic/vertical/8x32/sprite.aseprite b/assets/generic/vertical/8x32/sprite.aseprite new file mode 100644 index 0000000..080d7e0 Binary files /dev/null and b/assets/generic/vertical/8x32/sprite.aseprite differ diff --git a/src/2d_sprites.zig b/src/2d_sprites.zig index 04bba7f..99fe8b2 100644 --- a/src/2d_sprites.zig +++ b/src/2d_sprites.zig @@ -8,6 +8,7 @@ const Input = @import("gba").Input; const SquareSpriteTuple = std.meta.Tuple(&[_]type{ Sprite8x8, Sprite16x16, Sprite32x32, Sprite64x64 }); const HorizSpriteTuple = std.meta.Tuple(&[_]type{ Sprite16x8, Sprite32x8, Sprite32x16, Sprite64x32 }); +const VertSpriteTuple = std.meta.Tuple(&[_]type{ Sprite8x16, Sprite8x32, Sprite16x32, Sprite32x64 }); // TODO: ZigGBA should support spaces, slashes, underscores, etc. in ROM Title export var gameHeader linksection(".gbaheader") = GBA.Header.setup("2DSPRITE", "PAOD", "00", 0); @@ -18,6 +19,7 @@ export var gameHeader linksection(".gbaheader") = GBA.Header.setup("2DSPRITE", " const square_sprites = initSquareSpriteTuple(); const horiz_sprites = initHorizSpriteTuple(); +const vert_sprites = initVertSpriteTuple(); fn initSquareSpriteTuple() SquareSpriteTuple { return .{ Sprite8x8{}, Sprite16x16{}, Sprite32x32{}, Sprite64x64{} }; @@ -27,6 +29,10 @@ fn initHorizSpriteTuple() HorizSpriteTuple { return .{ Sprite16x8{}, Sprite32x8{}, Sprite32x16{}, Sprite64x32{} }; } +fn initVertSpriteTuple() VertSpriteTuple { + return .{ Sprite8x16{}, Sprite8x32{}, Sprite16x32{}, Sprite32x64{} }; +} + pub fn main() noreturn { LCD.setupDisplayControl(.{ .mode = .Mode0, // No Affine BGs @@ -36,7 +42,7 @@ pub fn main() noreturn { OAM.init(); - const sprites = horiz_sprites; + const sprites = square_sprites; sprites[0].load(); // Copy Mapping to VRAM and Palette to PALRAM @@ -113,8 +119,11 @@ const Sprite8x8 = struct { fn load(_: Self) void { // 8x8 Sprites don't differ in any meaningful way between 1D and 2D mapping + const sprite_width = 8; // 8x8 + const len = sprite_width * @sizeOf(u32); + // Copy Tile Mapping - GBA.memcpy32(GBA.SPRITE_VRAM, &Self.tiles, Self.tiles.len * @sizeOf(u32)); + GBA.memcpy32(GBA.SPRITE_VRAM, &Self.tiles[0], len); // Copy Palette GBA.memcpy32(GBA.OBJ_PALETTE_RAM, &Self.pal, Self.pal.len * @sizeOf(u32)); @@ -198,12 +207,14 @@ const Sprite32x32 = struct { // 9 10 11 12 // 13 14 15 16 - const quarter = Self.tiles.len / 4; + const px_width = 8 * 4; + const offset = 0x40 / 4; + const len = px_width * @sizeOf(u32); - GBA.memcpy32(GBA.SPRITE_VRAM, &Self.tiles[0], quarter * @sizeOf(u32)); - GBA.memcpy32(GBA.SPRITE_VRAM + (quarter * 0x10), &Self.tiles[quarter], quarter * @sizeOf(u32)); - GBA.memcpy32(GBA.SPRITE_VRAM + (quarter * 0x20), &Self.tiles[quarter * 2], quarter * @sizeOf(u32)); - GBA.memcpy32(GBA.SPRITE_VRAM + (quarter * 0x30), &Self.tiles[quarter * 3], quarter * @sizeOf(u32)); + GBA.memcpy32(GBA.SPRITE_VRAM, &Self.tiles[0], len); + GBA.memcpy32(GBA.SPRITE_VRAM + (px_width * offset), &Self.tiles[px_width], len); + GBA.memcpy32(GBA.SPRITE_VRAM + (px_width * (offset * 2)), &Self.tiles[px_width * 2], len); + GBA.memcpy32(GBA.SPRITE_VRAM + (px_width * (offset * 3)), &Self.tiles[px_width * 3], len); // Palette GBA.memcpy32(GBA.OBJ_PALETTE_RAM, &Self.pal, Self.pal.len * @sizeOf(u32)); @@ -309,16 +320,18 @@ const Sprite64x64 = struct { // 49 50 51 52 53 54 55 56 // 57 58 59 60 61 62 63 64 - const eighth = Self.tiles.len / 8; + const px_width = 8 * 8; + const offset = 0x40 / 8; + const len = px_width * @sizeOf(u32); - GBA.memcpy32(GBA.SPRITE_VRAM, &Self.tiles[0], eighth * @sizeOf(u32)); - GBA.memcpy32(GBA.SPRITE_VRAM + (eighth * 0x8), &Self.tiles[eighth], eighth * @sizeOf(u32)); - GBA.memcpy32(GBA.SPRITE_VRAM + (eighth * 0x10), &Self.tiles[eighth * 2], eighth * @sizeOf(u32)); - GBA.memcpy32(GBA.SPRITE_VRAM + (eighth * 0x18), &Self.tiles[eighth * 3], eighth * @sizeOf(u32)); - GBA.memcpy32(GBA.SPRITE_VRAM + (eighth * 0x20), &Self.tiles[eighth * 4], eighth * @sizeOf(u32)); - GBA.memcpy32(GBA.SPRITE_VRAM + (eighth * 0x28), &Self.tiles[eighth * 5], eighth * @sizeOf(u32)); - GBA.memcpy32(GBA.SPRITE_VRAM + (eighth * 0x30), &Self.tiles[eighth * 6], eighth * @sizeOf(u32)); - GBA.memcpy32(GBA.SPRITE_VRAM + (eighth * 0x38), &Self.tiles[eighth * 7], eighth * @sizeOf(u32)); + GBA.memcpy32(GBA.SPRITE_VRAM, &Self.tiles[0], len); + GBA.memcpy32(GBA.SPRITE_VRAM + (px_width * offset), &Self.tiles[px_width], len); + GBA.memcpy32(GBA.SPRITE_VRAM + (px_width * (offset * 2)), &Self.tiles[px_width * 2], len); + GBA.memcpy32(GBA.SPRITE_VRAM + (px_width * (offset * 3)), &Self.tiles[px_width * 3], len); + GBA.memcpy32(GBA.SPRITE_VRAM + (px_width * (offset * 4)), &Self.tiles[px_width * 4], len); + GBA.memcpy32(GBA.SPRITE_VRAM + (px_width * (offset * 5)), &Self.tiles[px_width * 5], len); + GBA.memcpy32(GBA.SPRITE_VRAM + (px_width * (offset * 6)), &Self.tiles[px_width * 6], len); + GBA.memcpy32(GBA.SPRITE_VRAM + (px_width * (offset * 7)), &Self.tiles[px_width * 7], len); // Palette GBA.memcpy32(GBA.OBJ_PALETTE_RAM, &Self.pal, Self.pal.len * @sizeOf(u32)); @@ -347,7 +360,11 @@ const Sprite16x8 = struct { fn load(_: Self) void { // In Memory, Tile Map is laid out like: 1 2 - GBA.memcpy32(GBA.SPRITE_VRAM, &Self.tiles[0], Self.tiles.len * @sizeOf(u32)); + + const px_width = 8 * 2; + const len = px_width * @sizeOf(u32); + + GBA.memcpy32(GBA.SPRITE_VRAM, &Self.tiles[0], len); // Palette GBA.memcpy32(GBA.OBJ_PALETTE_RAM, &Self.pal, Self.pal.len * @sizeOf(u32)); @@ -378,7 +395,11 @@ const Sprite32x8 = struct { fn load(_: Self) void { // In Memory, Tile Map is laid out like: 1 2 3 4 - GBA.memcpy32(GBA.SPRITE_VRAM, &Self.tiles[0], Self.tiles.len * @sizeOf(u32)); + + const px_width = 8 * 4; + const len = px_width * @sizeOf(u32); + + GBA.memcpy32(GBA.SPRITE_VRAM, &Self.tiles[0], len); // Palette GBA.memcpy32(GBA.OBJ_PALETTE_RAM, &Self.pal, Self.pal.len * @sizeOf(u32)); @@ -415,9 +436,12 @@ const Sprite32x16 = struct { // In Memory, Tile Map is laid out like: 1 2 3 4 // 5 6 7 8 - const half = Self.tiles.len / 2; - GBA.memcpy32(GBA.SPRITE_VRAM, &Self.tiles[0], half * @sizeOf(u32)); - GBA.memcpy32(GBA.SPRITE_VRAM + (half * 0x10), &Self.tiles[half], half * @sizeOf(u32)); + const px_width = 8 * 4; + const offset = 0x40 / 4; + const len = px_width * @sizeOf(u32); + + GBA.memcpy32(GBA.SPRITE_VRAM, &Self.tiles[0], len); + GBA.memcpy32(GBA.SPRITE_VRAM + (px_width * offset), &Self.tiles[px_width], len); // Palette GBA.memcpy32(GBA.OBJ_PALETTE_RAM, &Self.pal, Self.pal.len * @sizeOf(u32)); @@ -482,12 +506,218 @@ const Sprite64x32 = struct { // 9 10 11 12 13 14 15 16 // 17 18 19 20 21 22 23 24 // 25 26 27 28 29 30 31 32 - const quarter = Self.tiles.len / 4; - GBA.memcpy32(GBA.SPRITE_VRAM, &Self.tiles[0], quarter * @sizeOf(u32)); - GBA.memcpy32(GBA.SPRITE_VRAM + (quarter * 0x8), &Self.tiles[quarter], quarter * @sizeOf(u32)); - GBA.memcpy32(GBA.SPRITE_VRAM + (quarter * 0x10), &Self.tiles[quarter * 2], quarter * @sizeOf(u32)); - GBA.memcpy32(GBA.SPRITE_VRAM + (quarter * 0x18), &Self.tiles[quarter * 3], quarter * @sizeOf(u32)); + const px_width = 8 * 8; + const offset = 0x40 / 8; + const len = px_width * @sizeOf(u32); + + GBA.memcpy32(GBA.SPRITE_VRAM, &Self.tiles[0], len); + GBA.memcpy32(GBA.SPRITE_VRAM + (px_width * offset), &Self.tiles[px_width], len); + GBA.memcpy32(GBA.SPRITE_VRAM + (px_width * (offset * 2)), &Self.tiles[px_width * 2], len); + GBA.memcpy32(GBA.SPRITE_VRAM + (px_width * (offset * 3)), &Self.tiles[px_width * 3], len); + + // Palette + GBA.memcpy32(GBA.OBJ_PALETTE_RAM, &Self.pal, Self.pal.len * @sizeOf(u32)); + } +}; + +const Sprite8x16 = struct { + const Self = @This(); + + const pal = [8]u32{ + 0x3DEF0000, 0x00006318, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }; + + const tiles = [16]u32{ + 0x21111112, 0x21111112, 0x12111121, 0x12111121, 0x11211211, 0x11211211, 0x11112111, 0x11112111, + 0x11121111, 0x11121111, 0x11211211, 0x11211211, 0x12111121, 0x12111121, 0x21111112, 0x21111112, + }; + + fn paletteMode(_: Self) GBA.PaletteMode { + return .Color16; + } + + fn size(_: Self) OAM.ObjectSize { + return .Size8x16; + } + + fn load(_: Self) void { + // In Memory, Tile Map is laid out like: 1 + // 2 + + const sprite_len = 8; + + GBA.memcpy32(GBA.SPRITE_VRAM, &Self.tiles[0], sprite_len * @sizeOf(u32)); + GBA.memcpy32(GBA.SPRITE_VRAM + (sprite_len * 0x40), &Self.tiles[sprite_len], sprite_len * @sizeOf(u32)); + + // Palette + GBA.memcpy32(GBA.OBJ_PALETTE_RAM, &Self.pal, Self.pal.len * @sizeOf(u32)); + } +}; + +const Sprite8x32 = struct { + const Self = @This(); + + const pal = [8]u32{ + 0x3DEF0000, 0x00006318, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }; + + const tiles = [32]u32{ + 0x21111112, 0x21111112, 0x21111112, 0x21111112, 0x12111121, 0x12111121, 0x12111121, 0x12111121, + 0x11211211, 0x11211211, 0x11211211, 0x11211211, 0x11112111, 0x11112111, 0x11112111, 0x11112111, + 0x11121111, 0x11121111, 0x11121111, 0x11121111, 0x11211211, 0x11211211, 0x11211211, 0x11211211, + 0x12111121, 0x12111121, 0x12111121, 0x12111121, 0x21111112, 0x21111112, 0x21111112, 0x21111112, + }; + + fn paletteMode(_: Self) GBA.PaletteMode { + return .Color16; + } + + fn size(_: Self) OAM.ObjectSize { + return .Size8x32; + } + + fn load(_: Self) void { + // In Memory, Tile Map is laid out like: 1 + // 2 + // 3 + // 4 + + const px_width = 8; + const offset = 0x40; + const len = px_width * @sizeOf(u32); + + GBA.memcpy32(GBA.SPRITE_VRAM, &Self.tiles[0], len); + GBA.memcpy32(GBA.SPRITE_VRAM + (px_width * offset), &Self.tiles[px_width], len); + GBA.memcpy32(GBA.SPRITE_VRAM + (px_width * (offset * 2)), &Self.tiles[px_width * 2], len); + GBA.memcpy32(GBA.SPRITE_VRAM + (px_width * (offset * 3)), &Self.tiles[px_width * 3], len); + + // Palette + GBA.memcpy32(GBA.OBJ_PALETTE_RAM, &Self.pal, Self.pal.len * @sizeOf(u32)); + } +}; + +const Sprite16x32 = struct { + const Self = @This(); + + const pal = [8]u32{ + 0x3DEF0000, 0x00006318, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }; + + const tiles = [64]u32{ + 0x11111112, 0x11111112, 0x11111121, 0x11111121, 0x11111211, 0x11111211, 0x11112111, 0x11112111, + 0x21111111, 0x21111111, 0x12111111, 0x12111111, 0x11211111, 0x11211111, 0x11121111, 0x11121111, + 0x11121111, 0x11121111, 0x11211111, 0x11211111, 0x12111111, 0x12111111, 0x21111111, 0x21111111, + 0x11112111, 0x11112111, 0x11111211, 0x11111211, 0x11111121, 0x11111121, 0x11111111, 0x11111111, + 0x11111111, 0x11111111, 0x12111111, 0x12111111, 0x11211111, 0x11211111, 0x11121111, 0x11121111, + 0x11111112, 0x11111112, 0x11111121, 0x11111121, 0x11111211, 0x11111211, 0x11112111, 0x11112111, + 0x11112111, 0x11112111, 0x11111211, 0x11111211, 0x11111121, 0x11111121, 0x11111112, 0x11111112, + 0x11121111, 0x11121111, 0x11211111, 0x11211111, 0x12111111, 0x12111111, 0x21111111, 0x21111111, + }; + + fn paletteMode(_: Self) GBA.PaletteMode { + return .Color16; + } + + fn size(_: Self) OAM.ObjectSize { + return .Size16x32; + } + + fn load(_: Self) void { + // In Memory, Tile Map is laid out like: 1 2 + // 3 4 + // 5 6 + // 7 8 + + const px_width = 8 * 2; + const offset = 0x40 / 2; + const len = px_width * @sizeOf(u32); + + GBA.memcpy32(GBA.SPRITE_VRAM, &Self.tiles[0], len); + GBA.memcpy32(GBA.SPRITE_VRAM + (px_width * offset), &Self.tiles[px_width], len); + GBA.memcpy32(GBA.SPRITE_VRAM + (px_width * (offset * 2)), &Self.tiles[px_width * 2], len); + GBA.memcpy32(GBA.SPRITE_VRAM + (px_width * (offset * 3)), &Self.tiles[px_width * 3], len); + + // Palette + GBA.memcpy32(GBA.OBJ_PALETTE_RAM, &Self.pal, Self.pal.len * @sizeOf(u32)); + } +}; + +const Sprite32x64 = struct { + const Self = @This(); + + const pal = [8]u32{ + 0x3DEF0000, 0x00006318, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }; + + const tiles = [256]u32{ + 0x11111112, 0x11111112, 0x11111121, 0x11111121, 0x11111211, 0x11111211, 0x11112111, 0x11112111, + 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, + 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, + 0x21111111, 0x21111111, 0x12111111, 0x12111111, 0x11211111, 0x11211111, 0x11121111, 0x11121111, + 0x11121111, 0x11121111, 0x11211111, 0x11211111, 0x12111111, 0x12111111, 0x21111111, 0x21111111, + 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, + 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, + 0x11112111, 0x11112111, 0x11111211, 0x11111211, 0x11111121, 0x11111121, 0x11111112, 0x11111112, + + 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, + 0x11111112, 0x11111112, 0x11111121, 0x11111121, 0x11111211, 0x11111211, 0x11112111, 0x11112111, + 0x21111111, 0x21111111, 0x12111111, 0x12111111, 0x11211111, 0x11211111, 0x11121111, 0x11121111, + 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, + 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, + 0x11121111, 0x11121111, 0x11211111, 0x11211111, 0x12111111, 0x12111111, 0x21111111, 0x21111111, + 0x11112111, 0x11112111, 0x11111211, 0x11111211, 0x11111121, 0x11111121, 0x11111111, 0x11111111, + 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, + + 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, + 0x11111111, 0x11111111, 0x12111111, 0x12111111, 0x11211111, 0x11211111, 0x11121111, 0x11121111, + 0x11111112, 0x11111112, 0x11111121, 0x11111121, 0x11111211, 0x11111211, 0x11112111, 0x11112111, + 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, + 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, + 0x11112111, 0x11112111, 0x11111211, 0x11111211, 0x11111121, 0x11111121, 0x11111112, 0x11111112, + 0x11121111, 0x11121111, 0x11211111, 0x11211111, 0x12111111, 0x12111111, 0x21111111, 0x21111111, + 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, + + 0x21111111, 0x21111111, 0x12111111, 0x12111111, 0x11211111, 0x11211111, 0x11121111, 0x11121111, + 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, + 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, + 0x11111112, 0x11111112, 0x11111121, 0x11111121, 0x11111211, 0x11111211, 0x11112111, 0x11112111, + 0x11112111, 0x11112111, 0x11111211, 0x11111211, 0x11111121, 0x11111121, 0x11111112, 0x11111112, + 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, + 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, 0x11111111, + 0x11121111, 0x11121111, 0x11211111, 0x11211111, 0x12111111, 0x12111111, 0x21111111, 0x21111111, + }; + + fn paletteMode(_: Self) GBA.PaletteMode { + return .Color16; + } + + fn size(_: Self) OAM.ObjectSize { + return .Size32x64; + } + + fn load(_: Self) void { + // In Memory, Tile Map is laid out like: 1 2 3 4 + // 5 6 7 8 + // 9 10 11 12 + // 13 14 15 16 + // 17 18 19 20 + // 21 22 23 24 + // 25 26 27 28 + // 29 30 31 32 + + const px_width = 8 * 4; + const offset = 0x40 / 4; + const len = px_width * @sizeOf(u32); + + GBA.memcpy32(GBA.SPRITE_VRAM, &Self.tiles[0], len); + GBA.memcpy32(GBA.SPRITE_VRAM + (px_width * offset), &Self.tiles[px_width], len); + GBA.memcpy32(GBA.SPRITE_VRAM + (px_width * (offset * 2)), &Self.tiles[px_width * 2], len); + GBA.memcpy32(GBA.SPRITE_VRAM + (px_width * (offset * 3)), &Self.tiles[px_width * 3], len); + GBA.memcpy32(GBA.SPRITE_VRAM + (px_width * (offset * 4)), &Self.tiles[px_width * 4], len); + GBA.memcpy32(GBA.SPRITE_VRAM + (px_width * (offset * 5)), &Self.tiles[px_width * 5], len); + GBA.memcpy32(GBA.SPRITE_VRAM + (px_width * (offset * 6)), &Self.tiles[px_width * 6], len); + GBA.memcpy32(GBA.SPRITE_VRAM + (px_width * (offset * 7)), &Self.tiles[px_width * 7], len); // Palette GBA.memcpy32(GBA.OBJ_PALETTE_RAM, &Self.pal, Self.pal.len * @sizeOf(u32));