+/* player2 TH */
+#define PL2_ISFR PORTC_ISFR
+#define PL2_TH() ((CORE_PIN15_PINREG >> CORE_PIN15_BIT) & 1)
+#define PL2_ADJ(x) ((x) | ((x) << 12))
+
+static void pl2th_isr_fixed(void)
+{
+ uint32_t isfr, th, v;
+
+ isfr = PL2_ISFR;
+ PL2_ISFR = isfr;
+ th = PL2_TH();
+
+ v = g.pl[1].fixed_state[th];
+ GPIOB_PDOR = PL2_ADJ(v);
+}
+
+static noinline void do_to_step_pl2(void)
+{
+ g.pos_to_p[1].o = (g.pos_to_p[1].o + 1) & STREAM_BUF_MASK;
+ if (g.pos_to_p[1].o == g.pos_to_p[1].i)
+ // done
+ choose_isrs_idle();
+}
+
+static void pl2th_isr_do_to_inc(void)
+{
+ uint32_t isfr, th, v;
+
+ isfr = PL2_ISFR;
+ PL2_ISFR = isfr;
+ th = PL2_TH();
+
+ v = g.stream_to[1][g.pos_to_p[1].o][th];
+ GPIOB_PDOR = PL2_ADJ(v);
+ if (th)
+ do_to_step_pl2();
+}
+
+static void pl2th_isr_do_to_p1d(void)
+{
+ uint32_t isfr, th, v;
+
+ isfr = PL2_ISFR;
+ PL2_ISFR = isfr;
+ th = PL2_TH();
+
+ v = g.stream_to[1][g.pos_to_p[0].o][th];
+ GPIOB_PDOR = PL2_ADJ(v);
+
+ g.pos_to_p[1].o = g.pos_to_p[0].o;
+}
+
+static void pl2th_isr_do_to_inc_pl1(void)
+{
+ uint32_t isfr, th, v;
+
+ isfr = PL2_ISFR;
+ PL2_ISFR = isfr;
+ th = PL2_TH();
+
+ v = g.stream_to[1][g.pos_to_p[1].o][th];
+ GPIOB_PDOR = PL2_ADJ(v);
+ if (th) {
+ do_to_step_pl1();
+ g.pos_to_p[1].o = g.pos_to_p[0].o;
+ }
+}
+
+/* vsync handler */
+#define VSYNC_ISFR PORTC_ISFR
+
+static void vsync_isr_nop(void)