romdevtools 0.71.0 → 0.84.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.
Files changed (113) hide show
  1. package/AGENTS.md +19 -16
  2. package/CHANGELOG.md +196 -0
  3. package/README.md +5 -5
  4. package/examples/README.md +1 -0
  5. package/examples/gametank/templates/gt_draw.h +91 -0
  6. package/examples/gametank/templates/gt_hud.h +89 -0
  7. package/examples/gametank/templates/gt_palette.h +59 -0
  8. package/examples/gametank/templates/gt_sound.h +90 -0
  9. package/examples/gametank/templates/gt_sprites.h +53 -0
  10. package/examples/gametank/templates/platformer.c +318 -0
  11. package/examples/gametank/templates/puzzle.c +295 -0
  12. package/examples/gametank/templates/racing.c +139 -0
  13. package/examples/gametank/templates/shmup.c +277 -0
  14. package/examples/gametank/templates/sports.c +119 -0
  15. package/package.json +23 -22
  16. package/src/cores/capabilities.js +24 -0
  17. package/src/cores/registry.js +7 -1
  18. package/src/host/LibretroHost.js +90 -17
  19. package/src/host/callbacks.js +20 -2
  20. package/src/host/cpu-state.js +17 -0
  21. package/src/host/gametank-acp-state.js +53 -0
  22. package/src/http/skill-doc.js +10 -6
  23. package/src/mcp/tools/audio.js +1 -1
  24. package/src/mcp/tools/cart-parts.js +76 -0
  25. package/src/mcp/tools/lifecycle.js +1 -1
  26. package/src/mcp/tools/platform-tools.js +9 -1
  27. package/src/mcp/tools/platforms.js +46 -10
  28. package/src/mcp/tools/toolchain.js +35 -10
  29. package/src/platforms/gametank/lib/gt/audio/acp_image.bin +0 -0
  30. package/src/platforms/gametank/lib/gt/audio/audio_coprocessor.c +55 -0
  31. package/src/platforms/gametank/lib/gt/audio/audio_coprocessor.h +34 -0
  32. package/src/platforms/gametank/lib/gt/audio/audio_fw.asm +223 -0
  33. package/src/platforms/gametank/lib/gt/audio/audio_fw_blob.s +8 -0
  34. package/src/platforms/gametank/lib/gt/audio/instruments.c +79 -0
  35. package/src/platforms/gametank/lib/gt/audio/instruments.h +25 -0
  36. package/src/platforms/gametank/lib/gt/audio/music.c +370 -0
  37. package/src/platforms/gametank/lib/gt/audio/music.h +35 -0
  38. package/src/platforms/gametank/lib/gt/audio/note_numbers.h +132 -0
  39. package/src/platforms/gametank/lib/gt/audio/scaled_sines.raw +0 -0
  40. package/src/platforms/gametank/lib/gt/audio/sine_256_-63_63.bin +0 -0
  41. package/src/platforms/gametank/lib/gt/banking.c +29 -0
  42. package/src/platforms/gametank/lib/gt/banking.h +8 -0
  43. package/src/platforms/gametank/lib/gt/banking2.s +41 -0
  44. package/src/platforms/gametank/lib/gt/crt0.s +102 -0
  45. package/src/platforms/gametank/lib/gt/draw_logo.s +55 -0
  46. package/src/platforms/gametank/lib/gt/feature/persist/persist.c +103 -0
  47. package/src/platforms/gametank/lib/gt/feature/persist/persist.h +13 -0
  48. package/src/platforms/gametank/lib/gt/feature/random/random.c +40 -0
  49. package/src/platforms/gametank/lib/gt/feature/random/random.h +18 -0
  50. package/src/platforms/gametank/lib/gt/feature/text/text.c +111 -0
  51. package/src/platforms/gametank/lib/gt/feature/text/text.h +25 -0
  52. package/src/platforms/gametank/lib/gt/gametank.c +12 -0
  53. package/src/platforms/gametank/lib/gt/gametank.h +80 -0
  54. package/src/platforms/gametank/lib/gt/gametank_logo.inc +393 -0
  55. package/src/platforms/gametank/lib/gt/gen/assets/assets_index.h +9 -0
  56. package/src/platforms/gametank/lib/gt/gen/assets/sdk_default.h +5 -0
  57. package/src/platforms/gametank/lib/gt/gen/bank_nums.h +11 -0
  58. package/src/platforms/gametank/lib/gt/gen/modules_enabled.h +4 -0
  59. package/src/platforms/gametank/lib/gt/gen/modules_enabled.inc +4 -0
  60. package/src/platforms/gametank/lib/gt/gfx/draw_direct.c +132 -0
  61. package/src/platforms/gametank/lib/gt/gfx/draw_direct.h +75 -0
  62. package/src/platforms/gametank/lib/gt/gfx/draw_queue.c +177 -0
  63. package/src/platforms/gametank/lib/gt/gfx/draw_queue.h +35 -0
  64. package/src/platforms/gametank/lib/gt/gfx/draw_util.s +157 -0
  65. package/src/platforms/gametank/lib/gt/gfx/gfx_sys.c +43 -0
  66. package/src/platforms/gametank/lib/gt/gfx/gfx_sys.h +46 -0
  67. package/src/platforms/gametank/lib/gt/gfx/sprites.c +216 -0
  68. package/src/platforms/gametank/lib/gt/gfx/sprites.h +41 -0
  69. package/src/platforms/gametank/lib/gt/init.c +9 -0
  70. package/src/platforms/gametank/lib/gt/input.c +26 -0
  71. package/src/platforms/gametank/lib/gt/input.h +20 -0
  72. package/src/platforms/gametank/lib/gt/interrupt.s +67 -0
  73. package/src/platforms/gametank/lib/gt/vectors.s +14 -0
  74. package/src/platforms/gametank/lib/gt/wait.s +53 -0
  75. package/src/platforms/gba/MENTAL_MODEL.md +22 -1
  76. package/src/playtest/playtest.js +174 -26
  77. package/src/playtest/resampler/build.sh +19 -0
  78. package/src/playtest/resampler/index.mjs +75 -0
  79. package/src/playtest/resampler/resampler.c +129 -0
  80. package/src/playtest/resampler/resampler.mjs +2 -0
  81. package/src/playtest/resampler/resampler.wasm +0 -0
  82. package/src/toolchains/arm-none-eabi-gcc/gcc.js +39 -188
  83. package/src/toolchains/asar/asar.js +10 -15
  84. package/src/toolchains/cc65/cc65.js +82 -92
  85. package/src/toolchains/cc65/da65.js +12 -17
  86. package/src/toolchains/cc65/preset-resolver.js +13 -2
  87. package/src/toolchains/cc65/presets/gametank/gametank.h +80 -0
  88. package/src/toolchains/cc65/presets/gametank/sdk.cfg +32 -0
  89. package/src/toolchains/cc65/presets/gametank/sdk.crt0.s +61 -0
  90. package/src/toolchains/cc65/presets/gametank/sdk.vectors.s +11 -0
  91. package/src/toolchains/cc65/presets/gametank/single-bank.cfg +28 -0
  92. package/src/toolchains/cc65/presets/gametank/single-bank.crt0.s +71 -0
  93. package/src/toolchains/cc65/presets/gametank/single-bank.vectors.s +12 -0
  94. package/src/toolchains/common/c-build.js +109 -0
  95. package/src/toolchains/common/gcc-toolchain.js +164 -0
  96. package/src/toolchains/common/wasm-tool.js +101 -0
  97. package/src/toolchains/dasm/dasm.js +12 -18
  98. package/src/toolchains/gba-c/gba-c.js +253 -305
  99. package/src/toolchains/genesis-c/genesis-c.js +196 -225
  100. package/src/toolchains/index.js +58 -4
  101. package/src/toolchains/m68k-elf-gcc/gcc.js +39 -202
  102. package/src/toolchains/mips-c/mips-c.js +68 -78
  103. package/src/toolchains/mips-elf-gcc/gcc.js +55 -118
  104. package/src/toolchains/rgbds/rgbds.js +7 -19
  105. package/src/toolchains/sdcc/sdcc.js +35 -26
  106. package/src/toolchains/sh-c/sh-c.js +44 -52
  107. package/src/toolchains/sh-elf-gcc/gcc.js +55 -110
  108. package/src/toolchains/sjasm/sjasm.js +10 -14
  109. package/src/toolchains/snes-c/snes-c.js +125 -150
  110. package/src/toolchains/tcc816/tcc816.js +10 -15
  111. package/src/toolchains/vasm68k/vasm68k.js +11 -16
  112. package/src/toolchains/wladx/wladx.js +5 -17
  113. package/src/toolchains/z80/binutils.js +5 -11
@@ -0,0 +1,177 @@
1
+ #define MODULE_DRAWQUEUE_INTERNAL_USE
2
+ #include "draw_queue.h"
3
+ #include "gametank.h"
4
+ #include "modules_enabled.h"
5
+
6
+ #ifdef ENABLE_MODULE_DRAWQUEUE
7
+
8
+ void pushRect();
9
+
10
+ unsigned char queue_start = 0;
11
+ unsigned char queue_end = 0;
12
+ unsigned char queue_count = 0;
13
+ unsigned char queue_pending = 0;
14
+
15
+ void queue_draw_sprite_rect() {
16
+ if(queue_count >= QUEUE_MAX) {
17
+ asm("CLI");
18
+ await_drawing();
19
+ }
20
+
21
+ asm("SEI");
22
+ if(rect.b & SPRITE_OFFSET_X_MASK) { rect.gx |= 128; }
23
+ if(rect.b & SPRITE_OFFSET_Y_MASK) { rect.gy |= 128; }
24
+ rect.b = (rect.b & BANK_GRAM_MASK) | bankflip | CLIP_MODE_XY;
25
+ queue_flags_param = DMA_GCARRY;
26
+ pushRect();
27
+
28
+ if(queue_pending == 0) {
29
+ next_draw_queue();
30
+ }
31
+ asm("CLI");
32
+ }
33
+
34
+ void queue_draw_box(unsigned char x, unsigned char y, unsigned char w, unsigned char h, unsigned char c) {
35
+ if(x > 127) {
36
+ return;
37
+ }
38
+ if(y > 127) {
39
+ return;
40
+ }
41
+ if(w == 0) {
42
+ return;
43
+ }
44
+ if(h == 0) {
45
+ return;
46
+ }
47
+ while(queue_count >= QUEUE_MAX) {
48
+ asm("CLI");
49
+ await_drawing();
50
+ }
51
+ if(x + w >= 128) {
52
+ w = 128 - x;
53
+ }
54
+ if(y + h >= 128) {
55
+ h = 128 - y;
56
+ }
57
+ asm("SEI");
58
+
59
+ rect.x = x;
60
+ rect.y = y;
61
+ rect.w = w;
62
+ rect.h = h;
63
+ rect.gx = 0;
64
+ rect.gy = 0;
65
+ rect.b = bankflip;
66
+ rect.c = ~c;
67
+ queue_flags_param = DMA_COLORFILL_ENABLE | DMA_OPAQUE;
68
+ pushRect();
69
+
70
+
71
+ if(queue_pending == 0) {
72
+ next_draw_queue();
73
+ }
74
+ asm("CLI");
75
+ }
76
+
77
+ void queue_clear_border(char c) {
78
+ queue_draw_box(
79
+ 0,
80
+ 0,
81
+ SCREEN_WIDTH-BORDER_RIGHT_WIDTH,
82
+ BORDER_TOP_HEIGHT,
83
+ c
84
+ );
85
+ queue_draw_box(
86
+ 0,
87
+ BORDER_TOP_HEIGHT,
88
+ BORDER_LEFT_WIDTH,
89
+ SCREEN_HEIGHT-BORDER_TOP_HEIGHT,
90
+ c
91
+ );
92
+ queue_draw_box(
93
+ BORDER_LEFT_WIDTH,
94
+ SCREEN_HEIGHT-BORDER_BOTTOM_HEIGHT,
95
+ SCREEN_WIDTH-BORDER_LEFT_WIDTH,
96
+ BORDER_BOTTOM_HEIGHT,
97
+ c
98
+ );
99
+ queue_draw_box(
100
+ SCREEN_WIDTH-BORDER_RIGHT_WIDTH,
101
+ 0,
102
+ BORDER_RIGHT_WIDTH,
103
+ SCREEN_HEIGHT-BORDER_BOTTOM_HEIGHT,
104
+ c
105
+ );
106
+ }
107
+
108
+ void queue_draw_sprite_frame(SpriteSlot sprite, char x, char y, char frame, char flip) {
109
+ while(queue_count >= QUEUE_MAX) {
110
+ asm("CLI");
111
+ await_drawing();
112
+ }
113
+ asm("SEI");
114
+ queue_flags_param = DMA_GCARRY;
115
+ sprite_fetch_frame(sprite, frame);
116
+ rect.b = (sprite & BANK_GRAM_MASK) | bankflip | CLIP_MODE_XY;
117
+
118
+ if(flip & SPRITE_FLIP_X) {
119
+ rect.x = (x - sprite_temp_frame.w - sprite_temp_frame.x - 1);
120
+ } else {
121
+ rect.x = (sprite_temp_frame.x + x);
122
+ }
123
+
124
+ if(flip & SPRITE_FLIP_Y) {
125
+ rect.y = (y - sprite_temp_frame.h - sprite_temp_frame.y - 1);
126
+ } else {
127
+ rect.y = (sprite_temp_frame.y + y);
128
+ }
129
+
130
+ rect.gx = sprite_temp_frame.gx;
131
+ if(sprite & SPRITE_OFFSET_X_MASK) { rect.gx |= 128; }
132
+ if(flip & SPRITE_FLIP_X) {
133
+ rect.gx ^= 0xFF;
134
+ rect.gx -= sprite_temp_frame.w - 1;
135
+ }
136
+
137
+ rect.gy = sprite_temp_frame.gy;
138
+ if(sprite & SPRITE_OFFSET_Y_MASK) { rect.gy |= 128; }
139
+ if(flip & SPRITE_FLIP_Y) {
140
+ rect.gy ^= 0xFF;
141
+ rect.gy -= sprite_temp_frame.h - 1;
142
+ }
143
+
144
+ rect.w = sprite_temp_frame.w | (flip & SPRITE_FLIP_X ? 128 : 0);
145
+ rect.h = sprite_temp_frame.h | (flip & SPRITE_FLIP_Y ? 128 : 0);
146
+
147
+ pushRect();
148
+
149
+ if(queue_pending == 0) {
150
+ next_draw_queue();
151
+ }
152
+ asm("CLI");
153
+ }
154
+
155
+ void queue_clear_screen(char c) {
156
+ queue_draw_box(1, 7, SCREEN_WIDTH-2, SCREEN_HEIGHT - 15, c);
157
+ }
158
+
159
+ #endif
160
+
161
+ void await_draw_queue() {
162
+ //If draw queue isn't installed leave the stub in case something waits for it
163
+ #ifdef ENABLE_MODULE_DRAWQUEUE
164
+ asm ("SEI");
165
+ if(queue_pending != 0) {
166
+ await_drawing();
167
+ }
168
+ while(queue_end != queue_start) {
169
+ next_draw_queue();
170
+ asm ("CLI");
171
+ await_drawing();
172
+ }
173
+ vram[START] = 0;
174
+ queue_pending = 0;
175
+ asm ("CLI");
176
+ #endif
177
+ }
@@ -0,0 +1,35 @@
1
+ #ifndef DRAW_QUEUE_H
2
+ #define DRAW_QUEUE_H
3
+ #include "gfx_sys.h"
4
+ #include "sprites.h"
5
+ #include "modules_enabled.h"
6
+
7
+ #ifdef ENABLE_MODULE_DRAWQUEUE
8
+
9
+ #define QUEUE_MAX 250
10
+
11
+ extern unsigned char queue_start, queue_end, queue_pending, queue_count;
12
+ extern unsigned char queue_flags_param; //defined in draw_util.s
13
+
14
+ void queue_draw_box(unsigned char x, unsigned char y, unsigned char w, unsigned char h, unsigned char c);
15
+ void queue_draw_sprite_rect();
16
+
17
+ #define queue_draw_sprite(X,Y,W,H,GX,GY,SPRITESLOT) rect.x=X;rect.y=Y;rect.w=W;rect.h=H;rect.gx=GX;rect.gy=GY;rect.b=SPRITESLOT;queue_draw_sprite_rect();
18
+ void queue_draw_sprite_frame(SpriteSlot sprite, char x, char y, char frame, char flip);
19
+
20
+
21
+ void queue_clear_border(char c);
22
+ void queue_clear_screen(char c);
23
+
24
+ //defined in draw_util.s
25
+ void next_draw_queue();
26
+
27
+ #else
28
+
29
+ #ifndef MODULE_DRAWQUEUE_INTERNAL_USE
30
+ #error "Module DRAWQUEUE included but not enabled!"
31
+ #endif
32
+ #endif
33
+
34
+ void await_draw_queue();
35
+ #endif
@@ -0,0 +1,157 @@
1
+ .export _rect
2
+ .importzp sp, ptr1
3
+
4
+ .import incsp2, pushax
5
+ .import _flagsMirror, _frameflip, _draw_busy
6
+ .import _banksMirror
7
+
8
+ .include "modules_enabled.inc"
9
+
10
+ .ifdef ENABLE_MODULE_DRAWQUEUE
11
+ .export _pushRect, _queue_flags_param, _next_draw_queue
12
+ .import _queue_start,_queue_end, _queue_count, _queue_pending
13
+ .endif
14
+
15
+ BankReg = $2005
16
+ DMAFlags = $2007
17
+
18
+ Q_DMAFlags = $0200
19
+ Q_VX = $0300
20
+ Q_VY = $0400
21
+ Q_GX = $0500
22
+ Q_GY = $0600
23
+ Q_WIDTH = $0700
24
+ Q_HEIGHT = $0800
25
+ Q_Color = $0900
26
+ Q_BankReg = $0A00
27
+
28
+ DMA_VX = $4000
29
+ DMA_VY = $4001
30
+ DMA_GX = $4002
31
+ DMA_GY = $4003
32
+ DMA_WIDTH = $4004
33
+ DMA_HEIGHT = $4005
34
+ DMA_Start = $4006
35
+ DMA_Color = $4007
36
+
37
+ _queue_flags_param = $3200
38
+ _rect = $3201 ;borrow unbanked Audio RAM memory
39
+
40
+ .ifdef ENABLE_MODULE_DRAWQUEUE
41
+ ; ---------------------------------------------------------------
42
+ ; void __near__ pushRect ()
43
+ ; ---------------------------------------------------------------
44
+
45
+ .segment "CODE"
46
+
47
+ .proc _pushRect: near
48
+
49
+ .segment "CODE"
50
+
51
+ jsr pushax
52
+
53
+ ldy _queue_end
54
+ inc _queue_end
55
+ inc _queue_count
56
+
57
+ lda _banksMirror ;get current banks reg
58
+ tax
59
+ ora #$40 ;make BANK1 version of same
60
+ sta BankReg ;switch to BANK1
61
+
62
+
63
+ lda _rect+7 ;bank
64
+ sta Q_BankReg, y
65
+
66
+ lda _rect+0 ;x
67
+ sta Q_VX, y
68
+
69
+ lda _rect+1 ;y
70
+ sta Q_VY, y
71
+
72
+ lda _rect+4 ;gx
73
+ sta Q_GX, y
74
+
75
+ lda _rect+5 ;gy
76
+ sta Q_GY, y
77
+
78
+ lda _rect+2 ;w
79
+ sta Q_WIDTH, y
80
+
81
+ lda _rect+3 ;h
82
+ sta Q_HEIGHT, y
83
+
84
+ lda _rect+6 ;color
85
+ sta Q_Color, y
86
+
87
+ lda _queue_flags_param ;flags
88
+ sta Q_DMAFlags, y
89
+
90
+ ;now finally switch back to BANK0
91
+ stx BankReg
92
+
93
+ jmp incsp2
94
+
95
+ .endproc
96
+
97
+ .proc _next_draw_queue: near
98
+ ;determined that there is more to process
99
+ ;so load next set of parameters
100
+ STZ BankReg
101
+ LDA #1
102
+ STA _queue_pending
103
+
104
+ ;make sure DMA mode is set to input these params
105
+ LDA _flagsMirror
106
+ ORA #$01
107
+
108
+ LDY _queue_start
109
+
110
+ LDA #$40
111
+ STA BankReg
112
+
113
+ LDA Q_VX, y
114
+ STA DMA_VX
115
+
116
+ LDA Q_VY, y
117
+ STA DMA_VY
118
+
119
+ LDA Q_GX, y
120
+ STA DMA_GX
121
+
122
+ LDA Q_GY, y
123
+ STA DMA_GY
124
+
125
+ LDA Q_WIDTH, y
126
+ STA DMA_WIDTH
127
+
128
+ LDA Q_HEIGHT, y
129
+ STA DMA_HEIGHT
130
+
131
+ LDA Q_Color, y
132
+ STA DMA_Color
133
+
134
+ LDX Q_DMAFlags, y
135
+ LDA Q_BankReg, y
136
+
137
+ AND #$3F
138
+ STA BankReg
139
+ STA _banksMirror
140
+
141
+ TXA ;retrieve Q_DMAFlags value
142
+ ORA _frameflip
143
+ ORA #$45 ; DMA_ENABLE | DMA_NMI | DMA_IRQ
144
+ STA _flagsMirror
145
+ STA DMAFlags
146
+
147
+ INC _queue_start
148
+
149
+ LDA #1
150
+ STA _draw_busy
151
+ STA DMA_Start ;START
152
+
153
+ DEC _queue_count
154
+ RTS
155
+ .endproc
156
+
157
+ .endif
@@ -0,0 +1,43 @@
1
+ /*
2
+ * GameTank-specific implementation of drawing functions
3
+ */
4
+ #include "gfx_sys.h"
5
+ #include "gametank.h"
6
+ #include "banking.h"
7
+
8
+ char cursorX, cursorY;
9
+ char draw_busy;
10
+
11
+ void await_vsync(int frames) {
12
+ int i;
13
+ for(i = 0; i < frames; i++) {
14
+ frameflag = 1;
15
+ while(frameflag) {}
16
+ }
17
+ }
18
+
19
+ void flip_pages() {
20
+ frameflip ^= DMA_PAGE_OUT;
21
+ bankflip ^= BANK_SECOND_FRAMEBUFFER;
22
+ flagsMirror = DMA_NMI | DMA_ENABLE | DMA_IRQ | DMA_OPAQUE | frameflip | DMA_GCARRY;
23
+ *dma_flags = flagsMirror;
24
+ *bank_reg = bankflip;
25
+ }
26
+
27
+ void init_graphics() {
28
+ frameflip = 0;
29
+ draw_busy = 0;
30
+ flagsMirror = DMA_NMI | DMA_ENABLE | DMA_IRQ;
31
+ bankflip = BANK_SECOND_FRAMEBUFFER;
32
+ *dma_flags = flagsMirror;
33
+ banksMirror = bankflip;
34
+ *bank_reg = banksMirror;
35
+ }
36
+
37
+ void await_drawing() {
38
+ asm ("CLI");
39
+ while (draw_busy)
40
+ {
41
+ wait();
42
+ }
43
+ }
@@ -0,0 +1,46 @@
1
+ #ifndef GFX_SYS_H
2
+
3
+ #define GFX_SYS_H
4
+
5
+ #define CLIP_MODE_NONE 0
6
+ #define CLIP_MODE_X 16
7
+ #define CLIP_MODE_Y 32
8
+ #define CLIP_MODE_XY 48
9
+
10
+ #define SPRITE_FLIP_NONE 0
11
+ #define SPRITE_FLIP_X 1
12
+ #define SPRITE_FLIP_Y 2
13
+ #define SPRITE_FLIP_BOTH 3
14
+
15
+ #define QUADRANT_0 0
16
+ #define QUADRANT_1 8
17
+ #define QUADRANT_2 16
18
+ #define QUADRANT_3 24
19
+
20
+ #define BORDER_BOTTOM_HEIGHT 8
21
+ #define BORDER_TOP_HEIGHT 7
22
+ #define BORDER_LEFT_WIDTH 1
23
+ #define BORDER_RIGHT_WIDTH 1
24
+
25
+ typedef struct Frame {
26
+ char x, y, w, h, gx, gy, c, b;
27
+ } Frame;
28
+
29
+ #define SET_RECT(xm,ym,wm,hm,gxm,gym,cm,bm) rect.x = xm;\
30
+ rect.y = ym; \
31
+ rect.w = wm; \
32
+ rect.h = hm; \
33
+ rect.gx = gxm; \
34
+ rect.gy = gym; \
35
+ rect.c = cm; \
36
+ rect.b = bm; \
37
+
38
+ void await_vsync(int frames);
39
+ void flip_pages();
40
+ void init_graphics();
41
+ void await_drawing();
42
+
43
+ extern char draw_busy;
44
+ extern Frame rect; //Defined in draw_util.s
45
+
46
+ #endif
@@ -0,0 +1,216 @@
1
+ #include "sprites.h"
2
+ #include "gametank.h"
3
+ #include "banking.h"
4
+ #include <zlib.h>
5
+ #include "bank_nums.h"
6
+
7
+ /*
8
+ For each sprite bank:
9
+ HEADS mask of which quadrants contain the anchor of a sheet
10
+ OCCUPIED mask of which quadrants are allocated
11
+ HEADS:4 | OCCUPIED:4
12
+ */
13
+ static char bank_occupied[8] = { 0, 0, 0, 0, 0, 0, 0, 0};
14
+
15
+ typedef union PointerUnion {
16
+ void* ptr;
17
+ struct {
18
+ char lsb, msb;
19
+ } b;
20
+ } PointerUnion;
21
+
22
+ #define SPRITE_SLOT_COUNT 32
23
+ static char frametable_L[SPRITE_SLOT_COUNT];
24
+ static char frametable_H[SPRITE_SLOT_COUNT];
25
+ static char frametable_B[SPRITE_SLOT_COUNT];
26
+ static char sprite_size_cache[SPRITE_SLOT_COUNT];
27
+
28
+ #define HEAD_CORNER_NW 16
29
+ #define HEAD_CORNER_NE 32
30
+ #define HEAD_CORNER_SW 64
31
+ #define HEAD_CORNER_SE 128
32
+
33
+ void load_spritesheet(const unsigned char* spriteData, char srcBank, char ramBank) {
34
+ char oldFlags = flagsMirror;
35
+ char oldBanks = banksMirror;
36
+ char bankNum = ramBank & 7;
37
+ char xbit = (ramBank & 8) << 4;
38
+ char ybit = (ramBank & 16) << 3;
39
+ push_rom_bank();
40
+ change_rom_bank(srcBank);
41
+ flagsMirror = DMA_ENABLE;
42
+ *dma_flags = flagsMirror;
43
+ *vram_VX = 0;
44
+ *vram_VY = 0;
45
+ *vram_GX = xbit;
46
+ *vram_GY = ybit;
47
+ *vram_WIDTH = 1;
48
+ *vram_HEIGHT = 1;
49
+ *vram_START = 1;
50
+ *vram_START = 0;
51
+
52
+ flagsMirror = 0;
53
+ *dma_flags = flagsMirror;
54
+ banksMirror = bankflip | GRAM_PAGE(ramBank);
55
+ *bank_reg = banksMirror;
56
+ inflatemem(vram, spriteData);
57
+ flagsMirror = oldFlags;
58
+ banksMirror = oldBanks;
59
+ *dma_flags = flagsMirror;
60
+ *bank_reg = banksMirror;
61
+ pop_rom_bank();
62
+ }
63
+
64
+ void clear_spritebank(char bank) {
65
+ char oldFlags = flagsMirror;
66
+ char oldBanks = banksMirror;
67
+ char bankNum = bank & 7;
68
+ char xbit = (bank & 8) << 4;
69
+ char ybit = (bank & 16) << 3;
70
+ unsigned int i = 0;
71
+ flagsMirror = DMA_ENABLE;
72
+ *dma_flags = flagsMirror;
73
+ *vram_VX = 0;
74
+ *vram_VY = 0;
75
+ *vram_GX = xbit;
76
+ *vram_GY = ybit;
77
+ *vram_WIDTH = 1;
78
+ *vram_HEIGHT = 1;
79
+ *vram_START = 1;
80
+ *vram_START = 0;
81
+
82
+ flagsMirror = 0;
83
+ *dma_flags = flagsMirror;
84
+ banksMirror = bankflip | GRAM_PAGE(bank);
85
+ *bank_reg = banksMirror;
86
+ for(i = 0; i < 16384; i++) {
87
+ vram[i] = 0;
88
+ }
89
+ flagsMirror = oldFlags;
90
+ banksMirror = oldBanks;
91
+ *dma_flags = flagsMirror;
92
+ *bank_reg = banksMirror;
93
+ }
94
+
95
+ SpriteSlot allocate_sprite(const SpritePage* sprite) {
96
+ register const SpritePage* current;
97
+ register char mask, i, free_page;
98
+ push_rom_bank();
99
+ change_rom_bank(BANK_LOADERS);
100
+ mask = 0; i = 1;
101
+ for(current = sprite; current != 0; current = current->next) {
102
+ if(current->data != 0) {
103
+ mask |= i;
104
+ }
105
+ i = i << 1;
106
+ }
107
+ free_page = 0xFF;
108
+ for(i = 0; i < 8; ++i) {
109
+ if(!(bank_occupied[i] & mask)) {
110
+ bank_occupied[i] |= mask | HEAD_CORNER_NW;
111
+ free_page = i;
112
+ break;
113
+ }
114
+ if(mask == PAGE_MASK_FULL) {
115
+ continue;
116
+ }
117
+ if(mask != PAGE_MASK_WIDE) {
118
+ //if mask doesn't span horizontally
119
+ if(!(bank_occupied[i] & (mask << 1))) {
120
+ bank_occupied[i] |= ((mask << 1) & 0b1010) | HEAD_CORNER_NE;
121
+ free_page = i | SPRITE_OFFSET_X_MASK;
122
+ break;
123
+ }
124
+ }
125
+ if(mask != PAGE_MASK_TALL) {
126
+ //if mask doesn't span vertically
127
+ if(!(bank_occupied[i] & (mask << 2))) {
128
+ bank_occupied[i] |= ((mask << 2) & 0b1100) | HEAD_CORNER_SW;
129
+ free_page = i | SPRITE_OFFSET_Y_MASK;
130
+ break;
131
+ }
132
+ }
133
+ if(mask == 1) {
134
+ if(!(bank_occupied[i] & (mask << 3))) {
135
+ bank_occupied[i] |= ((mask << 3) & 0b1000) | HEAD_CORNER_SE;
136
+ free_page = i | SPRITE_OFFSET_XY_MASK;
137
+ break;
138
+ }
139
+ }
140
+ }
141
+
142
+ if(SPRITE_SLOT_INVALID(free_page)) {
143
+ pop_rom_bank();
144
+ return 0xFF;
145
+ }
146
+
147
+ sprite_size_cache[free_page] = mask;
148
+
149
+ i = 1;
150
+
151
+ mask = (free_page & SPRITE_OFFSET_XY_MASK);
152
+ for(current = sprite; current != 0; current = current->next) {
153
+ if(current->data != 0) {
154
+ load_spritesheet(current->data, current->bank, (free_page & 7) | mask);
155
+ }
156
+ i = i << 1;
157
+ mask += 8;
158
+ }
159
+ pop_rom_bank();
160
+ return free_page;
161
+ }
162
+
163
+ void set_sprite_frametable(SpriteSlot sprite, const Frame *frametable, char frametable_bank) {
164
+ frametable_B[sprite] = frametable_bank;
165
+ frametable_L[sprite] = (*((PointerUnion*)(&frametable))).b.lsb;
166
+ frametable_H[sprite] = (*((PointerUnion*)(&frametable))).b.msb;
167
+ }
168
+
169
+ void free_sprite(SpriteSlot slot) {
170
+ register char anchor, clear_mask, heads;
171
+ anchor = slot & SPRITE_OFFSET_XY_MASK;
172
+ heads = bank_occupied[slot & 7] >> 4;
173
+ clear_mask = ~heads;
174
+ switch(slot & SPRITE_OFFSET_XY_MASK) {
175
+ case 0:
176
+ clear_mask &= 0b1111;
177
+ clear_mask |= 1;
178
+ if((clear_mask & 0b0110) != 0b0110) {
179
+ clear_mask &= 7;
180
+ }
181
+ break;
182
+ case SPRITE_OFFSET_X_MASK:
183
+ clear_mask &= 0b1010;
184
+ clear_mask |= 2;
185
+ if(sprite_size_cache[slot] == 1) {
186
+ clear_mask &= 7;
187
+ }
188
+ break;
189
+ case SPRITE_OFFSET_Y_MASK:
190
+ clear_mask &= 0b1100;
191
+ clear_mask |= 4;
192
+ if(sprite_size_cache[slot] == 1) {
193
+ clear_mask &= 7;
194
+ }
195
+ break;
196
+ case SPRITE_OFFSET_XY_MASK:
197
+ clear_mask = 0b1000;
198
+ break;
199
+ }
200
+ clear_mask |= (clear_mask << 4);
201
+ bank_occupied[slot & 7] &= ~clear_mask;
202
+ }
203
+
204
+ Frame sprite_temp_frame;
205
+ static PointerUnion dsf_frametable;
206
+
207
+ void sprite_fetch_frame(SpriteSlot sprite, char frame) {
208
+ push_rom_bank();
209
+ change_rom_bank(frametable_B[sprite]);
210
+ dsf_frametable.b.lsb = frametable_L[sprite];
211
+ dsf_frametable.b.msb = frametable_H[sprite];
212
+ sprite_temp_frame = ((Frame*) dsf_frametable.ptr)[frame];
213
+ pop_rom_bank();
214
+ }
215
+
216
+ void pushRect();
@@ -0,0 +1,41 @@
1
+ #ifndef SPRITES_H
2
+ #define SPRITES_H
3
+ #include "gfx_sys.h"
4
+
5
+ #define SPRITE_SLOT_INVALID(x) (x & 0b11100000)
6
+
7
+ //Sprite sheets MUST be one of these
8
+ #define PAGE_MASK_SINGLE 1
9
+ #define PAGE_MASK_WIDE 3
10
+ #define PAGE_MASK_TALL 5
11
+ #define PAGE_MASK_FULL 15
12
+
13
+ #define SPRITE_OFFSET_X_MASK 8
14
+ #define SPRITE_OFFSET_Y_MASK 16
15
+ #define SPRITE_OFFSET_XY_MASK 24
16
+
17
+ #define SPRITE_OFFSET_X(slot) ((slot & SPRITE_OFFSET_X_MASK) ? 128 : 0)
18
+ #define SPRITE_OFFSET_Y(slot) ((slot & SPRITE_OFFSET_Y_MASK) ? 128 : 0)
19
+
20
+ #define CONSTRUCT_SPRITE_SLOT(slot, quadrant) ((slot) | (quadrant))
21
+
22
+ typedef char SpriteSlot;
23
+
24
+ typedef struct SpritePage {
25
+ const unsigned char* data;
26
+ char bank;
27
+ const struct SpritePage* next;
28
+ } SpritePage;
29
+
30
+ extern Frame sprite_temp_frame;
31
+
32
+ void load_spritesheet(const unsigned char* spriteData, char srcBank, char ramBank);
33
+ void clear_spritebank(char bank);
34
+
35
+ void sprite_fetch_frame(SpriteSlot sprite, char frame);
36
+
37
+ SpriteSlot allocate_sprite(const SpritePage* sprite);
38
+ void set_sprite_frametable(SpriteSlot sprite, const Frame *frametable, char frametable_bank);
39
+ void free_sprite(SpriteSlot slot);
40
+
41
+ #endif