aboutsummaryrefslogtreecommitdiff
path: root/pacc
diff options
context:
space:
mode:
authorTakamichi Horikawa <takamichiho@gmail.com>2017-09-08 23:25:51 +0900
committerTakamichi Horikawa <takamichiho@gmail.com>2017-09-08 23:25:51 +0900
commit50c75c12597b230cec4d7a29559cde263025eeb2 (patch)
tree9fa8afe8bcf6e1219186e5c567930831a3b5eab5 /pacc
parent4cfeddd04dcbbf658195bd837d7daff7f08b37bc (diff)
pacc: initial
Diffstat (limited to 'pacc')
-rw-r--r--pacc/glsl/Makefile40
-rw-r--r--pacc/glsl/blit.vert7
-rw-r--r--pacc/glsl/blit.vert.inc14
-rw-r--r--pacc/glsl/color.frag13
-rw-r--r--pacc/glsl/color.frag.inc30
-rw-r--r--pacc/glsl/color_trans.frag11
-rw-r--r--pacc/glsl/color_trans.frag.inc27
-rw-r--r--pacc/glsl/copy.frag9
-rw-r--r--pacc/glsl/copy.frag.inc25
-rw-r--r--pacc/glsl/dsheader5
-rw-r--r--pacc/glsl/dsheader.inc8
-rw-r--r--pacc/glsl/esheader2
-rw-r--r--pacc/glsl/esheader.inc5
-rw-r--r--pacc/glsl/fill.frag5
-rw-r--r--pacc/glsl/fill.frag.inc15
-rw-r--r--pacc/glsl/font.frag15
-rw-r--r--pacc/glsl/font.frag.inc37
-rw-r--r--pacc/glsl/key.frag12
-rw-r--r--pacc/glsl/key.frag.inc32
-rw-r--r--pacc/hlsl/Makefile15
-rw-r--r--pacc/hlsl/blit.vs.hlsl17
-rw-r--r--pacc/hlsl/blit.vs.inc71
-rw-r--r--pacc/hlsl/color.ps.hlsl23
-rw-r--r--pacc/hlsl/color.ps.inc106
-rw-r--r--pacc/hlsl/color_trans.ps.hlsl19
-rw-r--r--pacc/hlsl/color_trans.ps.inc110
-rw-r--r--pacc/hlsl/copy.ps.hlsl18
-rw-r--r--pacc/hlsl/copy.ps.inc93
-rw-r--r--pacc/hlsl/fill.ps.hlsl15
-rw-r--r--pacc/hlsl/fill.ps.inc65
-rw-r--r--pacc/hlsl/font.ps.hlsl24
-rw-r--r--pacc/hlsl/font.ps.inc126
-rw-r--r--pacc/hlsl/key.ps.hlsl20
-rw-r--r--pacc/hlsl/key.ps.inc141
-rw-r--r--pacc/pacc-d3d9.c633
-rw-r--r--pacc/pacc-gl-procs.inc46
-rw-r--r--pacc/pacc-gl.c505
-rw-r--r--pacc/pacc-gl.h8
-rw-r--r--pacc/pacc-win.h21
-rw-r--r--pacc/pacc.h53
40 files changed, 2441 insertions, 0 deletions
diff --git a/pacc/glsl/Makefile b/pacc/glsl/Makefile
new file mode 100644
index 0000000..36aace4
--- /dev/null
+++ b/pacc/glsl/Makefile
@@ -0,0 +1,40 @@
+VSHADERS:=blit.vert
+FSHADERS:=copy.frag color.frag color_trans.frag key.frag fill.frag font.frag
+DSHEADER:=dsheader
+ESHEADER:=esheader
+INCS:=$(addsuffix .inc,$(VSHADERS) $(FSHADERS) $(DSHEADER) $(ESHEADER))
+SHADERS2:=$(addsuffix .ds.vert,$(basename $(VSHADERS)))
+SHADERS2+=$(addsuffix .es.vert,$(basename $(VSHADERS)))
+SHADERS2+=$(addsuffix .ds.frag,$(basename $(FSHADERS)))
+SHADERS2+=$(addsuffix .es.frag,$(basename $(FSHADERS)))
+VALS:=$(addsuffix .vald,$(SHADERS2))
+VALIDATOR:=glslangValidator
+VFLAGS:=
+
+all: $(INCS)
+
+val: $(VALS)
+
+%.es.vert: %.vert
+ cat $(ESHEADER) $< > $@
+
+%.es.frag: %.frag
+ cat $(ESHEADER) $< > $@
+
+%.ds.vert: %.vert
+ cat $(DSHEADER) $< > $@
+
+%.ds.frag: %.frag
+ cat $(DSHEADER) $< > $@
+
+%.vald: %
+ $(VALIDATOR) $(VFLAGS) $<
+
+%.inc: %.zt
+ xxd -i $< | sed -e '/^unsigned char /c\static const uint8_t $(shell echo $(basename $<) | sed -e 's/\./_/g')[] = {' -e '/^unsigned int /c\\' > $@
+
+%.zt: %
+ dd bs=1 count=1 if=/dev/zero | cat $< - > $@
+
+clean:
+ rm -f $(INCS)
diff --git a/pacc/glsl/blit.vert b/pacc/glsl/blit.vert
new file mode 100644
index 0000000..4232a8d
--- /dev/null
+++ b/pacc/glsl/blit.vert
@@ -0,0 +1,7 @@
+attribute vec4 coord;
+varying vec2 texcoord;
+void main(void) {
+ gl_Position = vec4(coord.xy, 0.0, 1.0);
+ texcoord = coord.zw;
+}
+
diff --git a/pacc/glsl/blit.vert.inc b/pacc/glsl/blit.vert.inc
new file mode 100644
index 0000000..34691a9
--- /dev/null
+++ b/pacc/glsl/blit.vert.inc
@@ -0,0 +1,14 @@
+static const uint8_t blit_vert[] = {
+ 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x76, 0x65,
+ 0x63, 0x34, 0x20, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x3b, 0x0a, 0x76, 0x61,
+ 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x74,
+ 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x3b, 0x0a, 0x76, 0x6f, 0x69,
+ 0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x28, 0x76, 0x6f, 0x69, 0x64, 0x29,
+ 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69,
+ 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x76, 0x65, 0x63, 0x34, 0x28,
+ 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x2e, 0x78, 0x79, 0x2c, 0x20, 0x30, 0x2e,
+ 0x30, 0x2c, 0x20, 0x31, 0x2e, 0x30, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x74,
+ 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x20, 0x3d, 0x20, 0x63, 0x6f,
+ 0x6f, 0x72, 0x64, 0x2e, 0x7a, 0x77, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x00
+};
+
diff --git a/pacc/glsl/color.frag b/pacc/glsl/color.frag
new file mode 100644
index 0000000..d03bee5
--- /dev/null
+++ b/pacc/glsl/color.frag
@@ -0,0 +1,13 @@
+uniform sampler2D palette;
+uniform sampler2D tex;
+varying mediump vec2 texcoord;
+uniform lowp float color;
+void main(void) {
+ lowp float index = texture2D(tex, texcoord).x;
+ if (index > (0.5/255.0)) {
+ index = color;
+ } else {
+ index = 0.5 / 256.0;
+ }
+ gl_FragColor = texture2D(palette, vec2(index, 0.0));
+}
diff --git a/pacc/glsl/color.frag.inc b/pacc/glsl/color.frag.inc
new file mode 100644
index 0000000..8ea77ef
--- /dev/null
+++ b/pacc/glsl/color.frag.inc
@@ -0,0 +1,30 @@
+static const uint8_t color_frag[] = {
+ 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x73, 0x61, 0x6d, 0x70,
+ 0x6c, 0x65, 0x72, 0x32, 0x44, 0x20, 0x70, 0x61, 0x6c, 0x65, 0x74, 0x74,
+ 0x65, 0x3b, 0x0a, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x73,
+ 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x32, 0x44, 0x20, 0x74, 0x65, 0x78,
+ 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x65,
+ 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x74,
+ 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x3b, 0x0a, 0x75, 0x6e, 0x69,
+ 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6c, 0x6f, 0x77, 0x70, 0x20, 0x66, 0x6c,
+ 0x6f, 0x61, 0x74, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x0a, 0x76,
+ 0x6f, 0x69, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x28, 0x76, 0x6f, 0x69,
+ 0x64, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x77, 0x70, 0x20,
+ 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20,
+ 0x3d, 0x20, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x32, 0x44, 0x28,
+ 0x74, 0x65, 0x78, 0x2c, 0x20, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72,
+ 0x64, 0x29, 0x2e, 0x78, 0x3b, 0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28,
+ 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3e, 0x20, 0x28, 0x30, 0x2e, 0x35,
+ 0x2f, 0x32, 0x35, 0x35, 0x2e, 0x30, 0x29, 0x29, 0x20, 0x7b, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x20, 0x65, 0x6c,
+ 0x73, 0x65, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x64,
+ 0x65, 0x78, 0x20, 0x3d, 0x20, 0x30, 0x2e, 0x35, 0x20, 0x2f, 0x20, 0x32,
+ 0x35, 0x36, 0x2e, 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20,
+ 0x67, 0x6c, 0x5f, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x20, 0x3d, 0x20, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x32, 0x44,
+ 0x28, 0x70, 0x61, 0x6c, 0x65, 0x74, 0x74, 0x65, 0x2c, 0x20, 0x76, 0x65,
+ 0x63, 0x32, 0x28, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2c, 0x20, 0x30, 0x2e,
+ 0x30, 0x29, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x00
+};
+
diff --git a/pacc/glsl/color_trans.frag b/pacc/glsl/color_trans.frag
new file mode 100644
index 0000000..ef742a4
--- /dev/null
+++ b/pacc/glsl/color_trans.frag
@@ -0,0 +1,11 @@
+uniform sampler2D palette;
+uniform sampler2D tex;
+varying mediump vec2 texcoord;
+uniform lowp float color;
+void main(void) {
+ lowp float index = texture2D(tex, texcoord).x;
+ if (index < (0.5/255.0)) {
+ discard;
+ }
+ gl_FragColor = texture2D(palette, vec2(color, 0.0));
+}
diff --git a/pacc/glsl/color_trans.frag.inc b/pacc/glsl/color_trans.frag.inc
new file mode 100644
index 0000000..f49404c
--- /dev/null
+++ b/pacc/glsl/color_trans.frag.inc
@@ -0,0 +1,27 @@
+static const uint8_t color_trans_frag[] = {
+ 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x73, 0x61, 0x6d, 0x70,
+ 0x6c, 0x65, 0x72, 0x32, 0x44, 0x20, 0x70, 0x61, 0x6c, 0x65, 0x74, 0x74,
+ 0x65, 0x3b, 0x0a, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x73,
+ 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x32, 0x44, 0x20, 0x74, 0x65, 0x78,
+ 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x65,
+ 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x74,
+ 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x3b, 0x0a, 0x75, 0x6e, 0x69,
+ 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6c, 0x6f, 0x77, 0x70, 0x20, 0x66, 0x6c,
+ 0x6f, 0x61, 0x74, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x0a, 0x76,
+ 0x6f, 0x69, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x28, 0x76, 0x6f, 0x69,
+ 0x64, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x77, 0x70, 0x20,
+ 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20,
+ 0x3d, 0x20, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x32, 0x44, 0x28,
+ 0x74, 0x65, 0x78, 0x2c, 0x20, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72,
+ 0x64, 0x29, 0x2e, 0x78, 0x3b, 0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28,
+ 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3c, 0x20, 0x28, 0x30, 0x2e, 0x35,
+ 0x2f, 0x32, 0x35, 0x35, 0x2e, 0x30, 0x29, 0x29, 0x20, 0x7b, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x3b, 0x0a,
+ 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x67, 0x6c, 0x5f, 0x46, 0x72, 0x61,
+ 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x74, 0x65, 0x78,
+ 0x74, 0x75, 0x72, 0x65, 0x32, 0x44, 0x28, 0x70, 0x61, 0x6c, 0x65, 0x74,
+ 0x74, 0x65, 0x2c, 0x20, 0x76, 0x65, 0x63, 0x32, 0x28, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x29, 0x29, 0x3b, 0x0a, 0x7d,
+ 0x0a, 0x00
+};
+
diff --git a/pacc/glsl/copy.frag b/pacc/glsl/copy.frag
new file mode 100644
index 0000000..a77ad91
--- /dev/null
+++ b/pacc/glsl/copy.frag
@@ -0,0 +1,9 @@
+uniform sampler2D palette;
+uniform sampler2D tex;
+varying mediump vec2 texcoord;
+void main(void) {
+ lowp float index = texture2D(tex, texcoord).x;
+ lowp float color = (index * 255.0 + 0.5) / 256.0;
+ gl_FragColor = texture2D(palette, vec2(color, 0.0));
+}
+
diff --git a/pacc/glsl/copy.frag.inc b/pacc/glsl/copy.frag.inc
new file mode 100644
index 0000000..fa3f388
--- /dev/null
+++ b/pacc/glsl/copy.frag.inc
@@ -0,0 +1,25 @@
+static const uint8_t copy_frag[] = {
+ 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x73, 0x61, 0x6d, 0x70,
+ 0x6c, 0x65, 0x72, 0x32, 0x44, 0x20, 0x70, 0x61, 0x6c, 0x65, 0x74, 0x74,
+ 0x65, 0x3b, 0x0a, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x73,
+ 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x32, 0x44, 0x20, 0x74, 0x65, 0x78,
+ 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x65,
+ 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x74,
+ 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x3b, 0x0a, 0x76, 0x6f, 0x69,
+ 0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x28, 0x76, 0x6f, 0x69, 0x64, 0x29,
+ 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x77, 0x70, 0x20, 0x66, 0x6c,
+ 0x6f, 0x61, 0x74, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20,
+ 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x32, 0x44, 0x28, 0x74, 0x65,
+ 0x78, 0x2c, 0x20, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x29,
+ 0x2e, 0x78, 0x3b, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x77, 0x70, 0x20, 0x66,
+ 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d,
+ 0x20, 0x28, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x2a, 0x20, 0x32, 0x35,
+ 0x35, 0x2e, 0x30, 0x20, 0x2b, 0x20, 0x30, 0x2e, 0x35, 0x29, 0x20, 0x2f,
+ 0x20, 0x32, 0x35, 0x36, 0x2e, 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x67, 0x6c,
+ 0x5f, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d,
+ 0x20, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x32, 0x44, 0x28, 0x70,
+ 0x61, 0x6c, 0x65, 0x74, 0x74, 0x65, 0x2c, 0x20, 0x76, 0x65, 0x63, 0x32,
+ 0x28, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x29,
+ 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x00
+};
+
diff --git a/pacc/glsl/dsheader b/pacc/glsl/dsheader
new file mode 100644
index 0000000..13e65b7
--- /dev/null
+++ b/pacc/glsl/dsheader
@@ -0,0 +1,5 @@
+#version 110
+#define lowp
+#define mediump
+#define highp
+
diff --git a/pacc/glsl/dsheader.inc b/pacc/glsl/dsheader.inc
new file mode 100644
index 0000000..b742cec
--- /dev/null
+++ b/pacc/glsl/dsheader.inc
@@ -0,0 +1,8 @@
+static const uint8_t dsheader[] = {
+ 0x23, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x31, 0x31, 0x30,
+ 0x0a, 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x6f, 0x77,
+ 0x70, 0x0a, 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x6d, 0x65,
+ 0x64, 0x69, 0x75, 0x6d, 0x70, 0x0a, 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e,
+ 0x65, 0x20, 0x68, 0x69, 0x67, 0x68, 0x70, 0x0a, 0x0a, 0x00
+};
+
diff --git a/pacc/glsl/esheader b/pacc/glsl/esheader
new file mode 100644
index 0000000..43b26bc
--- /dev/null
+++ b/pacc/glsl/esheader
@@ -0,0 +1,2 @@
+#version 100
+
diff --git a/pacc/glsl/esheader.inc b/pacc/glsl/esheader.inc
new file mode 100644
index 0000000..3ca61f1
--- /dev/null
+++ b/pacc/glsl/esheader.inc
@@ -0,0 +1,5 @@
+static const uint8_t esheader[] = {
+ 0x23, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x31, 0x30, 0x30,
+ 0x0a, 0x0a, 0x00
+};
+
diff --git a/pacc/glsl/fill.frag b/pacc/glsl/fill.frag
new file mode 100644
index 0000000..010b5dc
--- /dev/null
+++ b/pacc/glsl/fill.frag
@@ -0,0 +1,5 @@
+uniform sampler2D palette;
+varying mediump vec2 texcoord;
+void main(void) {
+ gl_FragColor = texture2D(palette, vec2(texcoord.x, 0.0));
+}
diff --git a/pacc/glsl/fill.frag.inc b/pacc/glsl/fill.frag.inc
new file mode 100644
index 0000000..8065199
--- /dev/null
+++ b/pacc/glsl/fill.frag.inc
@@ -0,0 +1,15 @@
+static const uint8_t fill_frag[] = {
+ 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x73, 0x61, 0x6d, 0x70,
+ 0x6c, 0x65, 0x72, 0x32, 0x44, 0x20, 0x70, 0x61, 0x6c, 0x65, 0x74, 0x74,
+ 0x65, 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x6d,
+ 0x65, 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20,
+ 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x3b, 0x0a, 0x76, 0x6f,
+ 0x69, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x28, 0x76, 0x6f, 0x69, 0x64,
+ 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x67, 0x6c, 0x5f, 0x46, 0x72, 0x61,
+ 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x74, 0x65, 0x78,
+ 0x74, 0x75, 0x72, 0x65, 0x32, 0x44, 0x28, 0x70, 0x61, 0x6c, 0x65, 0x74,
+ 0x74, 0x65, 0x2c, 0x20, 0x76, 0x65, 0x63, 0x32, 0x28, 0x74, 0x65, 0x78,
+ 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x2e, 0x78, 0x2c, 0x20, 0x30, 0x2e, 0x30,
+ 0x29, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x00
+};
+
diff --git a/pacc/glsl/font.frag b/pacc/glsl/font.frag
new file mode 100644
index 0000000..8beb0a7
--- /dev/null
+++ b/pacc/glsl/font.frag
@@ -0,0 +1,15 @@
+uniform sampler2D palette;
+uniform sampler2D tex;
+varying mediump vec2 texcoord;
+uniform lowp float bg;
+uniform lowp float color;
+void main(void) {
+ gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);
+ lowp float pixel = texture2D(tex, texcoord).x;
+ lowp float index = color;
+ if (pixel < 0.5) {
+ if (bg < 0.5) discard;
+ index = 0.5 / 256.0;
+ }
+ gl_FragColor = texture2D(palette, vec2(index, 0.0));
+}
diff --git a/pacc/glsl/font.frag.inc b/pacc/glsl/font.frag.inc
new file mode 100644
index 0000000..27d143d
--- /dev/null
+++ b/pacc/glsl/font.frag.inc
@@ -0,0 +1,37 @@
+static const uint8_t font_frag[] = {
+ 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x73, 0x61, 0x6d, 0x70,
+ 0x6c, 0x65, 0x72, 0x32, 0x44, 0x20, 0x70, 0x61, 0x6c, 0x65, 0x74, 0x74,
+ 0x65, 0x3b, 0x0a, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x73,
+ 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x32, 0x44, 0x20, 0x74, 0x65, 0x78,
+ 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x65,
+ 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x74,
+ 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x3b, 0x0a, 0x75, 0x6e, 0x69,
+ 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6c, 0x6f, 0x77, 0x70, 0x20, 0x66, 0x6c,
+ 0x6f, 0x61, 0x74, 0x20, 0x62, 0x67, 0x3b, 0x0a, 0x75, 0x6e, 0x69, 0x66,
+ 0x6f, 0x72, 0x6d, 0x20, 0x6c, 0x6f, 0x77, 0x70, 0x20, 0x66, 0x6c, 0x6f,
+ 0x61, 0x74, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x0a, 0x76, 0x6f,
+ 0x69, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x28, 0x76, 0x6f, 0x69, 0x64,
+ 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x67, 0x6c, 0x5f, 0x46, 0x72, 0x61,
+ 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x76, 0x65, 0x63,
+ 0x34, 0x28, 0x31, 0x2e, 0x30, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x2c, 0x20,
+ 0x31, 0x2e, 0x30, 0x2c, 0x20, 0x31, 0x2e, 0x30, 0x29, 0x3b, 0x0a, 0x20,
+ 0x20, 0x6c, 0x6f, 0x77, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20,
+ 0x70, 0x69, 0x78, 0x65, 0x6c, 0x20, 0x3d, 0x20, 0x74, 0x65, 0x78, 0x74,
+ 0x75, 0x72, 0x65, 0x32, 0x44, 0x28, 0x74, 0x65, 0x78, 0x2c, 0x20, 0x74,
+ 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x29, 0x2e, 0x78, 0x3b, 0x0a,
+ 0x20, 0x20, 0x6c, 0x6f, 0x77, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74,
+ 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x3b, 0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x70, 0x69,
+ 0x78, 0x65, 0x6c, 0x20, 0x3c, 0x20, 0x30, 0x2e, 0x35, 0x29, 0x20, 0x7b,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x62, 0x67, 0x20,
+ 0x3c, 0x20, 0x30, 0x2e, 0x35, 0x29, 0x20, 0x64, 0x69, 0x73, 0x63, 0x61,
+ 0x72, 0x64, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x64, 0x65,
+ 0x78, 0x20, 0x3d, 0x20, 0x30, 0x2e, 0x35, 0x20, 0x2f, 0x20, 0x32, 0x35,
+ 0x36, 0x2e, 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x67,
+ 0x6c, 0x5f, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20,
+ 0x3d, 0x20, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x32, 0x44, 0x28,
+ 0x70, 0x61, 0x6c, 0x65, 0x74, 0x74, 0x65, 0x2c, 0x20, 0x76, 0x65, 0x63,
+ 0x32, 0x28, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2c, 0x20, 0x30, 0x2e, 0x30,
+ 0x29, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x00
+};
+
diff --git a/pacc/glsl/key.frag b/pacc/glsl/key.frag
new file mode 100644
index 0000000..d6bf7e1
--- /dev/null
+++ b/pacc/glsl/key.frag
@@ -0,0 +1,12 @@
+uniform sampler2D palette;
+uniform sampler2D tex;
+varying mediump vec2 texcoord;
+uniform lowp float key;
+uniform lowp float color;
+void main(void) {
+ lowp float index = texture2D(tex, texcoord).x;
+ if (index < (key + (0.5/255.0)) || (key + (1.5/255.0)) < index) {
+ discard;
+ }
+ gl_FragColor = texture2D(palette, vec2(color, 0.0));
+}
diff --git a/pacc/glsl/key.frag.inc b/pacc/glsl/key.frag.inc
new file mode 100644
index 0000000..4a4a6c1
--- /dev/null
+++ b/pacc/glsl/key.frag.inc
@@ -0,0 +1,32 @@
+static const uint8_t key_frag[] = {
+ 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x73, 0x61, 0x6d, 0x70,
+ 0x6c, 0x65, 0x72, 0x32, 0x44, 0x20, 0x70, 0x61, 0x6c, 0x65, 0x74, 0x74,
+ 0x65, 0x3b, 0x0a, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x73,
+ 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x32, 0x44, 0x20, 0x74, 0x65, 0x78,
+ 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x65,
+ 0x64, 0x69, 0x75, 0x6d, 0x70, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x74,
+ 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x3b, 0x0a, 0x75, 0x6e, 0x69,
+ 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6c, 0x6f, 0x77, 0x70, 0x20, 0x66, 0x6c,
+ 0x6f, 0x61, 0x74, 0x20, 0x6b, 0x65, 0x79, 0x3b, 0x0a, 0x75, 0x6e, 0x69,
+ 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6c, 0x6f, 0x77, 0x70, 0x20, 0x66, 0x6c,
+ 0x6f, 0x61, 0x74, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x0a, 0x76,
+ 0x6f, 0x69, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x28, 0x76, 0x6f, 0x69,
+ 0x64, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x77, 0x70, 0x20,
+ 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20,
+ 0x3d, 0x20, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x32, 0x44, 0x28,
+ 0x74, 0x65, 0x78, 0x2c, 0x20, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72,
+ 0x64, 0x29, 0x2e, 0x78, 0x3b, 0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28,
+ 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3c, 0x20, 0x28, 0x6b, 0x65, 0x79,
+ 0x20, 0x2b, 0x20, 0x28, 0x30, 0x2e, 0x35, 0x2f, 0x32, 0x35, 0x35, 0x2e,
+ 0x30, 0x29, 0x29, 0x20, 0x7c, 0x7c, 0x20, 0x28, 0x6b, 0x65, 0x79, 0x20,
+ 0x2b, 0x20, 0x28, 0x31, 0x2e, 0x35, 0x2f, 0x32, 0x35, 0x35, 0x2e, 0x30,
+ 0x29, 0x29, 0x20, 0x3c, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x29, 0x20,
+ 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72,
+ 0x64, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x67, 0x6c, 0x5f,
+ 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20,
+ 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x32, 0x44, 0x28, 0x70, 0x61,
+ 0x6c, 0x65, 0x74, 0x74, 0x65, 0x2c, 0x20, 0x76, 0x65, 0x63, 0x32, 0x28,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x29, 0x29,
+ 0x3b, 0x0a, 0x7d, 0x0a, 0x00
+};
+
diff --git a/pacc/hlsl/Makefile b/pacc/hlsl/Makefile
new file mode 100644
index 0000000..7cd2f51
--- /dev/null
+++ b/pacc/hlsl/Makefile
@@ -0,0 +1,15 @@
+INCS:=copy.ps.inc color.ps.inc color_trans.ps.inc key.ps.inc fill.ps.inc font.ps.inc blit.vs.inc
+FXC:=env WINEDEBUG=-all wine $(HOME)/hlsl/fxc/fxc
+all: $(INCS)
+
+%.inc: %.inc.tmp
+ dos2unix < $< | sed -e 's/^const BYTE g_/static const BYTE /' -e '$$a\\' > $@
+
+%.vs.inc.tmp: %.vs.hlsl
+ $(FXC) /nologo /O3 /Tvs_2_0 /E$(basename $(basename $<)) /Fh $@ $<
+
+%.ps.inc.tmp: %.ps.hlsl
+ $(FXC) /nologo /O3 /Tps_2_0 /E$(basename $(basename $<)) /Fh $@ $<
+
+clean:
+ rm -f $(INCS)
diff --git a/pacc/hlsl/blit.vs.hlsl b/pacc/hlsl/blit.vs.hlsl
new file mode 100644
index 0000000..ea4c18d
--- /dev/null
+++ b/pacc/hlsl/blit.vs.hlsl
@@ -0,0 +1,17 @@
+struct vsinput {
+ float4 coord : POSITION;
+};
+
+struct fsinput {
+ float4 coord : POSITION;
+ float4 texcoord : TEXCOORD;
+};
+
+float2 offset: register(c0);
+
+fsinput blit(vsinput input) {
+ fsinput output;
+ output.coord = float4(input.coord.xy + offset, 0.0, 1.0);
+ output.texcoord = float4(input.coord.zw, 0.0, 1.0);
+ return output;
+}
diff --git a/pacc/hlsl/blit.vs.inc b/pacc/hlsl/blit.vs.inc
new file mode 100644
index 0000000..a2c4a64
--- /dev/null
+++ b/pacc/hlsl/blit.vs.inc
@@ -0,0 +1,71 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
+//
+// fxc /nologo /O3 /Tvs_2_0 /Eblit /Fh blit.vs.inc.tmp blit.vs.hlsl
+//
+//
+// Parameters:
+//
+// float2 offset;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// offset c0 1
+//
+
+ vs_2_0
+ def c1, 0, 1, 0, 0
+ dcl_position v0
+ add oPos.xy, v0, c0
+ mov oPos.zw, c1.xyxy
+ mad oT0, v0.zwzz, c1.yyxx, c1.xxxy
+
+// approximately 3 instruction slots used
+#endif
+
+static const BYTE vs20_blit[] =
+{
+ 0, 2, 254, 255, 254, 255,
+ 33, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 79, 0,
+ 0, 0, 0, 2, 254, 255,
+ 1, 0, 0, 0, 28, 0,
+ 0, 0, 0, 129, 0, 0,
+ 72, 0, 0, 0, 48, 0,
+ 0, 0, 2, 0, 0, 0,
+ 1, 0, 2, 0, 56, 0,
+ 0, 0, 0, 0, 0, 0,
+ 111, 102, 102, 115, 101, 116,
+ 0, 171, 1, 0, 3, 0,
+ 1, 0, 2, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 118, 115, 95, 50, 95, 48,
+ 0, 77, 105, 99, 114, 111,
+ 115, 111, 102, 116, 32, 40,
+ 82, 41, 32, 72, 76, 83,
+ 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109,
+ 112, 105, 108, 101, 114, 32,
+ 57, 46, 50, 57, 46, 57,
+ 53, 50, 46, 51, 49, 49,
+ 49, 0, 81, 0, 0, 5,
+ 1, 0, 15, 160, 0, 0,
+ 0, 0, 0, 0, 128, 63,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 31, 0, 0, 2,
+ 0, 0, 0, 128, 0, 0,
+ 15, 144, 2, 0, 0, 3,
+ 0, 0, 3, 192, 0, 0,
+ 228, 144, 0, 0, 228, 160,
+ 1, 0, 0, 2, 0, 0,
+ 12, 192, 1, 0, 68, 160,
+ 4, 0, 0, 4, 0, 0,
+ 15, 224, 0, 0, 174, 144,
+ 1, 0, 5, 160, 1, 0,
+ 64, 160, 255, 255, 0, 0
+};
+
diff --git a/pacc/hlsl/color.ps.hlsl b/pacc/hlsl/color.ps.hlsl
new file mode 100644
index 0000000..5111097
--- /dev/null
+++ b/pacc/hlsl/color.ps.hlsl
@@ -0,0 +1,23 @@
+struct psinput {
+ float4 texcoord: TEXCOORD;
+};
+
+struct psoutput {
+ float4 fragcolor: COLOR;
+};
+
+sampler palette: register(s0);
+sampler tex: register(s1);
+float uni_color: register(c0);
+
+psoutput color(psinput input) {
+ psoutput output;
+ float index = tex2D(tex, input.texcoord.xy).r;
+ if (index > (0.5/255.0)) {
+ index = uni_color;
+ } else {
+ index = 0.5 / 256.0;
+ }
+ output.fragcolor = tex1D(palette, index);
+ return output;
+}
diff --git a/pacc/hlsl/color.ps.inc b/pacc/hlsl/color.ps.inc
new file mode 100644
index 0000000..5cd1a17
--- /dev/null
+++ b/pacc/hlsl/color.ps.inc
@@ -0,0 +1,106 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
+//
+// fxc /nologo /O3 /Tps_2_0 /Ecolor /Fh color.ps.inc.tmp color.ps.hlsl
+//
+//
+// Parameters:
+//
+// sampler2D palette;
+// sampler2D tex;
+// float uni_color;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// uni_color c0 1
+// palette s0 1
+// tex s1 1
+//
+
+ ps_2_0
+ def c1, 0.00196078443, 0.001953125, 0, 0
+ dcl t0.xy
+ dcl_2d s0
+ dcl_2d s1
+ texld r0, t0, s1
+ add r0.x, -r0.x, c1.x
+ mov r0.y, c1.y
+ cmp r0.xy, r0.x, r0.y, c0.x
+ texld r0, r0, s0
+ mov oC0, r0
+
+// approximately 6 instruction slots used (2 texture, 4 arithmetic)
+#endif
+
+static const BYTE ps20_color[] =
+{
+ 0, 2, 255, 255, 254, 255,
+ 55, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 167, 0,
+ 0, 0, 0, 2, 255, 255,
+ 3, 0, 0, 0, 28, 0,
+ 0, 0, 0, 129, 0, 0,
+ 160, 0, 0, 0, 88, 0,
+ 0, 0, 3, 0, 0, 0,
+ 1, 0, 2, 0, 96, 0,
+ 0, 0, 0, 0, 0, 0,
+ 112, 0, 0, 0, 3, 0,
+ 1, 0, 1, 0, 6, 0,
+ 116, 0, 0, 0, 0, 0,
+ 0, 0, 132, 0, 0, 0,
+ 2, 0, 0, 0, 1, 0,
+ 2, 0, 144, 0, 0, 0,
+ 0, 0, 0, 0, 112, 97,
+ 108, 101, 116, 116, 101, 0,
+ 4, 0, 12, 0, 1, 0,
+ 1, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 116, 101,
+ 120, 0, 4, 0, 12, 0,
+ 1, 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 117, 110, 105, 95, 99, 111,
+ 108, 111, 114, 0, 171, 171,
+ 0, 0, 3, 0, 1, 0,
+ 1, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 112, 115,
+ 95, 50, 95, 48, 0, 77,
+ 105, 99, 114, 111, 115, 111,
+ 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32,
+ 83, 104, 97, 100, 101, 114,
+ 32, 67, 111, 109, 112, 105,
+ 108, 101, 114, 32, 57, 46,
+ 50, 57, 46, 57, 53, 50,
+ 46, 51, 49, 49, 49, 0,
+ 81, 0, 0, 5, 1, 0,
+ 15, 160, 129, 128, 0, 59,
+ 0, 0, 0, 59, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 31, 0, 0, 2, 0, 0,
+ 0, 128, 0, 0, 3, 176,
+ 31, 0, 0, 2, 0, 0,
+ 0, 144, 0, 8, 15, 160,
+ 31, 0, 0, 2, 0, 0,
+ 0, 144, 1, 8, 15, 160,
+ 66, 0, 0, 3, 0, 0,
+ 15, 128, 0, 0, 228, 176,
+ 1, 8, 228, 160, 2, 0,
+ 0, 3, 0, 0, 1, 128,
+ 0, 0, 0, 129, 1, 0,
+ 0, 160, 1, 0, 0, 2,
+ 0, 0, 2, 128, 1, 0,
+ 85, 160, 88, 0, 0, 4,
+ 0, 0, 3, 128, 0, 0,
+ 0, 128, 0, 0, 85, 128,
+ 0, 0, 0, 160, 66, 0,
+ 0, 3, 0, 0, 15, 128,
+ 0, 0, 228, 128, 0, 8,
+ 228, 160, 1, 0, 0, 2,
+ 0, 8, 15, 128, 0, 0,
+ 228, 128, 255, 255, 0, 0
+};
+
diff --git a/pacc/hlsl/color_trans.ps.hlsl b/pacc/hlsl/color_trans.ps.hlsl
new file mode 100644
index 0000000..00999fd
--- /dev/null
+++ b/pacc/hlsl/color_trans.ps.hlsl
@@ -0,0 +1,19 @@
+struct psinput {
+ float4 texcoord: TEXCOORD;
+};
+
+struct psoutput {
+ float4 fragcolor: COLOR;
+};
+
+sampler palette: register(s0);
+sampler tex: register(s1);
+float uni_color: register(c0);
+
+psoutput color_trans(psinput input) {
+ psoutput output;
+ float index = tex2D(tex, input.texcoord.xy).r;
+ if (index < (0.5/255.0)) discard;
+ output.fragcolor = tex1D(palette, uni_color);
+ return output;
+}
diff --git a/pacc/hlsl/color_trans.ps.inc b/pacc/hlsl/color_trans.ps.inc
new file mode 100644
index 0000000..6df66f8
--- /dev/null
+++ b/pacc/hlsl/color_trans.ps.inc
@@ -0,0 +1,110 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
+//
+// fxc /nologo /O3 /Tps_2_0 /Ecolor_trans /Fh color_trans.ps.inc.tmp
+// color_trans.ps.hlsl
+//
+//
+// Parameters:
+//
+// sampler2D palette;
+// sampler2D tex;
+// float uni_color;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// uni_color c0 1
+// palette s0 1
+// tex s1 1
+//
+
+ ps_2_0
+ def c1, -0.00196078443, -0, -1, 0
+ dcl t0.xy
+ dcl_2d s0
+ dcl_2d s1
+ texld r0, t0, s1
+ add r0.x, r0.x, c1.x
+ cmp r0, r0.x, c1.y, c1.z
+ texkill r0
+ mov r0.xy, c0.x
+ texld r0, r0, s0
+ mov oC0, r0
+
+// approximately 7 instruction slots used (2 texture, 5 arithmetic)
+#endif
+
+static const BYTE ps20_color_trans[] =
+{
+ 0, 2, 255, 255, 254, 255,
+ 55, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 167, 0,
+ 0, 0, 0, 2, 255, 255,
+ 3, 0, 0, 0, 28, 0,
+ 0, 0, 0, 129, 0, 0,
+ 160, 0, 0, 0, 88, 0,
+ 0, 0, 3, 0, 0, 0,
+ 1, 0, 2, 0, 96, 0,
+ 0, 0, 0, 0, 0, 0,
+ 112, 0, 0, 0, 3, 0,
+ 1, 0, 1, 0, 6, 0,
+ 116, 0, 0, 0, 0, 0,
+ 0, 0, 132, 0, 0, 0,
+ 2, 0, 0, 0, 1, 0,
+ 2, 0, 144, 0, 0, 0,
+ 0, 0, 0, 0, 112, 97,
+ 108, 101, 116, 116, 101, 0,
+ 4, 0, 12, 0, 1, 0,
+ 1, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 116, 101,
+ 120, 0, 4, 0, 12, 0,
+ 1, 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 117, 110, 105, 95, 99, 111,
+ 108, 111, 114, 0, 171, 171,
+ 0, 0, 3, 0, 1, 0,
+ 1, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 112, 115,
+ 95, 50, 95, 48, 0, 77,
+ 105, 99, 114, 111, 115, 111,
+ 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32,
+ 83, 104, 97, 100, 101, 114,
+ 32, 67, 111, 109, 112, 105,
+ 108, 101, 114, 32, 57, 46,
+ 50, 57, 46, 57, 53, 50,
+ 46, 51, 49, 49, 49, 0,
+ 81, 0, 0, 5, 1, 0,
+ 15, 160, 129, 128, 0, 187,
+ 0, 0, 0, 128, 0, 0,
+ 128, 191, 0, 0, 0, 0,
+ 31, 0, 0, 2, 0, 0,
+ 0, 128, 0, 0, 3, 176,
+ 31, 0, 0, 2, 0, 0,
+ 0, 144, 0, 8, 15, 160,
+ 31, 0, 0, 2, 0, 0,
+ 0, 144, 1, 8, 15, 160,
+ 66, 0, 0, 3, 0, 0,
+ 15, 128, 0, 0, 228, 176,
+ 1, 8, 228, 160, 2, 0,
+ 0, 3, 0, 0, 1, 128,
+ 0, 0, 0, 128, 1, 0,
+ 0, 160, 88, 0, 0, 4,
+ 0, 0, 15, 128, 0, 0,
+ 0, 128, 1, 0, 85, 160,
+ 1, 0, 170, 160, 65, 0,
+ 0, 1, 0, 0, 15, 128,
+ 1, 0, 0, 2, 0, 0,
+ 3, 128, 0, 0, 0, 160,
+ 66, 0, 0, 3, 0, 0,
+ 15, 128, 0, 0, 228, 128,
+ 0, 8, 228, 160, 1, 0,
+ 0, 2, 0, 8, 15, 128,
+ 0, 0, 228, 128, 255, 255,
+ 0, 0
+};
+
diff --git a/pacc/hlsl/copy.ps.hlsl b/pacc/hlsl/copy.ps.hlsl
new file mode 100644
index 0000000..df9d1eb
--- /dev/null
+++ b/pacc/hlsl/copy.ps.hlsl
@@ -0,0 +1,18 @@
+struct psinput {
+ float4 texcoord: TEXCOORD;
+};
+
+struct psoutput {
+ float4 fragcolor: COLOR;
+};
+
+sampler palette: register(s0);
+sampler tex: register(s1);
+
+psoutput copy(psinput input) {
+ psoutput output;
+ float index = tex2D(tex, input.texcoord.xy).r;
+ float color = (index * 255.0 + 0.5) / 256.0;
+ output.fragcolor = tex1D(palette, color);
+ return output;
+}
diff --git a/pacc/hlsl/copy.ps.inc b/pacc/hlsl/copy.ps.inc
new file mode 100644
index 0000000..16acf0a
--- /dev/null
+++ b/pacc/hlsl/copy.ps.inc
@@ -0,0 +1,93 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
+//
+// fxc /nologo /O3 /Tps_2_0 /Ecopy /Fh copy.ps.inc.tmp copy.ps.hlsl
+//
+//
+// Parameters:
+//
+// sampler2D palette;
+// sampler2D tex;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// palette s0 1
+// tex s1 1
+//
+
+ ps_2_0
+ def c0, 255, 0.5, 0.00390625, 0
+ dcl t0.xy
+ dcl_2d s0
+ dcl_2d s1
+ texld r0, t0, s1
+ mad r0.x, r0.x, c0.x, c0.y
+ mul r0.xy, r0.x, c0.z
+ texld r0, r0, s0
+ mov oC0, r0
+
+// approximately 5 instruction slots used (2 texture, 3 arithmetic)
+#endif
+
+static const BYTE ps20_copy[] =
+{
+ 0, 2, 255, 255, 254, 255,
+ 43, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 119, 0,
+ 0, 0, 0, 2, 255, 255,
+ 2, 0, 0, 0, 28, 0,
+ 0, 0, 0, 129, 0, 0,
+ 112, 0, 0, 0, 68, 0,
+ 0, 0, 3, 0, 0, 0,
+ 1, 0, 2, 0, 76, 0,
+ 0, 0, 0, 0, 0, 0,
+ 92, 0, 0, 0, 3, 0,
+ 1, 0, 1, 0, 6, 0,
+ 96, 0, 0, 0, 0, 0,
+ 0, 0, 112, 97, 108, 101,
+ 116, 116, 101, 0, 4, 0,
+ 12, 0, 1, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 116, 101, 120, 0,
+ 4, 0, 12, 0, 1, 0,
+ 1, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 112, 115,
+ 95, 50, 95, 48, 0, 77,
+ 105, 99, 114, 111, 115, 111,
+ 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32,
+ 83, 104, 97, 100, 101, 114,
+ 32, 67, 111, 109, 112, 105,
+ 108, 101, 114, 32, 57, 46,
+ 50, 57, 46, 57, 53, 50,
+ 46, 51, 49, 49, 49, 0,
+ 81, 0, 0, 5, 0, 0,
+ 15, 160, 0, 0, 127, 67,
+ 0, 0, 0, 63, 0, 0,
+ 128, 59, 0, 0, 0, 0,
+ 31, 0, 0, 2, 0, 0,
+ 0, 128, 0, 0, 3, 176,
+ 31, 0, 0, 2, 0, 0,
+ 0, 144, 0, 8, 15, 160,
+ 31, 0, 0, 2, 0, 0,
+ 0, 144, 1, 8, 15, 160,
+ 66, 0, 0, 3, 0, 0,
+ 15, 128, 0, 0, 228, 176,
+ 1, 8, 228, 160, 4, 0,
+ 0, 4, 0, 0, 1, 128,
+ 0, 0, 0, 128, 0, 0,
+ 0, 160, 0, 0, 85, 160,
+ 5, 0, 0, 3, 0, 0,
+ 3, 128, 0, 0, 0, 128,
+ 0, 0, 170, 160, 66, 0,
+ 0, 3, 0, 0, 15, 128,
+ 0, 0, 228, 128, 0, 8,
+ 228, 160, 1, 0, 0, 2,
+ 0, 8, 15, 128, 0, 0,
+ 228, 128, 255, 255, 0, 0
+};
+
diff --git a/pacc/hlsl/fill.ps.hlsl b/pacc/hlsl/fill.ps.hlsl
new file mode 100644
index 0000000..9939553
--- /dev/null
+++ b/pacc/hlsl/fill.ps.hlsl
@@ -0,0 +1,15 @@
+struct psinput {
+ float4 texcoord: TEXCOORD;
+};
+
+struct psoutput {
+ float4 fragcolor: COLOR;
+};
+
+sampler palette: register(s0);
+
+psoutput fill(psinput input) {
+ psoutput output;
+ output.fragcolor = tex1D(palette, input.texcoord.x);
+ return output;
+}
diff --git a/pacc/hlsl/fill.ps.inc b/pacc/hlsl/fill.ps.inc
new file mode 100644
index 0000000..3fcc075
--- /dev/null
+++ b/pacc/hlsl/fill.ps.inc
@@ -0,0 +1,65 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
+//
+// fxc /nologo /O3 /Tps_2_0 /Efill /Fh fill.ps.inc.tmp fill.ps.hlsl
+//
+//
+// Parameters:
+//
+// sampler2D palette;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// palette s0 1
+//
+
+ ps_2_0
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ mov oC0, r0
+
+// approximately 2 instruction slots used (1 texture, 1 arithmetic)
+#endif
+
+static const BYTE ps20_fill[] =
+{
+ 0, 2, 255, 255, 254, 255,
+ 33, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 79, 0,
+ 0, 0, 0, 2, 255, 255,
+ 1, 0, 0, 0, 28, 0,
+ 0, 0, 0, 129, 0, 0,
+ 72, 0, 0, 0, 48, 0,
+ 0, 0, 3, 0, 0, 0,
+ 1, 0, 2, 0, 56, 0,
+ 0, 0, 0, 0, 0, 0,
+ 112, 97, 108, 101, 116, 116,
+ 101, 0, 4, 0, 12, 0,
+ 1, 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 112, 115, 95, 50, 95, 48,
+ 0, 77, 105, 99, 114, 111,
+ 115, 111, 102, 116, 32, 40,
+ 82, 41, 32, 72, 76, 83,
+ 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109,
+ 112, 105, 108, 101, 114, 32,
+ 57, 46, 50, 57, 46, 57,
+ 53, 50, 46, 51, 49, 49,
+ 49, 0, 31, 0, 0, 2,
+ 0, 0, 0, 128, 0, 0,
+ 3, 176, 31, 0, 0, 2,
+ 0, 0, 0, 144, 0, 8,
+ 15, 160, 66, 0, 0, 3,
+ 0, 0, 15, 128, 0, 0,
+ 228, 176, 0, 8, 228, 160,
+ 1, 0, 0, 2, 0, 8,
+ 15, 128, 0, 0, 228, 128,
+ 255, 255, 0, 0
+};
+
diff --git a/pacc/hlsl/font.ps.hlsl b/pacc/hlsl/font.ps.hlsl
new file mode 100644
index 0000000..406da2e
--- /dev/null
+++ b/pacc/hlsl/font.ps.hlsl
@@ -0,0 +1,24 @@
+struct psinput {
+ float4 texcoord: TEXCOORD;
+};
+
+struct psoutput {
+ float4 fragcolor: COLOR;
+};
+
+sampler palette: register(s0);
+sampler tex: register(s1);
+float bg: register(c0);
+float color: register(c1);
+
+psoutput font(psinput input) {
+ psoutput output;
+ float pixel = tex2D(tex, input.texcoord.xy).r;
+ float index = color;
+ if (pixel < 0.5) {
+ if (bg < 0.5) discard;
+ index = 0.5 / 256.0;
+ }
+ output.fragcolor = tex1D(palette, index);
+ return output;
+}
diff --git a/pacc/hlsl/font.ps.inc b/pacc/hlsl/font.ps.inc
new file mode 100644
index 0000000..2167cf7
--- /dev/null
+++ b/pacc/hlsl/font.ps.inc
@@ -0,0 +1,126 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
+//
+// fxc /nologo /O3 /Tps_2_0 /Efont /Fh font.ps.inc.tmp font.ps.hlsl
+//
+//
+// Parameters:
+//
+// float bg;
+// float color;
+// sampler2D palette;
+// sampler2D tex;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// bg c0 1
+// color c1 1
+// palette s0 1
+// tex s1 1
+//
+
+ ps_2_0
+ def c2, -0.5, -0, -1, 0.001953125
+ dcl t0.xy
+ dcl_2d s0
+ dcl_2d s1
+ texld r0, t0, s1
+ add r0.x, r0.x, c2.x
+ mov r1.xw, c2
+ add r0.y, r1.x, c0.x
+ cmp r0.y, r0.y, c2.y, c2.z
+ cmp r2, r0.x, c2.y, r0.y
+ texkill r2
+ cmp r0.xy, r0.x, c1.x, r1.w
+ texld r0, r0, s0
+ mov oC0, r0
+
+// approximately 10 instruction slots used (2 texture, 8 arithmetic)
+#endif
+
+static const BYTE ps20_font[] =
+{
+ 0, 2, 255, 255, 254, 255,
+ 60, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 187, 0,
+ 0, 0, 0, 2, 255, 255,
+ 4, 0, 0, 0, 28, 0,
+ 0, 0, 0, 129, 0, 0,
+ 180, 0, 0, 0, 108, 0,
+ 0, 0, 2, 0, 0, 0,
+ 1, 0, 2, 0, 112, 0,
+ 0, 0, 0, 0, 0, 0,
+ 128, 0, 0, 0, 2, 0,
+ 1, 0, 1, 0, 6, 0,
+ 112, 0, 0, 0, 0, 0,
+ 0, 0, 134, 0, 0, 0,
+ 3, 0, 0, 0, 1, 0,
+ 2, 0, 144, 0, 0, 0,
+ 0, 0, 0, 0, 160, 0,
+ 0, 0, 3, 0, 1, 0,
+ 1, 0, 6, 0, 164, 0,
+ 0, 0, 0, 0, 0, 0,
+ 98, 103, 0, 171, 0, 0,
+ 3, 0, 1, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 99, 111, 108, 111,
+ 114, 0, 112, 97, 108, 101,
+ 116, 116, 101, 0, 171, 171,
+ 4, 0, 12, 0, 1, 0,
+ 1, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 116, 101,
+ 120, 0, 4, 0, 12, 0,
+ 1, 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 112, 115, 95, 50, 95, 48,
+ 0, 77, 105, 99, 114, 111,
+ 115, 111, 102, 116, 32, 40,
+ 82, 41, 32, 72, 76, 83,
+ 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109,
+ 112, 105, 108, 101, 114, 32,
+ 57, 46, 50, 57, 46, 57,
+ 53, 50, 46, 51, 49, 49,
+ 49, 0, 81, 0, 0, 5,
+ 2, 0, 15, 160, 0, 0,
+ 0, 191, 0, 0, 0, 128,
+ 0, 0, 128, 191, 0, 0,
+ 0, 59, 31, 0, 0, 2,
+ 0, 0, 0, 128, 0, 0,
+ 3, 176, 31, 0, 0, 2,
+ 0, 0, 0, 144, 0, 8,
+ 15, 160, 31, 0, 0, 2,
+ 0, 0, 0, 144, 1, 8,
+ 15, 160, 66, 0, 0, 3,
+ 0, 0, 15, 128, 0, 0,
+ 228, 176, 1, 8, 228, 160,
+ 2, 0, 0, 3, 0, 0,
+ 1, 128, 0, 0, 0, 128,
+ 2, 0, 0, 160, 1, 0,
+ 0, 2, 1, 0, 9, 128,
+ 2, 0, 228, 160, 2, 0,
+ 0, 3, 0, 0, 2, 128,
+ 1, 0, 0, 128, 0, 0,
+ 0, 160, 88, 0, 0, 4,
+ 0, 0, 2, 128, 0, 0,
+ 85, 128, 2, 0, 85, 160,
+ 2, 0, 170, 160, 88, 0,
+ 0, 4, 2, 0, 15, 128,
+ 0, 0, 0, 128, 2, 0,
+ 85, 160, 0, 0, 85, 128,
+ 65, 0, 0, 1, 2, 0,
+ 15, 128, 88, 0, 0, 4,
+ 0, 0, 3, 128, 0, 0,
+ 0, 128, 1, 0, 0, 160,
+ 1, 0, 255, 128, 66, 0,
+ 0, 3, 0, 0, 15, 128,
+ 0, 0, 228, 128, 0, 8,
+ 228, 160, 1, 0, 0, 2,
+ 0, 8, 15, 128, 0, 0,
+ 228, 128, 255, 255, 0, 0
+};
+
diff --git a/pacc/hlsl/key.ps.hlsl b/pacc/hlsl/key.ps.hlsl
new file mode 100644
index 0000000..0ca9efd
--- /dev/null
+++ b/pacc/hlsl/key.ps.hlsl
@@ -0,0 +1,20 @@
+struct psinput {
+ float4 texcoord: TEXCOORD;
+};
+
+struct psoutput {
+ float4 fragcolor: COLOR;
+};
+
+sampler palette: register(s0);
+sampler tex: register(s1);
+float uni_key: register(c0);
+float color: register(c1);
+
+psoutput key(psinput input) {
+ psoutput output;
+ float index = tex2D(tex, input.texcoord.xy).r;
+ if (index < (uni_key + (0.5/255.0)) || (uni_key + (1.5/255.0)) < index) discard;
+ output.fragcolor = tex1D(palette, color);
+ return output;
+}
diff --git a/pacc/hlsl/key.ps.inc b/pacc/hlsl/key.ps.inc
new file mode 100644
index 0000000..63d51d8
--- /dev/null
+++ b/pacc/hlsl/key.ps.inc
@@ -0,0 +1,141 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
+//
+// fxc /nologo /O3 /Tps_2_0 /Ekey /Fh key.ps.inc.tmp key.ps.hlsl
+//
+//
+// Parameters:
+//
+// float color;
+// sampler2D palette;
+// sampler2D tex;
+// float uni_key;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// uni_key c0 1
+// color c1 1
+// palette s0 1
+// tex s1 1
+//
+
+ ps_2_0
+ def c2, 0.00196078443, 0, 1, 0.00588235306
+ dcl t0.xy
+ dcl_2d s0
+ dcl_2d s1
+ texld r0, t0, s1
+ mov r1.xw, c2
+ add r0.y, r1.w, c0.x
+ add r0.y, -r0.x, r0.y
+ cmp r0.y, r0.y, c2.y, c2.z
+ add r0.z, r1.x, c0.x
+ add r0.x, -r0.z, r0.x
+ cmp r0.x, r0.x, c2.y, c2.z
+ add r0.x, r0.y, r0.x
+ cmp r0, -r0.x, -c2.y, -c2.z
+ texkill r0
+ mov r0.xy, c1.x
+ texld r0, r0, s0
+ mov oC0, r0
+
+// approximately 14 instruction slots used (2 texture, 12 arithmetic)
+#endif
+
+static const BYTE ps20_key[] =
+{
+ 0, 2, 255, 255, 254, 255,
+ 61, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 191, 0,
+ 0, 0, 0, 2, 255, 255,
+ 4, 0, 0, 0, 28, 0,
+ 0, 0, 0, 129, 0, 0,
+ 184, 0, 0, 0, 108, 0,
+ 0, 0, 2, 0, 1, 0,
+ 1, 0, 6, 0, 116, 0,
+ 0, 0, 0, 0, 0, 0,
+ 132, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 2, 0,
+ 140, 0, 0, 0, 0, 0,
+ 0, 0, 156, 0, 0, 0,
+ 3, 0, 1, 0, 1, 0,
+ 6, 0, 160, 0, 0, 0,
+ 0, 0, 0, 0, 176, 0,
+ 0, 0, 2, 0, 0, 0,
+ 1, 0, 2, 0, 116, 0,
+ 0, 0, 0, 0, 0, 0,
+ 99, 111, 108, 111, 114, 0,
+ 171, 171, 0, 0, 3, 0,
+ 1, 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 112, 97, 108, 101, 116, 116,
+ 101, 0, 4, 0, 12, 0,
+ 1, 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 116, 101, 120, 0, 4, 0,
+ 12, 0, 1, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 117, 110, 105, 95,
+ 107, 101, 121, 0, 112, 115,
+ 95, 50, 95, 48, 0, 77,
+ 105, 99, 114, 111, 115, 111,
+ 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32,
+ 83, 104, 97, 100, 101, 114,
+ 32, 67, 111, 109, 112, 105,
+ 108, 101, 114, 32, 57, 46,
+ 50, 57, 46, 57, 53, 50,
+ 46, 51, 49, 49, 49, 0,
+ 81, 0, 0, 5, 2, 0,
+ 15, 160, 129, 128, 0, 59,
+ 0, 0, 0, 0, 0, 0,
+ 128, 63, 193, 192, 192, 59,
+ 31, 0, 0, 2, 0, 0,
+ 0, 128, 0, 0, 3, 176,
+ 31, 0, 0, 2, 0, 0,
+ 0, 144, 0, 8, 15, 160,
+ 31, 0, 0, 2, 0, 0,
+ 0, 144, 1, 8, 15, 160,
+ 66, 0, 0, 3, 0, 0,
+ 15, 128, 0, 0, 228, 176,
+ 1, 8, 228, 160, 1, 0,
+ 0, 2, 1, 0, 9, 128,
+ 2, 0, 228, 160, 2, 0,
+ 0, 3, 0, 0, 2, 128,
+ 1, 0, 255, 128, 0, 0,
+ 0, 160, 2, 0, 0, 3,
+ 0, 0, 2, 128, 0, 0,
+ 0, 129, 0, 0, 85, 128,
+ 88, 0, 0, 4, 0, 0,
+ 2, 128, 0, 0, 85, 128,
+ 2, 0, 85, 160, 2, 0,
+ 170, 160, 2, 0, 0, 3,
+ 0, 0, 4, 128, 1, 0,
+ 0, 128, 0, 0, 0, 160,
+ 2, 0, 0, 3, 0, 0,
+ 1, 128, 0, 0, 170, 129,
+ 0, 0, 0, 128, 88, 0,
+ 0, 4, 0, 0, 1, 128,
+ 0, 0, 0, 128, 2, 0,
+ 85, 160, 2, 0, 170, 160,
+ 2, 0, 0, 3, 0, 0,
+ 1, 128, 0, 0, 85, 128,
+ 0, 0, 0, 128, 88, 0,
+ 0, 4, 0, 0, 15, 128,
+ 0, 0, 0, 129, 2, 0,
+ 85, 161, 2, 0, 170, 161,
+ 65, 0, 0, 1, 0, 0,
+ 15, 128, 1, 0, 0, 2,
+ 0, 0, 3, 128, 1, 0,
+ 0, 160, 66, 0, 0, 3,
+ 0, 0, 15, 128, 0, 0,
+ 228, 128, 0, 8, 228, 160,
+ 1, 0, 0, 2, 0, 8,
+ 15, 128, 0, 0, 228, 128,
+ 255, 255, 0, 0
+};
+
diff --git a/pacc/pacc-d3d9.c b/pacc/pacc-d3d9.c
new file mode 100644
index 0000000..21f3210
--- /dev/null
+++ b/pacc/pacc-d3d9.c
@@ -0,0 +1,633 @@
+#include "pacc-win.h"
+#include <d3d9.h>
+#include <stdlib.h>
+#include <stdatomic.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include "hlsl/blit.vs.inc"
+#include "hlsl/copy.ps.inc"
+#include "hlsl/color.ps.inc"
+#include "hlsl/color_trans.ps.inc"
+
+struct pacc_ctx {
+ int w, h;
+ uint8_t pal[256*3];
+ bool pal_changed;
+ uint8_t clearpal;
+ uint8_t color;
+ uint8_t color_changed;
+ bool render_enabled;
+ enum pacc_mode curr_mode;
+ atomic_bool killthread;
+ HWND hwnd;
+ HMODULE d3d9m;
+ IDirect3D9 *d3d9;
+ IDirect3DDevice9 *d3d9d;
+ IDirect3DTexture9 *tex_pal;
+ IDirect3DVertexDeclaration9 *vdecl;
+ IDirect3DVertexShader9 *vs;
+ IDirect3DPixelShader9 *ps_modes[pacc_mode_count];
+ IDirect3DStateBlock9 *state_common;
+ IDirect3DStateBlock9 *state_modes[pacc_mode_count];
+ pacc_rendercb *rendercb;
+ void *renderptr;
+ HANDLE renderthread;
+ HANDLE rendermtx;
+};
+
+struct pacc_buf {
+ IDirect3DVertexBuffer9 *buf_obj;
+ float *buf;
+ struct pacc_tex *tex;
+ int len;
+ int buflen;
+ int bufobjlen;
+ bool changed;
+};
+
+struct pacc_tex {
+ int w, h;
+ bool changed;
+ atomic_flag flag;
+ IDirect3DTexture9 *tex_obj;
+ uint8_t *buf;
+};
+
+enum {
+ PACC_BUF_DEF_LEN = 32,
+ PRINTBUFLEN = 160,
+};
+
+static void pacc_buf_delete(struct pacc_buf *pb) {
+ if (pb) {
+ if (pb->buf_obj) pb->buf_obj->lpVtbl->Release(pb->buf_obj);
+ free(pb->buf);
+ free(pb);
+ }
+}
+
+static struct pacc_buf *pacc_gen_buf(
+ struct pacc_ctx *pc, struct pacc_tex *pt, enum pacc_buf_mode mode) {
+ struct pacc_buf *pb = malloc(sizeof(*pb));
+ if (!pb) goto err;
+ *pb = (struct pacc_buf) {
+ .buflen = PACC_BUF_DEF_LEN,
+ .bufobjlen = PACC_BUF_DEF_LEN,
+ .tex = pt,
+ };
+ pb->buf = malloc(sizeof(*pb->buf) * pb->buflen);
+ if (!pb->buf) goto err;
+ HRESULT res;
+ res = pc->d3d9d->lpVtbl->CreateVertexBuffer(
+ pc->d3d9d,
+ sizeof(*pb->buf) * pb->buflen,
+ D3DUSAGE_DYNAMIC,
+ 0,
+ D3DPOOL_DEFAULT,
+ &pb->buf_obj,
+ 0);
+ if (res != D3D_OK) goto err;
+ return pb;
+err:
+ MessageBox(pc->hwnd, L"Hello", L"HI", 0);
+ pacc_buf_delete(pb);
+ return 0;
+}
+
+static bool buf_reserve(struct pacc_buf *pb, int len) {
+ if (pb->len + len > pb->buflen) {
+ int newlen = pb->buflen;
+ while (pb->len + len > newlen) newlen *= 2;
+ float *newbuf = realloc(pb->buf, newlen * sizeof(pb->buf[0]));
+ if (!newbuf) return false;
+ pb->buflen = newlen;
+ pb->buf = newbuf;
+ }
+ return true;
+}
+
+static void pacc_calc_scale(float *ret, int w, int h, int wdest, int hdest) {
+ ret[0] = ((float)w) / wdest;
+ ret[1] = ((float)h) / hdest;
+}
+
+static void pacc_calc_off_tex(float *ret,
+ int tw, int th, int xsrc, int ysrc) {
+ ret[0] = ((float)xsrc) / tw;
+ ret[1] = ((float)ysrc) / th;
+}
+
+static void pacc_calc_off(
+ float *ret, int xdest, int ydest, int w, int h, int wdest, int hdest) {
+ ret[0] = ((float)(xdest * 2 + w - wdest)) / wdest;
+ ret[1] = ((float)(ydest * 2 + h - hdest)) / hdest;
+}
+
+static void pacc_buf_rect_off(
+ const struct pacc_ctx *pc, struct pacc_buf *pb,
+ int x, int y, int w, int h, int xoff, int yoff) {
+ float scale[2];
+ float off[2];
+ float tscale[2];
+ float toff[2];
+ pacc_calc_off(off, x, y, w, h, pc->w, pc->h);
+ pacc_calc_scale(scale, w, h, pc->w, pc->h);
+ pacc_calc_off_tex(toff, pb->tex->w, pb->tex->h, xoff, yoff);
+ pacc_calc_scale(tscale, w, h, pb->tex->w, pb->tex->h);
+ float coord[16] = {
+ -1.0f * scale[0] + off[0], -1.0f * scale[1] - off[1],
+ 0.0f * tscale[0] + toff[0], 1.0f * tscale[1] + toff[1],
+
+ -1.0f * scale[0] + off[0], 1.0f * scale[1] - off[1],
+ 0.0f * tscale[0] + toff[0], 0.0f * tscale[1] + toff[1],
+
+ 1.0f * scale[0] + off[0], -1.0f * scale[1] - off[1],
+ 1.0f * tscale[0] + toff[0], 1.0f * tscale[1] + toff[1],
+
+ 1.0f * scale[0] + off[0], 1.0f * scale[1] - off[1],
+ 1.0f * tscale[0] + toff[0], 0.0f * tscale[1] + toff[1],
+ };
+ if (!buf_reserve(pb, 24)) return;
+ int indices[6] = {0, 1, 2, 2, 1, 3};
+ for (int i = 0; i < 6; i++) {
+ for (int j = 0; j < 4; j++) {
+ pb->buf[pb->len+i*4+j] = coord[indices[i]*4+j];
+ }
+ }
+ pb->len += 24;
+ pb->changed = true;
+}
+
+static void pacc_buf_vprintf(
+ const struct pacc_ctx *pc, struct pacc_buf *pb,
+ int x, int y, const char *fmt, va_list ap) {
+ uint8_t printbuf[PRINTBUFLEN+1];
+ vsnprintf((char *)printbuf, sizeof(printbuf), fmt, ap);
+ int len = strlen((const char *)printbuf);
+ float scale[2];
+ float off[2];
+ int w = pb->tex->w / 256;
+ int h = pb->tex->h;
+ pacc_calc_scale(scale, w, h, pc->w, pc->h);
+ pacc_calc_off(off, x, y, w, h, pc->w, pc->h);
+ if (!buf_reserve(pb, len*24)) return;
+ float *coords = pb->buf + pb->len;
+ for (int i = 0; i < len; i++) {
+ coords[24*i+0*4+0] = (-1.0f + 2.0f*i) * scale[0] + off[0];
+ coords[24*i+0*4+1] = -1.0f * scale[1] - off[1];
+ coords[24*i+1*4+0] = coords[24*i+4*4+0] = (-1.0f + 2.0f*i) * scale[0] + off[0];
+ coords[24*i+1*4+1] = coords[24*i+4*4+1] = 1.0f * scale[1] - off[1];
+ coords[24*i+2*4+0] = coords[24*i+3*4+0] = (1.0f + 2.0f*i) * scale[0] + off[0];
+ coords[24*i+2*4+1] = coords[24*i+3*4+1] = -1.0f * scale[1] - off[1];
+ coords[24*i+5*4+0] = (1.0f + 2.0f*i) * scale[0] + off[0];
+ coords[24*i+5*4+1] = 1.0f * scale[1] - off[1];
+ coords[24*i+0*4+2] = ((float)printbuf[i]) / 256.0f;
+ coords[24*i+0*4+3] = 1.0f;
+ coords[24*i+1*4+2] = coords[24*i+4*4+2] = ((float)printbuf[i]) / 256.0f;
+ coords[24*i+1*4+3] = coords[24*i+4*4+3] = 0.0f;
+ coords[24*i+2*4+2] = coords[24*i+3*4+2] = ((float)(printbuf[i]+1)) / 256.0f;
+ coords[24*i+2*4+3] = coords[24*i+3*4+3] = 1.0f;
+ coords[24*i+5*4+2] = ((float)(printbuf[i]+1)) / 256.0f;
+ coords[24*i+5*4+3] = 0.0f;
+ }
+ pb->len += len * 24;
+ pb->changed = true;
+}
+
+static void pacc_buf_printf(
+ const struct pacc_ctx *pc, struct pacc_buf *pb,
+ int x, int y, const char *fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ pacc_buf_vprintf(pc, pb, x, y, fmt, ap);
+ va_end(ap);
+}
+
+static void pacc_buf_rect(
+ const struct pacc_ctx *pc, struct pacc_buf *pb,
+ int x, int y, int w, int h) {
+ pacc_buf_rect_off(pc, pb, x, y, w, h, 0, 0);
+}
+
+static void pacc_buf_clear(struct pacc_buf *pb) {
+ pb->len = 0;
+ pb->changed = true;
+}
+
+static void pacc_palette(struct pacc_ctx *pc, const uint8_t *rgb, int colors) {
+ memcpy(pc->pal, rgb, colors*3);
+ pc->pal_changed = true;
+}
+
+static void pacc_color(struct pacc_ctx *pc, uint8_t pal) {
+ pc->color = pal;
+ pc->color_changed = true;
+}
+
+static void pacc_begin_clear(struct pacc_ctx *pc) {
+ if (pc->pal_changed) {
+ D3DLOCKED_RECT lockrect;
+ if (SUCCEEDED(pc->tex_pal->lpVtbl->LockRect(
+ pc->tex_pal, 0, &lockrect, 0, D3DLOCK_DISCARD))) {
+ uint32_t *palpixel = lockrect.pBits;
+ for (int i = 0; i < 256; i++) {
+ palpixel[i] =
+ ((uint32_t)pc->pal[i*3+0]) << 16 |
+ ((uint32_t)pc->pal[i*3+1]) << 8 |
+ pc->pal[i*3+2];
+ }
+ pc->tex_pal->lpVtbl->UnlockRect(
+ pc->tex_pal, 0);
+ }
+ pc->pal_changed = false;
+ }
+ pc->d3d9d->lpVtbl->Clear(
+ pc->d3d9d,
+ 0, 0, D3DCLEAR_TARGET,
+ D3DCOLOR_RGBA(
+ pc->pal[0], pc->pal[1], pc->pal[2], 0xff
+ ), 1.0, 0);
+ pc->state_common->lpVtbl->Apply(pc->state_common);
+ float offsets[4] = {
+ -0.5f / pc->w, 0.5f / pc->h, 0.0f, 0.0f,
+ };
+ pc->d3d9d->lpVtbl->SetVertexShaderConstantF(
+ pc->d3d9d,
+ 0, offsets, 1);
+ pc->curr_mode = pacc_mode_count;
+}
+
+static void pacc_draw(struct pacc_ctx *pc, struct pacc_buf *pb, enum pacc_mode mode) {
+ if (mode >= pacc_mode_count) return;
+ if (pc->curr_mode != mode) {
+ pc->state_modes[mode]->lpVtbl->Apply(pc->state_modes[mode]);
+ pc->curr_mode = mode;
+ }
+ if (mode != pacc_mode_copy && pc->color_changed) {
+ float fbuf[4] = {pc->color / 255.f};
+ pc->d3d9d->lpVtbl->SetPixelShaderConstantF(pc->d3d9d, 0, fbuf, 1);
+ pc->color_changed = false;
+ }
+ if (pb->tex->changed) {
+ D3DLOCKED_RECT lockrect;
+ if (SUCCEEDED(pb->tex->tex_obj->lpVtbl->LockRect(
+ pb->tex->tex_obj, 0, &lockrect, 0, 0))) {
+ while (atomic_flag_test_and_set_explicit(&pb->tex->flag, memory_order_acquire));
+ for (int y = 0; y < pb->tex->h; y++) {
+ memcpy(
+ (char *)lockrect.pBits + lockrect.Pitch * y,
+ pb->tex->buf + pb->tex->w * y,
+ pb->tex->w);
+ }
+ atomic_flag_clear_explicit(&pb->tex->flag, memory_order_release);
+ pb->tex->tex_obj->lpVtbl->UnlockRect(
+ pb->tex->tex_obj, 0);
+ }
+ pb->tex->changed = false;
+ }
+ if (pb->changed) {
+ if (pb->buflen > pb->bufobjlen) {
+ IDirect3DVertexBuffer9 *newbufobj;
+ HRESULT res;
+ res = pc->d3d9d->lpVtbl->CreateVertexBuffer(
+ pc->d3d9d,
+ sizeof(*pb->buf) * pb->buflen,
+ D3DUSAGE_DYNAMIC,
+ 0,
+ D3DPOOL_DEFAULT,
+ &newbufobj,
+ 0);
+ if (res != D3D_OK) return;
+ pb->buf_obj->lpVtbl->Release(pb->buf_obj);
+ pb->buf_obj = newbufobj;
+ pb->bufobjlen = pb->buflen;
+ }
+ float *objbuf;
+ if (SUCCEEDED(pb->buf_obj->lpVtbl->Lock(
+ pb->buf_obj,
+ 0, sizeof(float)*pb->len,
+ (void **)&objbuf,
+ D3DLOCK_DISCARD))) {
+ memcpy(objbuf, pb->buf, pb->len*sizeof(pb->buf[0]));
+ pb->buf_obj->lpVtbl->Unlock(pb->buf_obj);
+ }
+ pb->changed = false;
+ }
+ DWORD texaddru, texaddrv;
+ if (pb->tex->w & (pb->tex->w - 1)) {
+ texaddru = D3DTADDRESS_CLAMP;
+ } else {
+ texaddru = D3DTADDRESS_WRAP;
+ }
+ if (pb->tex->h & (pb->tex->h - 1)) {
+ texaddrv = D3DTADDRESS_CLAMP;
+ } else {
+ texaddrv = D3DTADDRESS_WRAP;
+ }
+ pc->d3d9d->lpVtbl->SetSamplerState(
+ pc->d3d9d, 1, D3DSAMP_ADDRESSU, texaddru);
+ pc->d3d9d->lpVtbl->SetSamplerState(
+ pc->d3d9d, 1, D3DSAMP_ADDRESSV, texaddrv);
+ pc->d3d9d->lpVtbl->SetTexture(
+ pc->d3d9d, 1, (IDirect3DBaseTexture9 *)pb->tex->tex_obj);
+ pc->d3d9d->lpVtbl->SetStreamSource(
+ pc->d3d9d,
+ 0,
+ pb->buf_obj,
+ 0, 4*sizeof(float));
+ pc->d3d9d->lpVtbl->DrawPrimitive(
+ pc->d3d9d,
+ D3DPT_TRIANGLELIST,
+ 0, pb->len/(3*4));
+}
+
+static uint8_t *pacc_tex_lock(struct pacc_tex *pt) {
+ while (atomic_flag_test_and_set_explicit(&pt->flag, memory_order_acquire));
+ return pt->buf;
+}
+
+static void pacc_tex_unlock(struct pacc_tex *pt) {
+ pt->changed = true;
+ atomic_flag_clear_explicit(&pt->flag, memory_order_release);
+}
+
+static void pacc_tex_delete(struct pacc_tex *pt) {
+ if (pt) {
+ if (pt->tex_obj) pt->tex_obj->lpVtbl->Release(pt->tex_obj);
+ free(pt->buf);
+ free(pt);
+ }
+}
+
+static struct pacc_tex *pacc_gen_tex(struct pacc_ctx *pc, int w, int h) {
+ struct pacc_tex *pt = malloc(sizeof(*pt));
+ if (!pt) goto err;
+ *pt = (struct pacc_tex) {
+ .w = w,
+ .h = h,
+ .buf = calloc(w*h, 1),
+ };
+ if (!pt->buf) goto err;
+ atomic_flag_clear_explicit(&pt->flag, memory_order_release);
+ HRESULT res;
+ res = pc->d3d9d->lpVtbl->CreateTexture(
+ pc->d3d9d,
+ w, h,
+ 1,
+ D3DUSAGE_DYNAMIC,
+ D3DFMT_L8,
+ D3DPOOL_DEFAULT,
+ &pt->tex_obj,
+ 0);
+ if (res != D3D_OK) goto err;
+ return pt;
+err:
+ pacc_tex_delete(pt);
+ return 0;
+}
+
+static void pacc_delete(struct pacc_ctx *pc) {
+ if (pc) {
+ if (pc->renderthread) {
+ atomic_store_explicit(&pc->killthread, true, memory_order_relaxed);
+ WaitForSingleObject(pc->renderthread, INFINITE);
+ }
+ for (int i = 0; i < pacc_mode_count; i++) {
+ if (pc->ps_modes[i]) pc->ps_modes[i]->lpVtbl->Release(pc->ps_modes[i]);
+ if (pc->state_modes[i]) pc->state_modes[i]->lpVtbl->Release(pc->state_modes[i]);
+ }
+ if (pc->state_common) pc->state_common->lpVtbl->Release(pc->state_common);
+ if (pc->vs) pc->vs->lpVtbl->Release(pc->vs);
+ if (pc->vdecl) pc->vdecl->lpVtbl->Release(pc->vdecl);
+ if (pc->tex_pal) pc->tex_pal->lpVtbl->Release(pc->tex_pal);
+ if (pc->d3d9d) pc->d3d9d->lpVtbl->Release(pc->d3d9d);
+ if (pc->d3d9) pc->d3d9->lpVtbl->Release(pc->d3d9);
+ if (pc->d3d9m) FreeLibrary(pc->d3d9m);
+ if (pc->rendermtx) CloseHandle(pc->rendermtx);
+ free(pc);
+ }
+}
+
+static DWORD WINAPI pacc_renderproc(void *ptr) {
+ struct pacc_ctx *pc = ptr;
+ while (!atomic_load_explicit(&pc->killthread, memory_order_relaxed)) {
+ if (WaitForSingleObject(pc->rendermtx, INFINITE) == WAIT_OBJECT_0) {
+ if (SUCCEEDED(pc->d3d9d->lpVtbl->BeginScene(pc->d3d9d))) {
+ if (pc->render_enabled) {
+ pc->rendercb(pc->renderptr);
+ } else {
+ pc->d3d9d->lpVtbl->Clear(
+ pc->d3d9d,
+ 0, 0, D3DCLEAR_TARGET,
+ D3DCOLOR_RGBA(0x00, 0x00, 0x00, 0xff),
+ 1.0, 0);
+ }
+ pc->d3d9d->lpVtbl->EndScene(pc->d3d9d);
+ pc->d3d9d->lpVtbl->Present(pc->d3d9d, 0, 0, 0, 0);
+ }
+ ReleaseMutex(pc->rendermtx);
+ }
+ }
+ return 0;
+}
+
+static void pacc_renderctrl(struct pacc_ctx *pc, bool enable) {
+ while (WaitForSingleObject(pc->rendermtx, INFINITE) != WAIT_OBJECT_0);
+ pc->render_enabled = enable;
+ ReleaseMutex(pc->rendermtx);
+}
+
+static struct pacc_vtable pacc_d3d9_vtable = {
+ .pacc_delete = pacc_delete,
+ .gen_buf = pacc_gen_buf,
+ .gen_tex = pacc_gen_tex,
+ .buf_delete = pacc_buf_delete,
+ .tex_lock = pacc_tex_lock,
+ .tex_unlock = pacc_tex_unlock,
+ .tex_delete = pacc_tex_delete,
+ .buf_rect = pacc_buf_rect,
+ .buf_rect_off = pacc_buf_rect_off,
+ .buf_vprintf = pacc_buf_vprintf,
+ .buf_printf = pacc_buf_printf,
+ .buf_clear = pacc_buf_clear,
+ .palette = pacc_palette,
+ .color = pacc_color,
+ .begin_clear = pacc_begin_clear,
+ .draw = pacc_draw,
+};
+
+struct pacc_win_vtable pacc_win_vtable = {
+ .renderctrl = pacc_renderctrl,
+};
+
+struct pacc_ctx *pacc_init_d3d9(
+ HWND hwnd,
+ pacc_rendercb *rendercb, void *renderptr,
+ struct pacc_vtable *vt, struct pacc_win_vtable *winvt) {
+ struct pacc_ctx *pc = malloc(sizeof(*pc));
+ if (!pc) goto err;
+ RECT wr;
+ if (!GetClientRect(hwnd, &wr)) goto err;
+ *pc = (struct pacc_ctx) {
+ .w = wr.right - wr.left,
+ .h = wr.bottom - wr.top,
+ .hwnd = hwnd,
+ .rendercb = rendercb,
+ .renderptr = renderptr,
+ };
+ atomic_init(&pc->killthread, false);
+ pc->rendermtx = CreateMutex(0, FALSE, 0);
+ if (!pc->rendermtx) goto err;
+ pc->d3d9m = LoadLibrary(L"d3d9");
+ if (!pc->d3d9m) goto err;
+ IDirect3D9 * WINAPI (*d3d9create)(UINT) = (IDirect3D9 * WINAPI (*)(UINT))GetProcAddress(pc->d3d9m, "Direct3DCreate9");
+ if (!d3d9create) goto err;
+ pc->d3d9 = d3d9create(D3D_SDK_VERSION);
+ if (!pc->d3d9) goto err;
+
+ D3DCAPS9 dcaps;
+ HRESULT res;
+ res = pc->d3d9->lpVtbl->GetDeviceCaps(
+ pc->d3d9,
+ D3DADAPTER_DEFAULT,
+ D3DDEVTYPE_HAL,
+ &dcaps);
+ if (res != D3D_OK) goto err;
+
+ D3DMULTISAMPLE_TYPE ms;
+#ifdef PACC_DEBUG_MSAA
+ ms = D3DMULTISAMPLE_8_SAMPLES;
+#else
+ ms = D3DMULTISAMPLE_NONE;
+#endif
+ D3DPRESENT_PARAMETERS dp = {
+ .MultiSampleType = ms,
+ .BackBufferWidth = pc->w * 2,
+ .BackBufferHeight = pc->h * 2,
+ .SwapEffect = D3DSWAPEFFECT_DISCARD,
+ .hDeviceWindow = pc->hwnd,
+ .Windowed = TRUE,
+ };
+ DWORD behavior = D3DCREATE_MULTITHREADED;
+ /* from SDL_renderer_d3d.c
+ fallback to software vertex processing when hardware vertex processing not available
+ */
+ behavior |= (dcaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) ?
+ D3DCREATE_HARDWARE_VERTEXPROCESSING :
+ D3DCREATE_SOFTWARE_VERTEXPROCESSING;
+ res = pc->d3d9->lpVtbl->CreateDevice(
+ pc->d3d9,
+ D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
+ 0,
+ behavior,
+ &dp, &pc->d3d9d);
+ if (res != D3D_OK) goto err;
+ res = pc->d3d9d->lpVtbl->CreateTexture(
+ pc->d3d9d,
+ 256, 1,
+ 1,
+ D3DUSAGE_DYNAMIC,
+ D3DFMT_X8R8G8B8,
+ D3DPOOL_DEFAULT,
+ &pc->tex_pal,
+ 0);
+ if (res != D3D_OK) goto err;
+
+ D3DVERTEXELEMENT9 vertexdecls[] = {
+ {
+ .Stream = 0,
+ .Offset = 0,
+ .Type = D3DDECLTYPE_FLOAT4,
+ .Method = D3DDECLMETHOD_DEFAULT,
+ .Usage = D3DDECLUSAGE_POSITION,
+ .UsageIndex = 0,
+ },
+ D3DDECL_END()
+ };
+ res = pc->d3d9d->lpVtbl->CreateVertexDeclaration(
+ pc->d3d9d,
+ vertexdecls,
+ &pc->vdecl);
+ if (res != D3D_OK) goto err;
+ res = pc->d3d9d->lpVtbl->CreateVertexShader(
+ pc->d3d9d,
+ (const DWORD *)vs20_blit, &pc->vs);
+ if (res != D3D_OK) goto err;
+ res = pc->d3d9d->lpVtbl->CreatePixelShader(
+ pc->d3d9d,
+ (const DWORD *)ps20_copy, &pc->ps_modes[pacc_mode_copy]);
+ if (res != D3D_OK) goto err;
+ res = pc->d3d9d->lpVtbl->CreatePixelShader(
+ pc->d3d9d,
+ (const DWORD *)ps20_color, &pc->ps_modes[pacc_mode_color]);
+ if (res != D3D_OK) goto err;
+ res = pc->d3d9d->lpVtbl->CreatePixelShader(
+ pc->d3d9d,
+ (const DWORD *)ps20_color_trans, &pc->ps_modes[pacc_mode_color_trans]);
+ if (res != D3D_OK) goto err;
+
+ res = pc->d3d9d->lpVtbl->BeginStateBlock(pc->d3d9d);
+ if (res != D3D_OK) goto err;
+ res = pc->d3d9d->lpVtbl->SetVertexDeclaration(
+ pc->d3d9d, pc->vdecl);
+ if (res != D3D_OK) goto err;
+ res = pc->d3d9d->lpVtbl->SetRenderState(
+ pc->d3d9d, D3DRS_CULLMODE, D3DCULL_NONE);
+ if (res != D3D_OK) goto err;
+ res = pc->d3d9d->lpVtbl->SetVertexShader(
+ pc->d3d9d, pc->vs);
+ if (res != D3D_OK) goto err;
+ res = pc->d3d9d->lpVtbl->SetSamplerState(
+ pc->d3d9d, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
+ if (res != D3D_OK) goto err;
+ res = pc->d3d9d->lpVtbl->SetSamplerState(
+ pc->d3d9d, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
+ if (res != D3D_OK) goto err;
+ res = pc->d3d9d->lpVtbl->SetSamplerState(
+ pc->d3d9d, 1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
+ if (res != D3D_OK) goto err;
+ res = pc->d3d9d->lpVtbl->SetSamplerState(
+ pc->d3d9d, 1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
+ if (res != D3D_OK) goto err;
+#ifdef PACC_DEBUG_MSAA
+ res = pc->d3d9d->lpVtbl->SetSamplerState(
+ pc->d3d9d, 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+ if (res != D3D_OK) goto err;
+#endif
+ res = pc->d3d9d->lpVtbl->SetTexture(
+ pc->d3d9d, 0, (IDirect3DBaseTexture9 *)pc->tex_pal);
+ if (res != D3D_OK) goto err;
+ res = pc->d3d9d->lpVtbl->EndStateBlock(pc->d3d9d, &pc->state_common);
+ if (res != D3D_OK) goto err;
+
+ res = pc->d3d9d->lpVtbl->BeginStateBlock(pc->d3d9d);
+ if (res != D3D_OK) goto err;
+ res = pc->d3d9d->lpVtbl->SetPixelShader(pc->d3d9d, pc->ps_modes[pacc_mode_copy]);
+ if (res != D3D_OK) goto err;
+ res = pc->d3d9d->lpVtbl->EndStateBlock(pc->d3d9d, &pc->state_modes[pacc_mode_copy]);
+ if (res != D3D_OK) goto err;
+
+ res = pc->d3d9d->lpVtbl->BeginStateBlock(pc->d3d9d);
+ if (res != D3D_OK) goto err;
+ res = pc->d3d9d->lpVtbl->SetPixelShader(pc->d3d9d, pc->ps_modes[pacc_mode_color]);
+ if (res != D3D_OK) goto err;
+ res = pc->d3d9d->lpVtbl->EndStateBlock(pc->d3d9d, &pc->state_modes[pacc_mode_color]);
+ if (res != D3D_OK) goto err;
+
+ res = pc->d3d9d->lpVtbl->BeginStateBlock(pc->d3d9d);
+ if (res != D3D_OK) goto err;
+ res = pc->d3d9d->lpVtbl->SetPixelShader(pc->d3d9d, pc->ps_modes[pacc_mode_color_trans]);
+ if (res != D3D_OK) goto err;
+ res = pc->d3d9d->lpVtbl->EndStateBlock(pc->d3d9d, &pc->state_modes[pacc_mode_color_trans]);
+ if (res != D3D_OK) goto err;
+
+ pc->renderthread = CreateThread(0, 0, pacc_renderproc, pc, 0, 0);
+ if (!pc->renderthread) goto err;
+ *vt = pacc_d3d9_vtable;
+ *winvt = pacc_win_vtable;
+ return pc;
+err:
+ pacc_delete(pc);
+ return 0;
+}
diff --git a/pacc/pacc-gl-procs.inc b/pacc/pacc-gl-procs.inc
new file mode 100644
index 0000000..cd991e0
--- /dev/null
+++ b/pacc/pacc-gl-procs.inc
@@ -0,0 +1,46 @@
+#ifndef PROC_NO_GL_1_3
+#ifndef PROC_NO_GL_1_1
+PROC(CLEAR, Clear)
+PROC(DELETETEXTURES, DeleteTextures)
+PROC(TEXIMAGE2D, TexImage2D)
+PROC(CLEARCOLOR, ClearColor)
+PROC(BINDTEXTURE, BindTexture)
+PROC(GENTEXTURES, GenTextures)
+PROC(TEXPARAMETERI, TexParameteri)
+PROC(PIXELSTOREI, PixelStorei)
+PROC(DRAWARRAYS, DrawArrays)
+#endif // PROC_NO_GL_1_1
+PROC(ACTIVETEXTURE, ActiveTexture)
+#endif // PROC_NO_GL_1_3
+PROC(DELETEPROGRAM, DeleteProgram)
+PROC(CREATESHADER, CreateShader)
+PROC(SHADERSOURCE, ShaderSource)
+PROC(COMPILESHADER, CompileShader)
+PROC(GETSHADERIV, GetShaderiv)
+#ifndef NDEBUG
+PROC(GETSHADERINFOLOG, GetShaderInfoLog)
+#endif
+PROC(DELETESHADER, DeleteShader)
+PROC(CREATEPROGRAM, CreateProgram)
+PROC(ATTACHSHADER, AttachShader)
+PROC(BINDATTRIBLOCATION, BindAttribLocation)
+PROC(LINKPROGRAM, LinkProgram)
+PROC(GETPROGRAMIV, GetProgramiv)
+#ifndef NDEBUG
+PROC(GETPROGRAMINFOLOG, GetProgramInfoLog)
+#endif
+PROC(USEPROGRAM, UseProgram)
+PROC(UNIFORM1I, Uniform1i)
+PROC(GETUNIFORMLOCATION, GetUniformLocation)
+PROC(DELETEBUFFERS, DeleteBuffers)
+PROC(GENBUFFERS, GenBuffers)
+PROC(UNIFORM1F, Uniform1f)
+PROC(BINDBUFFER, BindBuffer)
+PROC(BUFFERDATA, BufferData)
+PROC(ENABLEVERTEXATTRIBARRAY, EnableVertexAttribArray)
+PROC(VERTEXATTRIBPOINTER, VertexAttribPointer)
+#ifdef PACC_GL_3
+PROC(DELETEVERTEXARRAYS, DeleteVertexArrays)
+PROC(GENVERTEXARRAYS, GenVertexArrays)
+PROC(BINDVERTEXARRAY, BindVertexArray)
+#endif
diff --git a/pacc/pacc-gl.c b/pacc/pacc-gl.c
new file mode 100644
index 0000000..e6ed0a1
--- /dev/null
+++ b/pacc/pacc-gl.c
@@ -0,0 +1,505 @@
+#include "pacc-gl.h"
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include "pacc-gl-inc.h"
+
+#ifdef NDEBUG
+#define DPRINTF(fmt, ...)
+#else
+#include <stdio.h>
+#define DPRINTF(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
+#endif
+
+/*
+ OpenGL versions:
+ OpenGL 2.0
+ OpenGL 3.2 core (#define PACC_GL_3)
+ OpenGL ES 2.0 (#define PACC_GL_ES)
+ OpenGL ES 3.0 (#define PACC_GL_ES, #define PACC_GL_3)
+
+ Shader languages:
+ GLSL 1.10 / GLSL ES 1.00
+*/
+
+#ifdef PACC_GL_ES
+#include "glsl/esheader.inc"
+#else
+#include "glsl/dsheader.inc"
+#endif
+
+#include "glsl/blit.vert.inc"
+#include "glsl/copy.frag.inc"
+#include "glsl/color.frag.inc"
+#include "glsl/color_trans.frag.inc"
+
+struct pacc_ctx {
+ int w;
+ int h;
+ uint8_t pal[256*3];
+ bool pal_changed;
+ uint8_t clearcolor[3];
+ GLuint tex_pal;
+ GLuint progs[pacc_mode_count];
+ GLint uni_color, uni_color_trans;
+ uint8_t color;
+ bool color_changed;
+ enum pacc_mode curr_mode;
+};
+
+struct pacc_buf {
+ GLuint buf_obj;
+ GLuint va_obj; // for OpenGL 3.2 Core
+ GLfloat *buf;
+ struct pacc_tex *tex;
+ int len;
+ int buflen;
+ GLenum usage;
+ bool changed;
+};
+
+struct pacc_tex {
+ GLuint tex_obj;
+ int w, h;
+ bool changed;
+ uint8_t *buf;
+};
+
+enum {
+ VAI_COORD,
+};
+
+enum {
+ PACC_BUF_DEF_LEN = 32,
+ PRINTBUFLEN = 160,
+};
+
+static void pacc_delete(struct pacc_ctx *pc) {
+ if (pc) {
+ glDeleteTextures(1, &pc->tex_pal);
+ for (int i = 0; i < pacc_mode_count; i++) {
+ glDeleteProgram(pc->progs[i]);
+ }
+ free(pc);
+ }
+}
+
+static GLuint compile_shader(const uint8_t *ss, GLenum type) {
+ GLuint s = glCreateShader(type);
+ if (!s) goto err;
+ const char *sourcelist[2] = {
+#ifdef PACC_GL_ES
+ (const char *)esheader,
+#else
+ (const char *)dsheader,
+#endif
+ (const char *)ss
+ };
+ glShaderSource(s, 2, sourcelist, 0);
+ glCompileShader(s);
+ GLint res;
+ glGetShaderiv(s, GL_COMPILE_STATUS, &res);
+ if (!res) {
+#ifndef NDEBUG
+ glGetShaderiv(s, GL_INFO_LOG_LENGTH, &res);
+ char *msgbuf = malloc(res);
+ if (msgbuf) {
+ glGetShaderInfoLog(s, res, 0, msgbuf);
+ DPRINTF("%s shader error: \n%s\n", type == GL_VERTEX_SHADER ? "vertex" : "fragment", msgbuf);
+ DPRINTF("s:\n%s\n", ss);
+ free(msgbuf);
+ }
+#endif
+ goto err;
+ }
+ return s;
+err:
+ glDeleteShader(s);
+ return 0;
+}
+
+static GLuint compile_and_link(const uint8_t *vss, const uint8_t *fss) {
+ GLuint p = 0, vs = 0, fs = 0;
+ p = glCreateProgram();
+ if (!p) goto err;
+ vs = compile_shader(vss, GL_VERTEX_SHADER);
+ if (!vs) goto err;
+ fs = compile_shader(fss, GL_FRAGMENT_SHADER);
+ if (!fs) goto err;
+ glAttachShader(p, vs);
+ glAttachShader(p, fs);
+ glBindAttribLocation(p, VAI_COORD, "coord");
+ glLinkProgram(p);
+ GLint res;
+ glGetProgramiv(p, GL_LINK_STATUS, &res);
+ if (!res) {
+#ifndef NDEBUG
+ glGetProgramiv(p, GL_INFO_LOG_LENGTH, &res);
+ char *msgbuf = malloc(res);
+ if (msgbuf) {
+ glGetProgramInfoLog(p, res, 0, msgbuf);
+ DPRINTF("program link error: \n%s\n", msgbuf);
+ DPRINTF("vs:\n%s\n", vss);
+ DPRINTF("fs:\n%s\n", fss);
+ free(msgbuf);
+ }
+#endif
+ goto err;
+ }
+ glDeleteShader(vs);
+ glDeleteShader(fs);
+ glUseProgram(p);
+ glUniform1i(glGetUniformLocation(p, "tex"), 1);
+ return p;
+err:
+ glDeleteProgram(p);
+ glDeleteShader(vs);
+ glDeleteShader(fs);
+ return 0;
+}
+
+static void pacc_buf_delete(struct pacc_buf *pb) {
+ if (pb) {
+ free(pb->buf);
+ glDeleteBuffers(1, &pb->buf_obj);
+#ifdef PACC_GL_3
+ glDeleteVertexArrays(1, &pb->va_obj);
+#endif
+ free(pb);
+ }
+}
+
+static struct pacc_buf *pacc_gen_buf(
+ struct pacc_ctx *pc, struct pacc_tex *pt, enum pacc_buf_mode mode) {
+ struct pacc_buf *pb = malloc(sizeof(*pb));
+ if (!pb) goto err;
+ *pb = (struct pacc_buf) {
+ .buflen = PACC_BUF_DEF_LEN,
+ .tex = pt,
+ .usage = (mode == pacc_buf_mode_static) ?
+ GL_STATIC_DRAW : GL_STREAM_DRAW,
+ };
+ pb->buf = malloc(sizeof(*pb->buf) * pb->buflen);
+ if (!pb->buf) goto err;
+ glGenBuffers(1, &pb->buf_obj);
+ if (!pb->buf_obj) goto err;
+#ifdef PACC_GL_3
+ glGenVertexArrays(1, &pb->va_obj);
+ if (!pb->va_obj) goto err;
+ glBindVertexArray(pb->va_obj);
+ glEnableVertexAttribArray(VAI_COORD);
+ glBindBuffer(GL_ARRAY_BUFFER, pb->buf_obj);
+ glVertexAttribPointer(VAI_COORD, 4, GL_FLOAT, GL_FALSE, 0, 0);
+#endif
+ return pb;
+err:
+ pacc_buf_delete(pb);
+ return 0;
+}
+
+static bool buf_reserve(struct pacc_buf *pb, int len) {
+ if (pb->len + len > pb->buflen) {
+ int newlen = pb->buflen;
+ while (pb->len + len > newlen) newlen *= 2;
+ GLfloat *newbuf = realloc(pb->buf, newlen * sizeof(pb->buf[0]));
+ if (!newbuf) return false;
+ pb->buflen = newlen;
+ pb->buf = newbuf;
+ }
+ return true;
+}
+
+static void pacc_calc_scale(float *ret, int w, int h, int wdest, int hdest) {
+ ret[0] = ((float)w) / wdest;
+ ret[1] = ((float)h) / hdest;
+}
+
+static void pacc_calc_off_tex(float *ret,
+ int tw, int th, int xsrc, int ysrc) {
+ ret[0] = ((float)xsrc) / tw;
+ ret[1] = ((float)ysrc) / th;
+}
+
+static void pacc_calc_off(
+ float *ret, int xdest, int ydest, int w, int h, int wdest, int hdest) {
+ ret[0] = ((float)(xdest * 2 + w - wdest)) / wdest;
+ ret[1] = ((float)(ydest * 2 + h - hdest)) / hdest;
+}
+
+static void pacc_buf_rect_off(
+ const struct pacc_ctx *pc, struct pacc_buf *pb,
+ int x, int y, int w, int h, int xoff, int yoff) {
+ float scale[2];
+ float off[2];
+ float tscale[2];
+ float toff[2];
+ pacc_calc_off(off, x, y, w, h, pc->w, pc->h);
+ pacc_calc_scale(scale, w, h, pc->w, pc->h);
+ pacc_calc_off_tex(toff, pb->tex->w, pb->tex->h, xoff, yoff);
+ pacc_calc_scale(tscale, w, h, pb->tex->w, pb->tex->h);
+ GLfloat coord[16] = {
+ -1.0f * scale[0] + off[0], -1.0f * scale[1] - off[1],
+ 0.0f * tscale[0] + toff[0], 1.0f * tscale[1] + toff[1],
+
+ -1.0f * scale[0] + off[0], 1.0f * scale[1] - off[1],
+ 0.0f * tscale[0] + toff[0], 0.0f * tscale[1] + toff[1],
+
+ 1.0f * scale[0] + off[0], -1.0f * scale[1] - off[1],
+ 1.0f * tscale[0] + toff[0], 1.0f * tscale[1] + toff[1],
+
+ 1.0f * scale[0] + off[0], 1.0f * scale[1] - off[1],
+ 1.0f * tscale[0] + toff[0], 0.0f * tscale[1] + toff[1],
+ };
+ if (!buf_reserve(pb, 24)) return;
+ int indices[6] = {0, 1, 2, 2, 1, 3};
+ for (int i = 0; i < 6; i++) {
+ for (int j = 0; j < 4; j++) {
+ pb->buf[pb->len+i*4+j] = coord[indices[i]*4+j];
+ }
+ }
+ pb->len += 24;
+ pb->changed = true;
+}
+
+static void pacc_buf_vprintf(
+ const struct pacc_ctx *pc, struct pacc_buf *pb,
+ int x, int y, const char *fmt, va_list ap) {
+ uint8_t printbuf[PRINTBUFLEN+1];
+ vsnprintf((char *)printbuf, sizeof(printbuf), fmt, ap);
+ int len = strlen((const char *)printbuf);
+ float scale[2];
+ float off[2];
+ int w = pb->tex->w / 256;
+ int h = pb->tex->h;
+ pacc_calc_scale(scale, w, h, pc->w, pc->h);
+ pacc_calc_off(off, x, y, w, h, pc->w, pc->h);
+ if (!buf_reserve(pb, len*24)) return;
+ GLfloat *coords = pb->buf + pb->len;
+ for (int i = 0; i < len; i++) {
+ coords[24*i+0*4+0] = (-1.0f + 2.0f*i) * scale[0] + off[0];
+ coords[24*i+0*4+1] = -1.0f * scale[1] - off[1];
+ coords[24*i+1*4+0] = coords[24*i+4*4+0] = (-1.0f + 2.0f*i) * scale[0] + off[0];
+ coords[24*i+1*4+1] = coords[24*i+4*4+1] = 1.0f * scale[1] - off[1];
+ coords[24*i+2*4+0] = coords[24*i+3*4+0] = (1.0f + 2.0f*i) * scale[0] + off[0];
+ coords[24*i+2*4+1] = coords[24*i+3*4+1] = -1.0f * scale[1] - off[1];
+ coords[24*i+5*4+0] = (1.0f + 2.0f*i) * scale[0] + off[0];
+ coords[24*i+5*4+1] = 1.0f * scale[1] - off[1];
+ coords[24*i+0*4+2] = ((float)printbuf[i]) / 256.0f;
+ coords[24*i+0*4+3] = 1.0f;
+ coords[24*i+1*4+2] = coords[24*i+4*4+2] = ((float)printbuf[i]) / 256.0f;
+ coords[24*i+1*4+3] = coords[24*i+4*4+3] = 0.0f;
+ coords[24*i+2*4+2] = coords[24*i+3*4+2] = ((float)(printbuf[i]+1)) / 256.0f;
+ coords[24*i+2*4+3] = coords[24*i+3*4+3] = 1.0f;
+ coords[24*i+5*4+2] = ((float)(printbuf[i]+1)) / 256.0f;
+ coords[24*i+5*4+3] = 0.0f;
+ }
+ pb->len += len * 24;
+ pb->changed = true;
+}
+
+static void pacc_buf_printf(
+ const struct pacc_ctx *pc, struct pacc_buf *pb,
+ int x, int y, const char *fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ pacc_buf_vprintf(pc, pb, x, y, fmt, ap);
+ va_end(ap);
+}
+
+static void pacc_buf_rect(
+ const struct pacc_ctx *pc, struct pacc_buf *pb,
+ int x, int y, int w, int h) {
+ pacc_buf_rect_off(pc, pb, x, y, w, h, 0, 0);
+}
+
+static void pacc_buf_clear(struct pacc_buf *pb) {
+ pb->len = 0;
+ pb->changed = true;
+}
+
+static void pacc_palette(struct pacc_ctx *pc, const uint8_t *rgb, int colors) {
+ memcpy(pc->pal, rgb, colors*3);
+ pc->pal_changed = true;
+}
+
+static void pacc_color(struct pacc_ctx *pc, uint8_t pal) {
+ pc->color = pal;
+ pc->color_changed = true;
+}
+
+static void pacc_begin_clear(struct pacc_ctx *pc) {
+ if (pc->pal_changed) {
+ glActiveTexture(GL_TEXTURE0);
+ glTexImage2D(
+ GL_TEXTURE_2D,
+ 0, GL_RGB,
+ 256, 1,
+ 0, GL_RGB,
+ GL_UNSIGNED_BYTE, pc->pal);
+ pc->pal_changed = false;
+ glActiveTexture(GL_TEXTURE1);
+ }
+ if (memcmp(pc->clearcolor, pc->pal, 3)) {
+ memcpy(pc->clearcolor, pc->pal, 3);
+ glClearColor(
+ pc->clearcolor[0] / 255.f,
+ pc->clearcolor[1] / 255.f,
+ pc->clearcolor[2] / 255.f,
+ 1.0f);
+ }
+ glClear(GL_COLOR_BUFFER_BIT);
+ pc->curr_mode = pacc_mode_count;
+}
+
+static void pacc_draw(struct pacc_ctx *pc, struct pacc_buf *pb, enum pacc_mode mode) {
+ if (!pb->len) return;
+ if (mode >= pacc_mode_count) return;
+ if (pc->curr_mode != mode) {
+ glUseProgram(pc->progs[mode]);
+ pc->curr_mode = mode;
+ }
+ if (mode != pacc_mode_copy && pc->color_changed) {
+ glUniform1f(pc->uni_color, pc->color / 255.f);
+ glUniform1f(pc->uni_color_trans, pc->color / 255.f);
+ pc->color_changed = false;
+ }
+ glBindTexture(GL_TEXTURE_2D, pb->tex->tex_obj);
+ if (pb->tex->changed) {
+ GLint format;
+#if PACC_GL_3
+ format = GL_RED;
+#else
+ format = GL_LUMINANCE;
+#endif
+ glTexImage2D(
+ GL_TEXTURE_2D,
+ 0, format,
+ pb->tex->w, pb->tex->h,
+ 0, format, GL_UNSIGNED_BYTE,
+ pb->tex->buf);
+ pb->tex->changed = false;
+ }
+ if (pb->changed) {
+ glBindBuffer(GL_ARRAY_BUFFER, pb->buf_obj);
+ glBufferData(
+ GL_ARRAY_BUFFER,
+ pb->len * sizeof(pb->buf[0]), pb->buf,
+ pb->usage);
+ pb->changed = false;
+ }
+#ifdef PACC_GL_3
+ glBindVertexArray(pb->va_obj);
+#else
+ glEnableVertexAttribArray(VAI_COORD);
+ glBindBuffer(GL_ARRAY_BUFFER, pb->buf_obj);
+ glVertexAttribPointer(VAI_COORD, 4, GL_FLOAT, GL_FALSE, 0, 0);
+#endif
+ glDrawArrays(GL_TRIANGLES, 0, pb->len / 4);
+}
+
+static uint8_t *pacc_tex_lock(struct pacc_tex *pt) {
+ return pt->buf;
+}
+
+static void pacc_tex_unlock(struct pacc_tex *pt) {
+ pt->changed = true;
+}
+
+static void pacc_tex_delete(struct pacc_tex *pt) {
+ if (pt) {
+ glDeleteTextures(1, &pt->tex_obj);
+ free(pt->buf);
+ free(pt);
+ }
+}
+
+static struct pacc_tex *pacc_gen_tex(struct pacc_ctx *pc, int w, int h) {
+ struct pacc_tex *pt = malloc(sizeof(*pt));
+ if (!pt) goto err;
+ *pt = (struct pacc_tex) {
+ .w = w,
+ .h = h,
+ .buf = calloc(w*h, 1),
+ };
+ if (!pt->buf) goto err;
+ glGenTextures(1, &pt->tex_obj);
+ glBindTexture(GL_TEXTURE_2D, pt->tex_obj);
+ GLint format;
+#ifdef PACC_GL_3
+ format = GL_RED;
+#else
+ format = GL_LUMINANCE;
+#endif
+ glTexImage2D(
+ GL_TEXTURE_2D,
+ 0, format,
+ w, h, 0,
+ format, GL_UNSIGNED_BYTE,
+ pt->buf);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ if (w & (w - 1)) {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ }
+ if (h & (h - 1)) {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ }
+ return pt;
+err:
+ pacc_tex_delete(pt);
+ return 0;
+}
+
+static struct pacc_vtable pacc_gl_vtable = {
+ .pacc_delete = pacc_delete,
+ .gen_buf = pacc_gen_buf,
+ .gen_tex = pacc_gen_tex,
+ .buf_delete = pacc_buf_delete,
+ .tex_lock = pacc_tex_lock,
+ .tex_unlock = pacc_tex_unlock,
+ .tex_delete = pacc_tex_delete,
+ .buf_rect = pacc_buf_rect,
+ .buf_rect_off = pacc_buf_rect_off,
+ .buf_vprintf = pacc_buf_vprintf,
+ .buf_printf = pacc_buf_printf,
+ .buf_clear = pacc_buf_clear,
+ .palette = pacc_palette,
+ .color = pacc_color,
+ .begin_clear = pacc_begin_clear,
+ .draw = pacc_draw,
+};
+
+struct pacc_ctx *pacc_init_gl(int w, int h, struct pacc_vtable *vt) {
+ struct pacc_ctx *pc = malloc(sizeof(*pc));
+ if (!pc) goto err;
+ *pc = (struct pacc_ctx) {
+ .w = w,
+ .h = h,
+ };
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ glGenTextures(1, &pc->tex_pal);
+ glBindTexture(GL_TEXTURE_2D, pc->tex_pal);
+ glTexImage2D(
+ GL_TEXTURE_2D,
+ 0, GL_RGB,
+ 256, 1, 0,
+ GL_RGB, GL_UNSIGNED_BYTE,
+ pc->pal);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ pc->progs[pacc_mode_copy] = compile_and_link(blit_vert, copy_frag);
+ if (!pc->progs[pacc_mode_copy]) goto err;
+ pc->progs[pacc_mode_color] = compile_and_link(blit_vert, color_frag);
+ if (!pc->progs[pacc_mode_color]) goto err;
+ pc->progs[pacc_mode_color_trans] = compile_and_link(blit_vert, color_trans_frag);
+ if (!pc->progs[pacc_mode_color_trans]) goto err;
+ pc->uni_color = glGetUniformLocation(pc->progs[pacc_mode_color], "color");
+ pc->uni_color_trans = glGetUniformLocation(pc->progs[pacc_mode_color_trans], "color");
+ glActiveTexture(GL_TEXTURE1);
+ *vt = pacc_gl_vtable;
+ return pc;
+err:
+ pacc_delete(pc);
+ return 0;
+}
+
diff --git a/pacc/pacc-gl.h b/pacc/pacc-gl.h
new file mode 100644
index 0000000..2f5ccff
--- /dev/null
+++ b/pacc/pacc-gl.h
@@ -0,0 +1,8 @@
+#ifndef MYON_PACC_GL_H_INCLUDED
+#define MYON_PACC_GL_H_INCLUDED
+
+#include "pacc.h"
+
+struct pacc_ctx *pacc_init_gl(int w, int h, struct pacc_vtable *vt);
+
+#endif // MYON_PACC_GL_H_INCLUDED
diff --git a/pacc/pacc-win.h b/pacc/pacc-win.h
new file mode 100644
index 0000000..47c09d1
--- /dev/null
+++ b/pacc/pacc-win.h
@@ -0,0 +1,21 @@
+#ifndef MYON_PACC_WIN_H_INCLUDED
+#define MYON_PACC_WIN_H_INCLUDED
+
+#include "pacc.h"
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#include <stdbool.h>
+
+typedef void pacc_rendercb(void *ptr);
+
+struct pacc_win_vtable {
+ void (*renderctrl)(struct pacc_ctx *ctx, bool enable);
+};
+
+struct pacc_ctx *pacc_init_d3d9(HWND hwnd, pacc_rendercb *rendercb, void *renderptr, struct pacc_vtable *vt, struct pacc_win_vtable *winvt);
+
+#endif // MYON_PACC_WIN_H_INCLUDED
+
diff --git a/pacc/pacc.h b/pacc/pacc.h
new file mode 100644
index 0000000..b3387ac
--- /dev/null
+++ b/pacc/pacc.h
@@ -0,0 +1,53 @@
+#ifndef MYON_PACC_H_INCLUDED
+#define MYON_PACC_H_INCLUDED
+
+#include <stdint.h>
+#include <stdarg.h>
+
+enum pacc_mode {
+ pacc_mode_copy,
+ pacc_mode_color,
+ pacc_mode_color_trans,
+ pacc_mode_count,
+};
+
+enum pacc_buf_mode {
+ pacc_buf_mode_static,
+ pacc_buf_mode_stream,
+};
+
+struct pacc_ctx;
+struct pacc_tex;
+struct pacc_buf;
+
+struct pacc_vtable {
+ void (*pacc_delete)(struct pacc_ctx *pc);
+ struct pacc_buf *(*gen_buf)(
+ struct pacc_ctx *pc, struct pacc_tex *pt, enum pacc_buf_mode mode);
+ struct pacc_tex *(*gen_tex)(struct pacc_ctx *pc, int w, int h);
+ void (*buf_delete)(struct pacc_buf *buf);
+ uint8_t *(*tex_lock)(struct pacc_tex *tex);
+ void (*tex_unlock)(struct pacc_tex *tex);
+ void (*tex_delete)(struct pacc_tex *tex);
+ void (*buf_rect)(
+ const struct pacc_ctx *ctx, struct pacc_buf *buf,
+ int x, int y, int w, int h);
+ void (*buf_rect_off)(
+ const struct pacc_ctx *ctx, struct pacc_buf *buf,
+ int x, int y, int w, int h, int xoff, int yoff);
+ void (*buf_vprintf)(
+ const struct pacc_ctx *ctx, struct pacc_buf *buf,
+ int x, int y, const char *fmt, va_list ap);
+ void (*buf_printf)(
+ const struct pacc_ctx *ctx, struct pacc_buf *buf,
+ int x, int y, const char *fmt, ...);
+ void (*buf_clear)(struct pacc_buf *buf);
+ void (*palette)(struct pacc_ctx *ctx, const uint8_t *rgb, int colors);
+ void (*color)(struct pacc_ctx *ctx, uint8_t pal);
+ void (*begin_clear)(struct pacc_ctx *ctx);
+ void (*draw)(struct pacc_ctx *ctx, struct pacc_buf *buf, enum pacc_mode mode);
+};
+
+struct pacc_ctx *pacc_init_gl(int w, int h, struct pacc_vtable *vt);
+
+#endif // MYON_PACC_H_INCLUDED