romdevtools 0.16.0 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +75 -16
- package/CHANGELOG.md +316 -0
- package/examples/README.md +2 -0
- package/examples/atari2600/templates/platformer.asm +460 -0
- package/examples/atari2600/templates/racing.asm +463 -0
- package/examples/atari2600/templates/shmup.asm +386 -0
- package/examples/atari2600/templates/sports.asm +362 -0
- package/examples/atari7800/templates/default.c +49 -5
- package/examples/atari7800/templates/hello_sprite.c +48 -4
- package/examples/atari7800/templates/music_demo.c +47 -2
- package/examples/atari7800/templates/platformer.c +43 -4
- package/examples/atari7800/templates/puzzle.c +39 -4
- package/examples/atari7800/templates/racing.c +39 -4
- package/examples/atari7800/templates/shmup.c +40 -2
- package/examples/atari7800/templates/sports.c +36 -5
- package/examples/c64/templates/platformer.c +19 -5
- package/examples/c64/templates/puzzle.c +32 -2
- package/examples/c64/templates/shmup.c +28 -2
- package/examples/c64/templates/sports.c +30 -2
- package/examples/c64/templates/tile_engine.c +77 -27
- package/examples/gb/templates/default.c +110 -16
- package/examples/gb/templates/hello_sprite.c +15 -6
- package/examples/gb/templates/music_demo.c +36 -0
- package/examples/gb/templates/platformer.c +28 -6
- package/examples/gb/templates/puzzle.c +35 -4
- package/examples/gb/templates/racing.c +75 -10
- package/examples/gb/templates/shmup.c +41 -3
- package/examples/gb/templates/sports.c +51 -3
- package/examples/gb/templates/tile_engine.c +3 -2
- package/examples/gba/templates/gba_hello.c +29 -11
- package/examples/gba/templates/maxmod_demo.c +36 -2
- package/examples/gba/templates/platformer.c +3 -1
- package/examples/gba/templates/puzzle.c +15 -3
- package/examples/gba/templates/racing.c +65 -3
- package/examples/gba/templates/shmup.c +41 -4
- package/examples/gba/templates/sports.c +36 -2
- package/examples/gba/templates/tonc_hello.c +41 -5
- package/examples/gba/templates/tonc_hello_sprite.c +35 -1
- package/examples/gbc/templates/default.c +103 -26
- package/examples/gbc/templates/hello_sprite.c +12 -3
- package/examples/gbc/templates/music_demo.c +56 -12
- package/examples/gbc/templates/platformer.c +28 -6
- package/examples/gbc/templates/puzzle.c +35 -4
- package/examples/gbc/templates/racing.c +88 -21
- package/examples/gbc/templates/shmup.c +37 -3
- package/examples/gbc/templates/sports.c +48 -3
- package/examples/gbc/templates/tile_engine.c +3 -2
- package/examples/genesis/main.s +53 -1
- package/examples/genesis/templates/hello_sprite.c +25 -3
- package/examples/genesis/templates/puzzle.c +37 -3
- package/examples/genesis/templates/racing.c +44 -11
- package/examples/genesis/templates/sgdk_hello.c +34 -1
- package/examples/genesis/templates/shmup.c +31 -1
- package/examples/genesis/templates/shmup_2p.c +31 -0
- package/examples/genesis/templates/xgm2_demo.c +20 -0
- package/examples/gg/templates/default.c +56 -18
- package/examples/gg/templates/hello_sprite.c +25 -2
- package/examples/gg/templates/music_demo.c +24 -2
- package/examples/gg/templates/platformer.c +18 -12
- package/examples/gg/templates/puzzle.c +38 -7
- package/examples/gg/templates/racing.c +58 -9
- package/examples/gg/templates/shmup.c +47 -3
- package/examples/gg/templates/sports.c +57 -16
- package/examples/gg/templates/tile_engine.c +12 -6
- package/examples/lynx/templates/default.c +39 -8
- package/examples/lynx/templates/hello_sprite.c +15 -1
- package/examples/lynx/templates/music_demo.c +13 -1
- package/examples/lynx/templates/puzzle.c +28 -1
- package/examples/lynx/templates/racing.c +34 -7
- package/examples/lynx/templates/shmup.c +42 -3
- package/examples/lynx/templates/sports.c +29 -2
- package/examples/msx/platformer/main.c +213 -0
- package/examples/msx/puzzle/main.c +250 -0
- package/examples/msx/racing/main.c +249 -0
- package/examples/msx/shmup/main.c +288 -0
- package/examples/msx/sports/main.c +182 -0
- package/examples/nes/templates/default.c +67 -19
- package/examples/nes/templates/hello_sprite.c +35 -0
- package/examples/nes/templates/music_demo.c +40 -0
- package/examples/nes/templates/platformer.c +65 -6
- package/examples/nes/templates/puzzle.c +67 -6
- package/examples/nes/templates/racing.c +45 -13
- package/examples/nes/templates/shmup.c +51 -2
- package/examples/nes/templates/sports.c +51 -6
- package/examples/pce/catch_game/main.c +22 -3
- package/examples/pce/music_sfx/main.c +28 -1
- package/examples/pce/platformer/main.c +283 -0
- package/examples/pce/puzzle/main.c +304 -0
- package/examples/pce/racing/main.c +304 -0
- package/examples/pce/shmup/main.c +346 -0
- package/examples/pce/sports/main.c +254 -0
- package/examples/pce/sprite_move/main.c +7 -2
- package/examples/sms/main.c +35 -6
- package/examples/sms/templates/hello_sprite.c +29 -3
- package/examples/sms/templates/music_demo.c +18 -4
- package/examples/sms/templates/puzzle.c +34 -5
- package/examples/sms/templates/racing.c +39 -2
- package/examples/sms/templates/shmup.c +41 -2
- package/examples/sms/templates/shmup_2p.c +24 -1
- package/examples/sms/templates/sports.c +47 -4
- package/examples/snes/main.asm +108 -17
- package/examples/snes/templates/c-hello-data.asm +23 -0
- package/examples/snes/templates/c-hello.c +18 -1
- package/examples/snes/templates/default.c +50 -28
- package/examples/snes/templates/hello_sprite-data.asm +23 -0
- package/examples/snes/templates/hello_sprite.c +17 -1
- package/examples/snes/templates/music_demo-data.asm +23 -0
- package/examples/snes/templates/music_demo.c +22 -4
- package/examples/snes/templates/platformer-data.asm +22 -0
- package/examples/snes/templates/platformer.c +20 -2
- package/examples/snes/templates/puzzle-data.asm +22 -0
- package/examples/snes/templates/puzzle.c +21 -2
- package/examples/snes/templates/racing-data.asm +22 -0
- package/examples/snes/templates/racing.c +17 -1
- package/examples/snes/templates/shmup-data.asm +22 -0
- package/examples/snes/templates/shmup.c +20 -1
- package/examples/snes/templates/sports-data.asm +22 -0
- package/examples/snes/templates/sports.c +16 -1
- package/package.json +1 -1
- package/src/cheats/gamegenie.js +0 -1
- package/src/cli/smoke.js +1 -3
- package/src/cores/wasm/vice_x64_libretro.js +1 -1
- package/src/cores/wasm/vice_x64_libretro.wasm +0 -0
- package/src/host/LibretroHost.js +191 -16
- package/src/host/callbacks.js +9 -1
- package/src/host/chafa-render.js +2 -0
- package/src/host/dsp-state.js +2 -2
- package/src/host/gpgx-state.js +4 -0
- package/src/host/types.js +15 -8
- package/src/http/routes.js +1 -1
- package/src/http/tool-registry.js +26 -1
- package/src/mcp/server.js +1 -1
- package/src/mcp/state.js +36 -0
- package/src/mcp/tools/address-to-symbol.js +0 -1
- package/src/mcp/tools/art-loaders.js +1 -1
- package/src/mcp/tools/cart-parts.js +75 -4
- package/src/mcp/tools/classify-region.js +1 -1
- package/src/mcp/tools/diff-roms.js +1 -1
- package/src/mcp/tools/disasm-rebuild.js +507 -0
- package/src/mcp/tools/disasm.js +97 -9
- package/src/mcp/tools/find-references.js +1 -2
- package/src/mcp/tools/font-map.js +1 -1
- package/src/mcp/tools/frame.js +168 -3
- package/src/mcp/tools/index.js +0 -49
- package/src/mcp/tools/input-layout.js +0 -1
- package/src/mcp/tools/input.js +33 -3
- package/src/mcp/tools/lifecycle.js +18 -4
- package/src/mcp/tools/lospec.js +0 -19
- package/src/mcp/tools/platform-docs.js +1 -1
- package/src/mcp/tools/platform-tools.js +4 -4
- package/src/mcp/tools/project.js +54 -11
- package/src/mcp/tools/reinject.js +0 -1
- package/src/mcp/tools/rom-id.js +2 -2
- package/src/mcp/tools/snippets.js +2 -2
- package/src/mcp/tools/sprite-pipeline.js +1 -2
- package/src/mcp/tools/state.js +201 -14
- package/src/mcp/tools/tile-inspect.js +1 -1
- package/src/mcp/tools/toolchain.js +105 -12
- package/src/mcp/tools/watch-memory.js +137 -16
- package/src/platforms/_guides/ROMHACKING_PLAYBOOK.md +34 -0
- package/src/platforms/atari2600/TROUBLESHOOTING.md +6 -0
- package/src/platforms/atari7800/TROUBLESHOOTING.md +6 -0
- package/src/platforms/c64/MENTAL_MODEL.md +45 -1
- package/src/platforms/c64/TROUBLESHOOTING.md +6 -0
- package/src/platforms/c64/d64.js +280 -0
- package/src/platforms/c64/sid.js +0 -2
- package/src/platforms/common/metasprite-adapters.js +1 -1
- package/src/platforms/common/metasprite-codegen.js +3 -3
- package/src/platforms/common/registers.js +5 -3
- package/src/platforms/gb/MENTAL_MODEL.md +10 -0
- package/src/platforms/gb/TROUBLESHOOTING.md +6 -0
- package/src/platforms/gb/lib/c/gb_runtime.c +4 -4
- package/src/platforms/gba/TROUBLESHOOTING.md +6 -0
- package/src/platforms/gbc/TROUBLESHOOTING.md +6 -0
- package/src/platforms/gbc/lib/c/gb_runtime.c +4 -4
- package/src/platforms/genesis/TROUBLESHOOTING.md +6 -0
- package/src/platforms/gg/TROUBLESHOOTING.md +6 -0
- package/src/platforms/lynx/TROUBLESHOOTING.md +6 -0
- package/src/platforms/msx/MENTAL_MODEL.md +10 -6
- package/src/platforms/msx/TROUBLESHOOTING.md +6 -0
- package/src/platforms/nes/MENTAL_MODEL.md +63 -2
- package/src/platforms/nes/TROUBLESHOOTING.md +6 -0
- package/src/platforms/nes/image-to-tilemap.js +3 -0
- package/src/platforms/nes/lib/asm/famitone2.s +5 -1
- package/src/platforms/pce/MENTAL_MODEL.md +9 -4
- package/src/platforms/pce/TROUBLESHOOTING.md +6 -0
- package/src/platforms/pce/lib/c/pce_video.c +1 -1
- package/src/platforms/sms/TROUBLESHOOTING.md +6 -0
- package/src/platforms/snes/TROUBLESHOOTING.md +6 -0
- package/src/platforms/snes/brr.js +0 -2
- package/src/playtest/playtest.js +0 -7
- package/src/rom-id/identifier.js +15 -0
- package/src/toolchains/asar/asar.js +0 -9
- package/src/toolchains/assemble-snippet.js +30 -12
- package/src/toolchains/cc65/ines.js +145 -0
- package/src/toolchains/cc65/presets/nes/chr-ram-runtime.cfg +14 -1
- package/src/toolchains/cc65/presets/nes/chr-rom.cfg +83 -0
- package/src/toolchains/cc65/presets/nes/chr-rom.crt0.s +153 -0
- package/src/toolchains/common/reassemble.js +10 -3
- package/src/toolchains/common/sdk-cache.js +1 -1
- package/src/toolchains/genesis-c/genesis-c.js +5 -3
- package/src/toolchains/index.js +27 -3
- package/src/toolchains/parse-errors.js +78 -1
- package/src/toolchains/sdcc/preflight-lint.js +5 -1
- package/src/toolchains/sdcc/sdcc.js +1 -1
- package/src/toolchains/sjasm/sjasm.js +1 -1
- package/src/toolchains/snes-c/snes-c.js +2 -2
- package/src/toolchains/vasm68k/vasm68k.js +2 -4
- package/src/toolchains/wladx/wladx.js +1 -1
|
@@ -15,6 +15,7 @@ extern void sms_vdp_display_on(void);
|
|
|
15
15
|
extern void sms_vdp_set_addr(uint16_t addr, uint8_t prefix);
|
|
16
16
|
extern void sms_load_palette(const uint8_t *palette);
|
|
17
17
|
extern void sms_load_tiles(uint16_t vram_dest, const uint8_t *src, uint16_t byte_count);
|
|
18
|
+
extern void sms_set_tilemap_cell(uint8_t row, uint8_t col, uint8_t tile_idx, uint8_t attr);
|
|
18
19
|
extern void sms_vblank_wait(void);
|
|
19
20
|
extern uint8_t sms_joypad_read(void);
|
|
20
21
|
extern void sms_sprite_init(void);
|
|
@@ -29,13 +30,49 @@ extern void sms_sat_upload(void);
|
|
|
29
30
|
#define T_ENEMY 2
|
|
30
31
|
|
|
31
32
|
static const uint8_t palette[32] = {
|
|
32
|
-
|
|
33
|
+
/* BG: 0 = backdrop, 1 = deep space blue, 2 = lighter space blue, 3 = star white */
|
|
34
|
+
0x10,0x08,0x20,0x3F, 0x00,0x00,0x00,0x00,
|
|
33
35
|
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
|
|
34
36
|
/* Sprite palette: white, yellow, red */
|
|
35
37
|
0x00,0x3F,0x0F,0x03, 0x00,0x00,0x00,0x00,
|
|
36
38
|
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
|
|
37
39
|
};
|
|
38
40
|
|
|
41
|
+
/* Three BG tiles for the starfield, loaded into the BG tile bank at $0000:
|
|
42
|
+
* tile 0 = deep space (solid colour 1)
|
|
43
|
+
* tile 1 = lighter space band (solid colour 2)
|
|
44
|
+
* tile 2 = space with a star (mostly colour 1, one colour-3 pixel) */
|
|
45
|
+
static const uint8_t bg_tiles[96] = {
|
|
46
|
+
/* tile 0 = deep space (colour 1 -> plane 0 set) */
|
|
47
|
+
0xFF,0x00,0x00,0x00, 0xFF,0x00,0x00,0x00,
|
|
48
|
+
0xFF,0x00,0x00,0x00, 0xFF,0x00,0x00,0x00,
|
|
49
|
+
0xFF,0x00,0x00,0x00, 0xFF,0x00,0x00,0x00,
|
|
50
|
+
0xFF,0x00,0x00,0x00, 0xFF,0x00,0x00,0x00,
|
|
51
|
+
/* tile 1 = lighter band (colour 2 -> plane 1 set) */
|
|
52
|
+
0x00,0xFF,0x00,0x00, 0x00,0xFF,0x00,0x00,
|
|
53
|
+
0x00,0xFF,0x00,0x00, 0x00,0xFF,0x00,0x00,
|
|
54
|
+
0x00,0xFF,0x00,0x00, 0x00,0xFF,0x00,0x00,
|
|
55
|
+
0x00,0xFF,0x00,0x00, 0x00,0xFF,0x00,0x00,
|
|
56
|
+
/* tile 2 = deep space + a star: row 3 col 3 = colour 3 (planes 0+1) */
|
|
57
|
+
0xFF,0x00,0x00,0x00, 0xFF,0x00,0x00,0x00,
|
|
58
|
+
0xFF,0x00,0x00,0x00, 0xFF,0x10,0x00,0x00,
|
|
59
|
+
0xFF,0x00,0x00,0x00, 0xFF,0x00,0x00,0x00,
|
|
60
|
+
0xFF,0x00,0x00,0x00, 0xFF,0x00,0x00,0x00,
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/* Paint the whole 32x24 SMS screen with a banded starfield so the screen
|
|
64
|
+
* is clearly space, not a flat backdrop. BG tile bank is $0000. */
|
|
65
|
+
static void draw_starfield(void) {
|
|
66
|
+
uint8_t row, col;
|
|
67
|
+
for (row = 0; row < 24; row++) {
|
|
68
|
+
for (col = 0; col < 32; col++) {
|
|
69
|
+
uint8_t t = (row & 2) ? 1 : 0; /* alternating depth bands */
|
|
70
|
+
if (((row * 7 + col * 5) & 7) == 0) t = 2; /* sparse stars */
|
|
71
|
+
sms_set_tilemap_cell(row, col, t, 0);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
39
76
|
static const uint8_t sprite_tiles[32 * 3] = {
|
|
40
77
|
/* T_SHIP — diamond using colour 1 (white) */
|
|
41
78
|
0x18,0x00,0x00,0x00, 0x3C,0x00,0x00,0x00,
|
|
@@ -96,7 +133,9 @@ void main(void) {
|
|
|
96
133
|
|
|
97
134
|
sms_vdp_init();
|
|
98
135
|
sms_load_palette(palette);
|
|
99
|
-
sms_load_tiles(
|
|
136
|
+
sms_load_tiles(0x0000, bg_tiles, 96); /* BG tiles -> BG bank $0000 */
|
|
137
|
+
sms_load_tiles(0x2000, sprite_tiles, 32 * 3); /* sprite tiles -> $2000 */
|
|
138
|
+
draw_starfield();
|
|
100
139
|
|
|
101
140
|
player.x = 120; player.y = 160; player.alive = 1;
|
|
102
141
|
{
|
|
@@ -24,6 +24,7 @@ extern void sms_vdp_init(void);
|
|
|
24
24
|
extern void sms_vdp_display_on(void);
|
|
25
25
|
extern void sms_load_palette(const uint8_t *palette);
|
|
26
26
|
extern void sms_load_tiles(uint16_t vram_dest, const uint8_t *src, uint16_t byte_count);
|
|
27
|
+
extern void sms_set_tilemap_cell(uint8_t row, uint8_t col, uint8_t tile_idx, uint8_t attr);
|
|
27
28
|
extern void sms_vblank_wait(void);
|
|
28
29
|
extern uint8_t sms_joypad_read(void);
|
|
29
30
|
extern uint8_t sms_joypad_read_p2(void);
|
|
@@ -40,13 +41,32 @@ extern void sms_sat_upload(void);
|
|
|
40
41
|
#define T_ENEMY 3
|
|
41
42
|
|
|
42
43
|
static const uint8_t palette[32] = {
|
|
43
|
-
|
|
44
|
+
/* BG palette: 0 backdrop space-blue, 1 mid-blue, 2 dark-blue (starfield dither) */
|
|
45
|
+
0x10, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
44
46
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
45
47
|
/* Sprite palette: 1 white (P1), 2 yellow (bullet), 3 red (enemy + P2 highlight) */
|
|
46
48
|
0x00, 0x3F, 0x0F, 0x03, 0x00, 0x00, 0x00, 0x00,
|
|
47
49
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
48
50
|
};
|
|
49
51
|
|
|
52
|
+
/* One dithered BG tile (BG bank $0000): plane0=0xAA/0x55, plane1=0x55/0xAA
|
|
53
|
+
* so pixels alternate colour 1 (mid-blue) and colour 2 (dark-blue) in a fine
|
|
54
|
+
* checkerboard. Filling the name table with it gives a two-tone "space"
|
|
55
|
+
* backdrop so the screen never reads as a single flat colour. */
|
|
56
|
+
static const uint8_t bg_tiles[32] = {
|
|
57
|
+
0xAA,0x55,0x00,0x00, 0x55,0xAA,0x00,0x00,
|
|
58
|
+
0xAA,0x55,0x00,0x00, 0x55,0xAA,0x00,0x00,
|
|
59
|
+
0xAA,0x55,0x00,0x00, 0x55,0xAA,0x00,0x00,
|
|
60
|
+
0xAA,0x55,0x00,0x00, 0x55,0xAA,0x00,0x00,
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
static void draw_bg(void) {
|
|
64
|
+
uint8_t row, col;
|
|
65
|
+
for (row = 0; row < 28; row++)
|
|
66
|
+
for (col = 0; col < 32; col++)
|
|
67
|
+
sms_set_tilemap_cell(row, col, 0, 0);
|
|
68
|
+
}
|
|
69
|
+
|
|
50
70
|
/* 4 sprite tiles back-to-back: P1 ship (col1), P2 ship (col3), bullet (col2), enemy (col3). */
|
|
51
71
|
static const uint8_t sprite_tiles[32 * 4] = {
|
|
52
72
|
/* P1 ship — diamond, colour 1 (plane 0) */
|
|
@@ -112,6 +132,9 @@ void main(void) {
|
|
|
112
132
|
uint8_t prev1 = 0, prev2 = 0;
|
|
113
133
|
sms_vdp_init();
|
|
114
134
|
sms_load_palette(palette);
|
|
135
|
+
/* BG dither tile → BG bank $0000, paint the whole name table. */
|
|
136
|
+
sms_load_tiles(0x0000, bg_tiles, 32);
|
|
137
|
+
draw_bg();
|
|
115
138
|
sms_load_tiles(0x2000, sprite_tiles, 32 * 4);
|
|
116
139
|
|
|
117
140
|
p1.x = 80; p1.y = 160; p1.alive = 1;
|
|
@@ -20,6 +20,7 @@ extern void sms_vdp_init(void);
|
|
|
20
20
|
extern void sms_vdp_display_on(void);
|
|
21
21
|
extern void sms_load_palette(const uint8_t *palette);
|
|
22
22
|
extern void sms_load_tiles(uint16_t vram_dest, const uint8_t *src, uint16_t byte_count);
|
|
23
|
+
extern void sms_set_tilemap_cell(uint8_t row, uint8_t col, uint8_t tile_idx, uint8_t attr);
|
|
23
24
|
extern void sms_vblank_wait(void);
|
|
24
25
|
extern uint8_t sms_joypad_read(void);
|
|
25
26
|
extern uint8_t sms_joypad_read_p2(void);
|
|
@@ -35,7 +36,8 @@ extern void sms_sat_upload(void);
|
|
|
35
36
|
#define PADDLE_X2 232
|
|
36
37
|
|
|
37
38
|
static const uint8_t palette[32] = {
|
|
38
|
-
|
|
39
|
+
/* BG: 0 = backdrop, 1 = court green, 2 = court line / net white */
|
|
40
|
+
0x10, 0x08, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
39
41
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
40
42
|
/* Sprite palette: white at idx 1 */
|
|
41
43
|
0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
@@ -49,6 +51,43 @@ static const uint8_t tile_solid[32] = {
|
|
|
49
51
|
0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00,
|
|
50
52
|
};
|
|
51
53
|
|
|
54
|
+
/* Three BG tiles for the court, loaded into the BG tile bank at $0000:
|
|
55
|
+
* tile 0 = court green (solid colour 1)
|
|
56
|
+
* tile 1 = court line / border (solid colour 2 = white)
|
|
57
|
+
* tile 2 = dashed net (colour 2 vertical stripe on green) */
|
|
58
|
+
static const uint8_t bg_tiles[96] = {
|
|
59
|
+
/* tile 0 = court green (colour 1 -> plane 0 set) */
|
|
60
|
+
0xFF,0x00,0x00,0x00, 0xFF,0x00,0x00,0x00,
|
|
61
|
+
0xFF,0x00,0x00,0x00, 0xFF,0x00,0x00,0x00,
|
|
62
|
+
0xFF,0x00,0x00,0x00, 0xFF,0x00,0x00,0x00,
|
|
63
|
+
0xFF,0x00,0x00,0x00, 0xFF,0x00,0x00,0x00,
|
|
64
|
+
/* tile 1 = court line / border (colour 2 -> plane 1 set) */
|
|
65
|
+
0x00,0xFF,0x00,0x00, 0x00,0xFF,0x00,0x00,
|
|
66
|
+
0x00,0xFF,0x00,0x00, 0x00,0xFF,0x00,0x00,
|
|
67
|
+
0x00,0xFF,0x00,0x00, 0x00,0xFF,0x00,0x00,
|
|
68
|
+
0x00,0xFF,0x00,0x00, 0x00,0xFF,0x00,0x00,
|
|
69
|
+
/* tile 2 = net: centre column colour 2, rest colour 1 (green) */
|
|
70
|
+
0xFF,0x18,0x00,0x00, 0xFF,0x18,0x00,0x00,
|
|
71
|
+
0xFF,0x18,0x00,0x00, 0xFF,0x18,0x00,0x00,
|
|
72
|
+
0xFF,0x18,0x00,0x00, 0xFF,0x18,0x00,0x00,
|
|
73
|
+
0xFF,0x18,0x00,0x00, 0xFF,0x18,0x00,0x00,
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/* Paint the whole 32x24 court: green field, white top/bottom border lines,
|
|
77
|
+
* and a dashed net down the centre column. BG tile bank is $0000. */
|
|
78
|
+
static void draw_court(void) {
|
|
79
|
+
uint8_t row, col;
|
|
80
|
+
for (row = 0; row < 24; row++) {
|
|
81
|
+
for (col = 0; col < 32; col++) {
|
|
82
|
+
uint8_t t = 0; /* green field */
|
|
83
|
+
if (row <= 1 || row >= 22) t = 1; /* white top/bottom lines */
|
|
84
|
+
else if (col == 1 || col == 30) t = 1; /* white sidelines */
|
|
85
|
+
else if (col == 16) t = 2; /* solid centre net */
|
|
86
|
+
sms_set_tilemap_cell(row, col, t, 0);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
52
91
|
static int16_t p1y, p2y, bx, by;
|
|
53
92
|
static int8_t bdx, bdy;
|
|
54
93
|
static uint8_t score_p1, score_p2;
|
|
@@ -72,7 +111,9 @@ void main(void) {
|
|
|
72
111
|
uint8_t i;
|
|
73
112
|
sms_vdp_init();
|
|
74
113
|
sms_load_palette(palette);
|
|
75
|
-
sms_load_tiles(
|
|
114
|
+
sms_load_tiles(0x0000, bg_tiles, 96); /* BG court tiles -> BG bank $0000 */
|
|
115
|
+
sms_load_tiles(0x2000, tile_solid, 32); /* paddle/ball sprite tile -> $2000 */
|
|
116
|
+
draw_court();
|
|
76
117
|
sms_sprite_init();
|
|
77
118
|
sfx_init();
|
|
78
119
|
sms_vdp_display_on();
|
|
@@ -82,6 +123,7 @@ void main(void) {
|
|
|
82
123
|
do {
|
|
83
124
|
uint8_t p1, p2;
|
|
84
125
|
uint8_t slot;
|
|
126
|
+
int16_t target;
|
|
85
127
|
sms_vblank_wait();
|
|
86
128
|
sfx_update();
|
|
87
129
|
|
|
@@ -103,12 +145,13 @@ void main(void) {
|
|
|
103
145
|
if ((p1 & JOY_UP) && p1y > COURT_TOP) p1y -= 2;
|
|
104
146
|
if ((p1 & JOY_DOWN) && p1y < COURT_BOT - PADDLE_H) p1y += 2;
|
|
105
147
|
|
|
106
|
-
/* P2 input if any, otherwise AI.
|
|
148
|
+
/* P2 input if any, otherwise AI. (`target` is declared at the top of the
|
|
149
|
+
* loop body — SDCC is C89, declarations must precede statements.) */
|
|
107
150
|
if (p2 != 0) {
|
|
108
151
|
if ((p2 & JOY_UP) && p2y > COURT_TOP) p2y -= 2;
|
|
109
152
|
if ((p2 & JOY_DOWN) && p2y < COURT_BOT - PADDLE_H) p2y += 2;
|
|
110
153
|
} else {
|
|
111
|
-
|
|
154
|
+
target = by - PADDLE_H / 2;
|
|
112
155
|
if (p2y < target && p2y < COURT_BOT - PADDLE_H) p2y += 1;
|
|
113
156
|
else if (p2y > target && p2y > COURT_TOP) p2y -= 1;
|
|
114
157
|
}
|
package/examples/snes/main.asm
CHANGED
|
@@ -2,32 +2,49 @@
|
|
|
2
2
|
;
|
|
3
3
|
; What this does:
|
|
4
4
|
; 1. Standard SNES reset (sei, clc xce → native mode, stack at $1FFF).
|
|
5
|
-
; 2. Uploads a
|
|
6
|
-
;
|
|
7
|
-
;
|
|
5
|
+
; 2. Uploads a 4-colour palette + two 2bpp tiles to VRAM via DMA.
|
|
6
|
+
; 3. Fills a 32x32 BG1 tilemap with a checkerboard of those two tiles
|
|
7
|
+
; so the whole screen shows a real tiled pattern — NOT a flat one-
|
|
8
|
+
; colour backdrop (which reads as "blank" to a human / the verifier).
|
|
9
|
+
; 4. Points BG1 at the tile + map bases, enables BG1, turns the screen
|
|
10
|
+
; on at full brightness, then parks forever.
|
|
8
11
|
;
|
|
9
|
-
; SUFFICIENT FOR: confirming your toolchain works
|
|
10
|
-
;
|
|
11
|
-
;
|
|
12
|
+
; SUFFICIENT FOR: confirming your toolchain works AND showing your user a
|
|
13
|
+
; real rendered screen in playtest. To go further (sprites, scrolling,
|
|
14
|
+
; sound, a vblank handler) see src/platforms/snes/lib/* snippets:
|
|
12
15
|
;
|
|
13
16
|
; listStarterSnippets({platform:"snes"})
|
|
14
17
|
;
|
|
15
18
|
; The key snippets are:
|
|
16
19
|
; - lorom_header.asm: full SNES header (this scaffold's is minimal)
|
|
17
20
|
; - cgram_upload.asm: palette upload boilerplate
|
|
18
|
-
; - vram_dma_upload.asm: fast tile/map uploads
|
|
21
|
+
; - vram_dma_upload.asm: fast tile/map uploads (used below)
|
|
19
22
|
; - oam_upload.asm: sprite table writes
|
|
20
23
|
; - nmi_safe.asm: vblank handler skeleton
|
|
21
24
|
;
|
|
22
25
|
; BUILD: complete LoROM image, no extra options needed.
|
|
23
|
-
; build({ output: "
|
|
26
|
+
; build({ output: "run", platform: "snes", source: /* this file */ });
|
|
24
27
|
|
|
25
28
|
lorom
|
|
26
29
|
|
|
30
|
+
; ── PPU / DMA registers ────────────────────────────────────────────────
|
|
27
31
|
INIDISP = $2100 ; screen brightness / forced blank
|
|
32
|
+
BGMODE = $2105 ; BG mode + tile-size
|
|
33
|
+
BG1SC = $2107 ; BG1 tilemap base + size
|
|
34
|
+
BG12NBA = $210B ; BG1/BG2 character (tile) base
|
|
35
|
+
TM = $212C ; main-screen layer enable
|
|
28
36
|
NMITIMEN = $4200
|
|
29
37
|
CGADD = $2121
|
|
30
38
|
CGDATA = $2122
|
|
39
|
+
VMAIN = $2115 ; VRAM address increment mode
|
|
40
|
+
VMADDL = $2116 ; VRAM word address (16-bit)
|
|
41
|
+
VMDATAL = $2118 ; VRAM data port (low)
|
|
42
|
+
DMAP0 = $4300 ; DMA0 control
|
|
43
|
+
BBAD0 = $4301 ; DMA0 B-bus address
|
|
44
|
+
A1T0L = $4302 ; DMA0 source address (16-bit)
|
|
45
|
+
A1B0 = $4304 ; DMA0 source bank
|
|
46
|
+
DAS0L = $4305 ; DMA0 byte count (16-bit)
|
|
47
|
+
MDMAEN = $420B ; DMA enable
|
|
31
48
|
|
|
32
49
|
; -----------------------------------------------------------------------
|
|
33
50
|
org $008000
|
|
@@ -40,29 +57,103 @@ START:
|
|
|
40
57
|
txs ; stack at $1FFF
|
|
41
58
|
sep #$20 ; A = 8-bit
|
|
42
59
|
|
|
43
|
-
; Blank screen during init.
|
|
60
|
+
; Blank screen during init; disable NMI/HDMA.
|
|
44
61
|
lda #$80
|
|
45
62
|
sta INIDISP
|
|
46
|
-
|
|
47
|
-
; Disable interrupts.
|
|
48
63
|
stz NMITIMEN
|
|
49
64
|
|
|
50
|
-
;
|
|
51
|
-
;
|
|
65
|
+
; ── Palette → CGRAM ───────────────────────────────────────────
|
|
66
|
+
; 4 colours (2bpp): 0 = blue backdrop, 1 = white, 2 = green,
|
|
67
|
+
; 3 = magenta. BGR-555, little-endian (low byte then high byte).
|
|
52
68
|
stz CGADD
|
|
53
69
|
lda #$00
|
|
54
|
-
sta CGDATA
|
|
70
|
+
sta CGDATA ; colour 0 low ($7C00 = blue)
|
|
71
|
+
lda #$7C
|
|
72
|
+
sta CGDATA ; colour 0 high
|
|
73
|
+
lda #$FF
|
|
74
|
+
sta CGDATA ; colour 1 low ($7FFF = white)
|
|
75
|
+
lda #$7F
|
|
76
|
+
sta CGDATA ; colour 1 high
|
|
77
|
+
lda #$E0
|
|
78
|
+
sta CGDATA ; colour 2 low ($03E0 = green)
|
|
79
|
+
lda #$03
|
|
80
|
+
sta CGDATA ; colour 2 high
|
|
81
|
+
lda #$1F
|
|
82
|
+
sta CGDATA ; colour 3 low ($7C1F = magenta)
|
|
55
83
|
lda #$7C
|
|
56
|
-
sta CGDATA
|
|
84
|
+
sta CGDATA ; colour 3 high
|
|
85
|
+
|
|
86
|
+
; ── Tile CHR → VRAM word $0000 (DMA channel 0) ────────────────
|
|
87
|
+
; Two 8x8 2bpp tiles = 32 bytes. VMAIN $80 = +1 word after the
|
|
88
|
+
; high-byte write; B-bus $18 = VMDATAL (auto-alternates to $2119).
|
|
89
|
+
ldx #$0000
|
|
90
|
+
stx VMADDL
|
|
91
|
+
lda #$80
|
|
92
|
+
sta VMAIN
|
|
93
|
+
lda #$01
|
|
94
|
+
sta DMAP0 ; DMA mode 1 (2 regs, word transfers)
|
|
95
|
+
lda #$18
|
|
96
|
+
sta BBAD0 ; → $2118 / $2119
|
|
97
|
+
ldx #TILES
|
|
98
|
+
stx A1T0L
|
|
99
|
+
lda #TILES>>16
|
|
100
|
+
sta A1B0
|
|
101
|
+
ldx #(TILES_END-TILES)
|
|
102
|
+
stx DAS0L ; byte count
|
|
103
|
+
lda #$01
|
|
104
|
+
sta MDMAEN ; fire channel 0
|
|
105
|
+
|
|
106
|
+
; ── Fill BG1 tilemap → VRAM word $0400 (byte $0800) ───────────
|
|
107
|
+
; A 32x32 map = 1024 entries. Each entry is a word: low byte =
|
|
108
|
+
; tile index, high byte = attributes (0). We write a checkerboard
|
|
109
|
+
; of tile 0 / tile 1 directly through the data port (no source
|
|
110
|
+
; buffer needed). VMAIN already = +1 word per write.
|
|
111
|
+
ldx #$0400
|
|
112
|
+
stx VMADDL
|
|
113
|
+
rep #$20 ; A = 16-bit for word writes
|
|
114
|
+
ldy #$0000 ; entry counter (0..1023)
|
|
115
|
+
.maploop:
|
|
116
|
+
tya
|
|
117
|
+
and #$0001 ; checker by column parity
|
|
118
|
+
sta VMDATAL ; entry = tile 0 or tile 1
|
|
119
|
+
iny
|
|
120
|
+
cpy #1024
|
|
121
|
+
bne .maploop
|
|
122
|
+
sep #$20 ; back to 8-bit A
|
|
57
123
|
|
|
58
|
-
;
|
|
59
|
-
|
|
124
|
+
; ── BG1 base registers ────────────────────────────────────────
|
|
125
|
+
stz BGMODE ; mode 0, 8x8 tiles
|
|
126
|
+
; BG1SC: bits 2-7 = tilemap base in $0400-word units, bits 0-1 =
|
|
127
|
+
; size (00 = 32x32). Map is at word $0400 → base = 1 → ($01<<2)=$04.
|
|
128
|
+
lda #$04
|
|
129
|
+
sta BG1SC
|
|
130
|
+
stz BG12NBA ; BG1 char base = word $0000 (our tiles)
|
|
131
|
+
lda #$01
|
|
132
|
+
sta TM ; enable BG1 on the main screen
|
|
133
|
+
|
|
134
|
+
; ── Screen ON at full brightness ──────────────────────────────
|
|
60
135
|
lda #$0F
|
|
61
136
|
sta INIDISP
|
|
62
137
|
|
|
63
138
|
LOOP:
|
|
64
139
|
bra LOOP
|
|
65
140
|
|
|
141
|
+
; -----------------------------------------------------------------------
|
|
142
|
+
; Tile CHR: two 8x8 2bpp tiles (16 bytes each). 2bpp = 2 bitplanes
|
|
143
|
+
; interleaved per row: byte0=row0 plane0, byte1=row0 plane1, ...
|
|
144
|
+
;
|
|
145
|
+
; Tile 0 — solid colour 1 (plane0 all set, plane1 clear → colour 1).
|
|
146
|
+
; Tile 1 — checker of colour 2 / colour 3 (both planes patterned) so the
|
|
147
|
+
; map's alternating tiles give a busy, multi-colour screen.
|
|
148
|
+
TILES:
|
|
149
|
+
; tile 0 (solid: every pixel colour 1)
|
|
150
|
+
db $FF, $00, $FF, $00, $FF, $00, $FF, $00
|
|
151
|
+
db $FF, $00, $FF, $00, $FF, $00, $FF, $00
|
|
152
|
+
; tile 1 (checkerboard: colour 2 / colour 3 alternating per pixel)
|
|
153
|
+
db $AA, $55, $55, $AA, $AA, $55, $55, $AA
|
|
154
|
+
db $AA, $55, $55, $AA, $AA, $55, $55, $AA
|
|
155
|
+
TILES_END:
|
|
156
|
+
|
|
66
157
|
; -----------------------------------------------------------------------
|
|
67
158
|
; Emulation-mode reset vector (used at boot, before `xce` flips to native).
|
|
68
159
|
; asar's `lorom` directive handles header + rest of vector table padding.
|
|
@@ -320,4 +320,27 @@ palfont:
|
|
|
320
320
|
.db $00, $00, $00, $00, $00, $00, $00, $00
|
|
321
321
|
.db $00, $00
|
|
322
322
|
|
|
323
|
+
|
|
324
|
+
; ── Background wallpaper (one 8x8 4bpp tile, 4 solid colour quadrants) ──
|
|
325
|
+
; Tiled across BG1 it paints the whole screen in four muted colours so the
|
|
326
|
+
; backdrop never reads as flat/blank. Quadrant->colour: TL=1, TR=2, BL=3,
|
|
327
|
+
; BR=4. 4bpp plane order: bytes 0-15 = rows 0-7 plane0/plane1 pairs, bytes
|
|
328
|
+
; 16-31 = rows 0-7 plane2/plane3 pairs.
|
|
329
|
+
tilbg:
|
|
330
|
+
.db $F0, $0F, $F0, $0F, $F0, $0F, $F0, $0F ; rows 0-3: p0=left p1=right
|
|
331
|
+
.db $F0, $F0, $F0, $F0, $F0, $F0, $F0, $F0 ; rows 4-7: p0+p1 = left
|
|
332
|
+
.db $00, $00, $00, $00, $00, $00, $00, $00 ; rows 0-3: p2/p3 = 0
|
|
333
|
+
.db $0F, $00, $0F, $00, $0F, $00, $0F, $00 ; rows 4-7: p2 = right
|
|
334
|
+
|
|
335
|
+
palbg:
|
|
336
|
+
; 16-colour BG palette; only 1-4 used (the four wallpaper quadrant tones).
|
|
337
|
+
.db $00, $00 ; 0 unused (BG fully opaque)
|
|
338
|
+
.db $C4, $30 ; 1 dark blue
|
|
339
|
+
.db $42, $29 ; 2 dark teal
|
|
340
|
+
.db $88, $30 ; 3 dark purple
|
|
341
|
+
.db $C6, $24 ; 4 dark slate
|
|
342
|
+
.db $00, $00, $00, $00, $00, $00, $00, $00
|
|
343
|
+
.db $00, $00, $00, $00, $00, $00, $00, $00
|
|
344
|
+
.db $00, $00, $00, $00, $00, $00
|
|
345
|
+
|
|
323
346
|
.ends
|
|
@@ -27,13 +27,20 @@
|
|
|
27
27
|
#include <snes.h>
|
|
28
28
|
|
|
29
29
|
extern char tilfont, palfont;
|
|
30
|
+
extern char tilbg, palbg; /* wallpaper tile + palette (data.asm) */
|
|
30
31
|
|
|
31
32
|
/* consoleVblank() copies the dirty text tilemap to VRAM during VBlank.
|
|
32
33
|
* It has no public prototype in console.h, so declare it here. Call it
|
|
33
34
|
* once per frame (after WaitForVBlank) or via nmiSet(consoleVblank). */
|
|
34
35
|
extern void consoleVblank(void);
|
|
35
36
|
|
|
37
|
+
/* BG1 wallpaper map: a full 32x32 screen of the 4-colour tile so the
|
|
38
|
+
* screen never reads as a flat/blank backdrop. Filled at runtime. */
|
|
39
|
+
static u16 bg_map[32 * 32];
|
|
40
|
+
|
|
36
41
|
int main(void) {
|
|
42
|
+
u16 i;
|
|
43
|
+
|
|
37
44
|
/* ── 1. PVSnesLib text-mode setup ─────────────────────────────
|
|
38
45
|
* Map + tile-data + palette-offset addresses are conventions —
|
|
39
46
|
* any free VRAM region will work, these match PVSnesLib's
|
|
@@ -54,7 +61,17 @@ int main(void) {
|
|
|
54
61
|
setMode(BG_MODE1, 0);
|
|
55
62
|
bgSetGfxPtr(0, 0x3000);
|
|
56
63
|
bgSetMapPtr(0, 0x6800, SC_32x32);
|
|
57
|
-
|
|
64
|
+
|
|
65
|
+
/* BG1 = full-screen wallpaper so the screen never reads as blank.
|
|
66
|
+
* Tiles -> VRAM $2000, map -> VRAM $4000 (clear of the console gfx
|
|
67
|
+
* $3000 / map $6800). Map entries use palette block 1 (0x0400) so the
|
|
68
|
+
* wallpaper palette doesn't disturb the console font palette in block 0
|
|
69
|
+
* (HUD text stays legible). */
|
|
70
|
+
bgInitTileSet(1, (u8 *)&tilbg, (u8 *)&palbg, 1,
|
|
71
|
+
32, 32, BG_16COLORS, 0x2000);
|
|
72
|
+
for (i = 0; i < 32 * 32; i++) bg_map[i] = 0x0400;
|
|
73
|
+
bgInitMapSet(1, (u8 *)bg_map, sizeof(bg_map), SC_32x32, 0x4000);
|
|
74
|
+
bgSetEnable(1);
|
|
58
75
|
bgSetDisable(2);
|
|
59
76
|
|
|
60
77
|
/* ── 3. Draw text ─────────────────────────────────────────────
|
|
@@ -1,61 +1,83 @@
|
|
|
1
1
|
/* default.c — SNES PVSnesLib starter (C).
|
|
2
2
|
*
|
|
3
|
-
* Smallest "ROM that does something visible"
|
|
4
|
-
*
|
|
5
|
-
* Pressing the d-pad moves the sprite.
|
|
3
|
+
* Smallest "ROM that does something visible": a full-screen diamond-tile
|
|
4
|
+
* background (BG0) with a movable white sprite parked in the centre.
|
|
5
|
+
* Pressing the d-pad moves the sprite. The tiled backdrop means the very
|
|
6
|
+
* first build shows recognizable content, not a flat colour — the SNES
|
|
7
|
+
* equivalent of the "is anything even rendering?" smoke test.
|
|
6
8
|
*
|
|
7
9
|
* Picked as the default SNES template because:
|
|
8
|
-
* - PVSnesLib gives a clean C API (oamSet, padsCurrent
|
|
10
|
+
* - PVSnesLib gives a clean C API (bgInitTileSet, oamSet, padsCurrent…)
|
|
9
11
|
* instead of raw 65816 / direct register pokes.
|
|
10
12
|
* - tcc-65816 builds it in <2s.
|
|
11
|
-
* - You read this file once and know how every SNES C scaffold
|
|
12
|
-
*
|
|
13
|
+
* - You read this file once and know how every SNES C scaffold is
|
|
14
|
+
* structured (hello_sprite, shmup, platformer all extend it).
|
|
15
|
+
*
|
|
16
|
+
* The one footgun this guards against: on the SNES, NOTHING renders until
|
|
17
|
+
* setScreenOn() lifts forced blank (INIDISP $80) AND at least one layer
|
|
18
|
+
* (a BG or the sprite layer) actually has tiles + a non-black palette.
|
|
19
|
+
* Disabling every BG and showing one sprite (the obvious "minimal" move)
|
|
20
|
+
* leaves a near-blank screen — so here we light up BG0 too.
|
|
13
21
|
*
|
|
14
|
-
* For raw 65816 see template:"asm" (kept for cycle-accurate work).
|
|
15
22
|
* For text-mode console output see template:"c_hello".
|
|
16
|
-
* For
|
|
23
|
+
* For raw 65816 see template:"asm" (kept for cycle-accurate work).
|
|
24
|
+
* For genre-shaped scaffolds see scaffold({op:'game', genre:"shmup", ...}).
|
|
17
25
|
*
|
|
18
|
-
* Sibling `data.asm` provides
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* platform:"snes", language:"c",
|
|
22
|
-
* sourcesPaths:{"main.c":"...","data.asm":"..."},
|
|
23
|
-
* })
|
|
26
|
+
* Sibling `data.asm` provides tilsprite (one 8×8 4bpp diamond tile) +
|
|
27
|
+
* palsprite (its 16-colour palette). We reuse that one tile for BOTH the
|
|
28
|
+
* sprite and the BG wallpaper — replace with real gfx4snes .pic/.pal art.
|
|
24
29
|
*/
|
|
25
30
|
#include <snes.h>
|
|
26
31
|
|
|
27
32
|
extern char tilsprite, palsprite;
|
|
28
33
|
|
|
34
|
+
/* A 32×32 BG tilemap (one screen), all pointing at tile 0 = the diamond.
|
|
35
|
+
* SNES map entries are 16-bit (tile# + palette/priority/flip bits); 0x0000
|
|
36
|
+
* = tile 0, palette 0, no flip. 32*32 = 1024 entries = 2048 bytes. We fill
|
|
37
|
+
* it at runtime so the source stays small. */
|
|
38
|
+
static u16 bg_map[32 * 32];
|
|
39
|
+
|
|
29
40
|
int main(void) {
|
|
30
41
|
u16 x = 120, y = 100;
|
|
42
|
+
u16 i;
|
|
31
43
|
|
|
32
|
-
/* BG_MODE1
|
|
33
|
-
*
|
|
44
|
+
/* BG_MODE1: BG0/BG1 are 16-colour, BG2 is 4-colour — standard mix.
|
|
45
|
+
* We use BG0 for the wallpaper and the sprite layer on top. */
|
|
34
46
|
setMode(BG_MODE1, 0);
|
|
35
|
-
bgSetDisable(0);
|
|
36
47
|
bgSetDisable(1);
|
|
37
48
|
bgSetDisable(2);
|
|
38
49
|
|
|
39
|
-
/*
|
|
40
|
-
*
|
|
41
|
-
|
|
50
|
+
/* Load the diamond tile + its palette as BG0's tileset. Tile gfx go to
|
|
51
|
+
* VRAM $2000, palette into BG palette 0. 32 bytes of tile (one 8×8 4bpp
|
|
52
|
+
* tile), 32 bytes of palette (16 colours × 2). */
|
|
53
|
+
bgInitTileSet(0, (u8 *)&tilsprite, (u8 *)&palsprite,
|
|
54
|
+
0, /* palette entry 0 */
|
|
55
|
+
32, /* tile data size */
|
|
56
|
+
32, /* palette size */
|
|
57
|
+
BG_16COLORS, /* colour mode */
|
|
58
|
+
0x2000); /* VRAM addr for BG0 tiles */
|
|
59
|
+
|
|
60
|
+
/* Fill the map with tile 0 and upload it to VRAM $6000. */
|
|
61
|
+
for (i = 0; i < 32 * 32; i++) bg_map[i] = 0x0000;
|
|
62
|
+
bgInitMapSet(0, (u8 *)bg_map, sizeof(bg_map), SC_32x32, 0x6000);
|
|
63
|
+
|
|
64
|
+
bgSetEnable(0);
|
|
42
65
|
|
|
43
|
-
/* Upload
|
|
44
|
-
*
|
|
45
|
-
* are 8×8, large 16×16 (we use small). */
|
|
66
|
+
/* Upload the same tile as a sprite (VRAM $0000, OBJ palette slot 0) so
|
|
67
|
+
* the movable sprite reads distinctly on top of the wallpaper. */
|
|
46
68
|
oamInitGfxSet(&tilsprite, 32, &palsprite, 32,
|
|
47
69
|
0, /* OBJ palette slot */
|
|
48
70
|
0x0000, /* VRAM address for sprite tiles */
|
|
49
71
|
OBJ_SIZE8_L16);
|
|
50
72
|
|
|
51
|
-
/* Place sprite #0 at the centre. */
|
|
73
|
+
/* Place sprite #0 at the centre, highest priority so it sits over BG0. */
|
|
52
74
|
oamSet(0, x, y,
|
|
53
|
-
3 /*
|
|
54
|
-
0 /*
|
|
75
|
+
3 /* priority */, 0 /* no flip */, 0 /* palette */,
|
|
76
|
+
0 /* tile index */, 0 /* objsize */);
|
|
55
77
|
oamSetEx(0, OBJ_SMALL, OBJ_SHOW);
|
|
56
78
|
|
|
57
|
-
/* Until setScreenOn() fires, the SNES holds forced blank
|
|
58
|
-
*
|
|
79
|
+
/* Until setScreenOn() fires, the SNES holds forced blank (INIDISP $80)
|
|
80
|
+
* and nothing renders. */
|
|
59
81
|
setScreenOn();
|
|
60
82
|
|
|
61
83
|
while (1) {
|
|
@@ -340,4 +340,27 @@ palsprite:
|
|
|
340
340
|
.db $00, $00, $00, $00, $00, $00, $00, $00
|
|
341
341
|
.db $00, $00, $00, $00, $00, $00, $00, $00
|
|
342
342
|
|
|
343
|
+
|
|
344
|
+
; ── Background wallpaper (one 8x8 4bpp tile, 4 solid colour quadrants) ──
|
|
345
|
+
; Tiled across BG1 it paints the whole screen in four muted colours so the
|
|
346
|
+
; backdrop never reads as flat/blank. Quadrant->colour: TL=1, TR=2, BL=3,
|
|
347
|
+
; BR=4. 4bpp plane order: bytes 0-15 = rows 0-7 plane0/plane1 pairs, bytes
|
|
348
|
+
; 16-31 = rows 0-7 plane2/plane3 pairs.
|
|
349
|
+
tilbg:
|
|
350
|
+
.db $F0, $0F, $F0, $0F, $F0, $0F, $F0, $0F ; rows 0-3: p0=left p1=right
|
|
351
|
+
.db $F0, $F0, $F0, $F0, $F0, $F0, $F0, $F0 ; rows 4-7: p0+p1 = left
|
|
352
|
+
.db $00, $00, $00, $00, $00, $00, $00, $00 ; rows 0-3: p2/p3 = 0
|
|
353
|
+
.db $0F, $00, $0F, $00, $0F, $00, $0F, $00 ; rows 4-7: p2 = right
|
|
354
|
+
|
|
355
|
+
palbg:
|
|
356
|
+
; 16-colour BG palette; only 1-4 used (the four wallpaper quadrant tones).
|
|
357
|
+
.db $00, $00 ; 0 unused (BG fully opaque)
|
|
358
|
+
.db $C4, $30 ; 1 dark blue
|
|
359
|
+
.db $42, $29 ; 2 dark teal
|
|
360
|
+
.db $88, $30 ; 3 dark purple
|
|
361
|
+
.db $C6, $24 ; 4 dark slate
|
|
362
|
+
.db $00, $00, $00, $00, $00, $00, $00, $00
|
|
363
|
+
.db $00, $00, $00, $00, $00, $00, $00, $00
|
|
364
|
+
.db $00, $00, $00, $00, $00, $00
|
|
365
|
+
|
|
343
366
|
.ends
|
|
@@ -24,14 +24,20 @@
|
|
|
24
24
|
|
|
25
25
|
extern char tilfont, palfont;
|
|
26
26
|
extern char tilsprite, palsprite;
|
|
27
|
+
extern char tilbg, palbg; /* wallpaper tile + palette (data.asm) */
|
|
27
28
|
|
|
28
29
|
/* consoleVblank() copies the dirty text tilemap to VRAM during VBlank.
|
|
29
30
|
* No public prototype in console.h, so declare it; call once per frame. */
|
|
30
31
|
extern void consoleVblank(void);
|
|
31
32
|
|
|
33
|
+
/* BG1 wallpaper map: a full 32x32 screen of the 4-colour tile so the
|
|
34
|
+
* screen never reads as a flat/blank backdrop. Filled at runtime. */
|
|
35
|
+
static u16 bg_map[32 * 32];
|
|
36
|
+
|
|
32
37
|
int main(void) {
|
|
33
38
|
u16 x = 120, y = 100;
|
|
34
39
|
u16 prev = 0;
|
|
40
|
+
u16 i;
|
|
35
41
|
|
|
36
42
|
/* Text setup — same layout as c-hello. */
|
|
37
43
|
consoleSetTextMapPtr(0x6800);
|
|
@@ -44,7 +50,17 @@ int main(void) {
|
|
|
44
50
|
* registers — point BG0 at the same font ($3000) + map ($6800). */
|
|
45
51
|
bgSetGfxPtr(0, 0x3000);
|
|
46
52
|
bgSetMapPtr(0, 0x6800, SC_32x32);
|
|
47
|
-
|
|
53
|
+
|
|
54
|
+
/* BG1 = full-screen wallpaper so the screen never reads as blank.
|
|
55
|
+
* Tiles -> VRAM $2000, map -> VRAM $4000 (clear of sprites $0000 and
|
|
56
|
+
* the console gfx $3000 / map $6800). Map entries use palette block 1
|
|
57
|
+
* (0x0400) so the wallpaper palette doesn't disturb the console font
|
|
58
|
+
* palette in block 0 (status text stays legible). */
|
|
59
|
+
bgInitTileSet(1, (u8 *)&tilbg, (u8 *)&palbg, 1,
|
|
60
|
+
32, 32, BG_16COLORS, 0x2000);
|
|
61
|
+
for (i = 0; i < 32 * 32; i++) bg_map[i] = 0x0400;
|
|
62
|
+
bgInitMapSet(1, (u8 *)bg_map, sizeof(bg_map), SC_32x32, 0x4000);
|
|
63
|
+
bgSetEnable(1);
|
|
48
64
|
bgSetDisable(2);
|
|
49
65
|
|
|
50
66
|
/* OAM init — sprite tiles at VRAM $0000, 8x8 default. */
|
|
@@ -315,4 +315,27 @@ palfont:
|
|
|
315
315
|
.db $00, $00, $00, $00, $00, $00, $00, $00
|
|
316
316
|
.db $00, $00
|
|
317
317
|
|
|
318
|
+
|
|
319
|
+
; ── Background wallpaper (one 8x8 4bpp tile, 4 solid colour quadrants) ──
|
|
320
|
+
; Tiled across BG1 it paints the whole screen in four muted colours so the
|
|
321
|
+
; backdrop never reads as flat/blank. Quadrant->colour: TL=1, TR=2, BL=3,
|
|
322
|
+
; BR=4. 4bpp plane order: bytes 0-15 = rows 0-7 plane0/plane1 pairs, bytes
|
|
323
|
+
; 16-31 = rows 0-7 plane2/plane3 pairs.
|
|
324
|
+
tilbg:
|
|
325
|
+
.db $F0, $0F, $F0, $0F, $F0, $0F, $F0, $0F ; rows 0-3: p0=left p1=right
|
|
326
|
+
.db $F0, $F0, $F0, $F0, $F0, $F0, $F0, $F0 ; rows 4-7: p0+p1 = left
|
|
327
|
+
.db $00, $00, $00, $00, $00, $00, $00, $00 ; rows 0-3: p2/p3 = 0
|
|
328
|
+
.db $0F, $00, $0F, $00, $0F, $00, $0F, $00 ; rows 4-7: p2 = right
|
|
329
|
+
|
|
330
|
+
palbg:
|
|
331
|
+
; 16-colour BG palette; only 1-4 used (the four wallpaper quadrant tones).
|
|
332
|
+
.db $00, $00 ; 0 unused (BG fully opaque)
|
|
333
|
+
.db $C4, $30 ; 1 dark blue
|
|
334
|
+
.db $42, $29 ; 2 dark teal
|
|
335
|
+
.db $88, $30 ; 3 dark purple
|
|
336
|
+
.db $C6, $24 ; 4 dark slate
|
|
337
|
+
.db $00, $00, $00, $00, $00, $00, $00, $00
|
|
338
|
+
.db $00, $00, $00, $00, $00, $00, $00, $00
|
|
339
|
+
.db $00, $00, $00, $00, $00, $00
|
|
340
|
+
|
|
318
341
|
.ends
|