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.
- package/AGENTS.md +19 -16
- package/CHANGELOG.md +196 -0
- package/README.md +5 -5
- package/examples/README.md +1 -0
- package/examples/gametank/templates/gt_draw.h +91 -0
- package/examples/gametank/templates/gt_hud.h +89 -0
- package/examples/gametank/templates/gt_palette.h +59 -0
- package/examples/gametank/templates/gt_sound.h +90 -0
- package/examples/gametank/templates/gt_sprites.h +53 -0
- package/examples/gametank/templates/platformer.c +318 -0
- package/examples/gametank/templates/puzzle.c +295 -0
- package/examples/gametank/templates/racing.c +139 -0
- package/examples/gametank/templates/shmup.c +277 -0
- package/examples/gametank/templates/sports.c +119 -0
- package/package.json +23 -22
- package/src/cores/capabilities.js +24 -0
- package/src/cores/registry.js +7 -1
- package/src/host/LibretroHost.js +90 -17
- package/src/host/callbacks.js +20 -2
- package/src/host/cpu-state.js +17 -0
- package/src/host/gametank-acp-state.js +53 -0
- package/src/http/skill-doc.js +10 -6
- package/src/mcp/tools/audio.js +1 -1
- package/src/mcp/tools/cart-parts.js +76 -0
- package/src/mcp/tools/lifecycle.js +1 -1
- package/src/mcp/tools/platform-tools.js +9 -1
- package/src/mcp/tools/platforms.js +46 -10
- package/src/mcp/tools/toolchain.js +35 -10
- package/src/platforms/gametank/lib/gt/audio/acp_image.bin +0 -0
- package/src/platforms/gametank/lib/gt/audio/audio_coprocessor.c +55 -0
- package/src/platforms/gametank/lib/gt/audio/audio_coprocessor.h +34 -0
- package/src/platforms/gametank/lib/gt/audio/audio_fw.asm +223 -0
- package/src/platforms/gametank/lib/gt/audio/audio_fw_blob.s +8 -0
- package/src/platforms/gametank/lib/gt/audio/instruments.c +79 -0
- package/src/platforms/gametank/lib/gt/audio/instruments.h +25 -0
- package/src/platforms/gametank/lib/gt/audio/music.c +370 -0
- package/src/platforms/gametank/lib/gt/audio/music.h +35 -0
- package/src/platforms/gametank/lib/gt/audio/note_numbers.h +132 -0
- package/src/platforms/gametank/lib/gt/audio/scaled_sines.raw +0 -0
- package/src/platforms/gametank/lib/gt/audio/sine_256_-63_63.bin +0 -0
- package/src/platforms/gametank/lib/gt/banking.c +29 -0
- package/src/platforms/gametank/lib/gt/banking.h +8 -0
- package/src/platforms/gametank/lib/gt/banking2.s +41 -0
- package/src/platforms/gametank/lib/gt/crt0.s +102 -0
- package/src/platforms/gametank/lib/gt/draw_logo.s +55 -0
- package/src/platforms/gametank/lib/gt/feature/persist/persist.c +103 -0
- package/src/platforms/gametank/lib/gt/feature/persist/persist.h +13 -0
- package/src/platforms/gametank/lib/gt/feature/random/random.c +40 -0
- package/src/platforms/gametank/lib/gt/feature/random/random.h +18 -0
- package/src/platforms/gametank/lib/gt/feature/text/text.c +111 -0
- package/src/platforms/gametank/lib/gt/feature/text/text.h +25 -0
- package/src/platforms/gametank/lib/gt/gametank.c +12 -0
- package/src/platforms/gametank/lib/gt/gametank.h +80 -0
- package/src/platforms/gametank/lib/gt/gametank_logo.inc +393 -0
- package/src/platforms/gametank/lib/gt/gen/assets/assets_index.h +9 -0
- package/src/platforms/gametank/lib/gt/gen/assets/sdk_default.h +5 -0
- package/src/platforms/gametank/lib/gt/gen/bank_nums.h +11 -0
- package/src/platforms/gametank/lib/gt/gen/modules_enabled.h +4 -0
- package/src/platforms/gametank/lib/gt/gen/modules_enabled.inc +4 -0
- package/src/platforms/gametank/lib/gt/gfx/draw_direct.c +132 -0
- package/src/platforms/gametank/lib/gt/gfx/draw_direct.h +75 -0
- package/src/platforms/gametank/lib/gt/gfx/draw_queue.c +177 -0
- package/src/platforms/gametank/lib/gt/gfx/draw_queue.h +35 -0
- package/src/platforms/gametank/lib/gt/gfx/draw_util.s +157 -0
- package/src/platforms/gametank/lib/gt/gfx/gfx_sys.c +43 -0
- package/src/platforms/gametank/lib/gt/gfx/gfx_sys.h +46 -0
- package/src/platforms/gametank/lib/gt/gfx/sprites.c +216 -0
- package/src/platforms/gametank/lib/gt/gfx/sprites.h +41 -0
- package/src/platforms/gametank/lib/gt/init.c +9 -0
- package/src/platforms/gametank/lib/gt/input.c +26 -0
- package/src/platforms/gametank/lib/gt/input.h +20 -0
- package/src/platforms/gametank/lib/gt/interrupt.s +67 -0
- package/src/platforms/gametank/lib/gt/vectors.s +14 -0
- package/src/platforms/gametank/lib/gt/wait.s +53 -0
- package/src/platforms/gba/MENTAL_MODEL.md +22 -1
- package/src/playtest/playtest.js +174 -26
- package/src/playtest/resampler/build.sh +19 -0
- package/src/playtest/resampler/index.mjs +75 -0
- package/src/playtest/resampler/resampler.c +129 -0
- package/src/playtest/resampler/resampler.mjs +2 -0
- package/src/playtest/resampler/resampler.wasm +0 -0
- package/src/toolchains/arm-none-eabi-gcc/gcc.js +39 -188
- package/src/toolchains/asar/asar.js +10 -15
- package/src/toolchains/cc65/cc65.js +82 -92
- package/src/toolchains/cc65/da65.js +12 -17
- package/src/toolchains/cc65/preset-resolver.js +13 -2
- package/src/toolchains/cc65/presets/gametank/gametank.h +80 -0
- package/src/toolchains/cc65/presets/gametank/sdk.cfg +32 -0
- package/src/toolchains/cc65/presets/gametank/sdk.crt0.s +61 -0
- package/src/toolchains/cc65/presets/gametank/sdk.vectors.s +11 -0
- package/src/toolchains/cc65/presets/gametank/single-bank.cfg +28 -0
- package/src/toolchains/cc65/presets/gametank/single-bank.crt0.s +71 -0
- package/src/toolchains/cc65/presets/gametank/single-bank.vectors.s +12 -0
- package/src/toolchains/common/c-build.js +109 -0
- package/src/toolchains/common/gcc-toolchain.js +164 -0
- package/src/toolchains/common/wasm-tool.js +101 -0
- package/src/toolchains/dasm/dasm.js +12 -18
- package/src/toolchains/gba-c/gba-c.js +253 -305
- package/src/toolchains/genesis-c/genesis-c.js +196 -225
- package/src/toolchains/index.js +58 -4
- package/src/toolchains/m68k-elf-gcc/gcc.js +39 -202
- package/src/toolchains/mips-c/mips-c.js +68 -78
- package/src/toolchains/mips-elf-gcc/gcc.js +55 -118
- package/src/toolchains/rgbds/rgbds.js +7 -19
- package/src/toolchains/sdcc/sdcc.js +35 -26
- package/src/toolchains/sh-c/sh-c.js +44 -52
- package/src/toolchains/sh-elf-gcc/gcc.js +55 -110
- package/src/toolchains/sjasm/sjasm.js +10 -14
- package/src/toolchains/snes-c/snes-c.js +125 -150
- package/src/toolchains/tcc816/tcc816.js +10 -15
- package/src/toolchains/vasm68k/vasm68k.js +11 -16
- package/src/toolchains/wladx/wladx.js +5 -17
- 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
|