+#ifdef BUILD_VR
+ int num_vr_sticks;
+
+ if(goatvr_invr() && (num_vr_sticks = goatvr_num_sticks()) > 0) {
+ float p[2];
+
+ goatvr_stick_pos(0, p);
+ p[1] *= 0.65; /* drops harder to trigger accidentally */
+
+ if(fabs(p[0]) > fabs(joy_axis[GPAD_LSTICK_X])) {
+ joy_axis[GPAD_LSTICK_X] = p[0];
+ }
+ if(fabs(p[1]) > fabs(joy_axis[GPAD_LSTICK_Y])) {
+ joy_axis[GPAD_LSTICK_Y] = -p[1];
+ }
+
+ if(goatvr_button_state(vrbn_a)) {
+ joy_bnstate |= 1 << GPAD_A;
+ }
+ if(goatvr_button_state(vrbn_x)) {
+ joy_bnstate |= 1 << GPAD_START;
+ }
+ if(goatvr_action(0, GOATVR_ACTION_TRIGGER) || goatvr_action(1, GOATVR_ACTION_TRIGGER)) {
+ joy_bnstate |= 1 << GPAD_UP;
+ }
+ }
+#endif /* BUILD_VR */
+
+ ginp_bnstate = 0;
+
+ /* joystick axis */
+ if(joy_axis[GPAD_LSTICK_X] >= JTHRES) {
+ ginp_bnstate |= GINP_RIGHT;
+ } else if(joy_axis[GPAD_LSTICK_X] <= -JTHRES) {
+ ginp_bnstate |= GINP_LEFT;
+ }
+
+ if(joy_axis[GPAD_LSTICK_Y] >= JTHRES) {
+ ginp_bnstate |= GINP_DOWN;
+ } else if(joy_axis[GPAD_LSTICK_Y] <= -JTHRES) {
+ ginp_bnstate |= GINP_UP;
+ }
+
+ CHECK_BUTTON(GPAD_LEFT, GINP_LEFT);
+ CHECK_BUTTON(GPAD_RIGHT, GINP_RIGHT);
+ CHECK_BUTTON(GPAD_UP, GINP_UP);
+ CHECK_BUTTON(GPAD_DOWN, GINP_DOWN);
+ CHECK_BUTTON(GPAD_A, GINP_ROTATE);
+ CHECK_BUTTON(GPAD_START, GINP_PAUSE);
+
+ update_ginp();
+
+ if(GINP_PRESS(GINP_LEFT)) {
+ game_keyboard('a', 1);
+ }
+ if(GINP_PRESS(GINP_RIGHT)) {
+ game_keyboard('d', 1);
+ }
+ if(GINP_PRESS(GINP_DOWN)) {
+ game_keyboard('s', 1);
+ }
+ if(GINP_PRESS(GINP_UP)) {
+ game_keyboard('\t', 1);
+ }
+ if(GINP_PRESS(GINP_ROTATE)) {
+ game_keyboard('w', 1);
+ }
+ if(GINP_PRESS(GINP_PAUSE)) {
+ game_keyboard('p', 1);
+ }
+
+#ifdef BUILD_VR
+ memset(joy_axis, 0, sizeof joy_axis);
+ joy_bnstate = 0;
+#endif
+}
+
+static void update(float dtsec)
+{
+ static long prev_tick;
+ long dt;
+
+ update_input(dtsec);
+
+ if(pause) {
+ prev_tick = time_msec;
+ return;
+ }
+ dt = time_msec - prev_tick;
+
+ if(gameover) {
+ int i, row = PF_ROWS - gameover;
+ unsigned int *ptr;
+
+ if(dt < GAMEOVER_FILL_RATE) {
+ return;
+ }
+
+ if(row >= 0) {
+ ptr = pfield + row * PF_COLS;
+ for(i=0; i<PF_COLS; i++) {
+ *ptr++ = PF_VIS | PF_FULL | 7;
+ }
+
+ gameover++;
+ prev_tick = time_msec;
+ }
+ return;
+ }
+
+ if(num_complines) {
+ /* lines where completed, we're in blinking mode */
+ int i, j, blink = dt >> 8;
+
+ if(blink > 6) {
+ erase_completed();
+ num_complines = 0;
+ return;
+ }
+
+ for(i=0; i<num_complines; i++) {
+ unsigned int *ptr = pfield + complines[i] * PF_COLS;
+ for(j=0; j<PF_COLS; j++) {
+ *ptr = (*ptr & ~PF_VIS) | ((blink & 1) << PF_VIS_SHIFT);
+ ptr++;
+ }
+ }
+ return;
+ }
+
+ /* fall */
+ while(dt >= tick_interval) {
+ if(cur_block >= 0) {
+ just_spawned = 0;
+ next_pos[0] = pos[0] + 1;
+ if(collision(cur_block, next_pos)) {
+ next_pos[0] = pos[0];
+ stick(cur_block, next_pos);
+ return;
+ }
+ } else {
+ /* respawn */
+ if(spawn() == -1) {
+ gameover = 1;
+ return;
+ }
+ }
+
+ dt -= tick_interval;
+ prev_tick = time_msec;
+ }
+
+ update_cur_block();