limit tickrate to half refresh rate
[d2d-md.git] / src / switch.c
blob8d4d488dedebf2d43ea5e97129ec35ecc4c1db2d
1 #include <genesis.h>
2 #include "switch.h"
3 #include "map.h"
5 #define MTYPE(x) (x & ~MAP_FORCECLEAR)
7 static switch_t g_sw[MAX_SWITCHES];
8 static u16 numsw = 0;
10 void sw_load(switch_t *sw, u16 num) {
11 numsw = num;
12 memcpy(g_sw, sw, sizeof(switch_t)*num);
15 static bool toggle(u8 sx, u8 sy, u8 from, u8 to) {
16 u8 *rowp = g_cells + sy*MAPW + sx;
17 u8 *cellp;
18 u8 ex, ey;
20 if (MTYPE(*rowp) != from)
21 return FALSE;
23 // find x extents of the door
24 ex = sx + 1;
25 for (cellp = rowp - 1; sx && MTYPE(*cellp) == from; --sx, --cellp);
26 for (cellp = rowp + 1; ex < MAPW && MTYPE(*cellp) == from; ++ex, ++cellp);
28 // find y extents of the door
29 ey = sy + 1;
30 for (cellp = rowp - MAPW; sy && MTYPE(*cellp) == from; --sy, cellp -= MAPW);
31 for (cellp = rowp + MAPW; ey < MAPH && MTYPE(*cellp) == from; ++ey, cellp += MAPW);
33 // gotta blast
34 const u8 dx = ex - sx;
35 rowp = g_cells + sy*MAPW + sx;
36 for (u8 y = sy; y < ey; ++y, rowp += MAPW)
37 memset(rowp, to, dx);
39 // update tiles that are on screen
40 if (MTYPE(to) == MAP_OPENDOOR)
41 map_clear_tile_rect(sx, sy, dx, ey-sy);
42 else
43 map_set_tile_rect(sx, sy, dx, ey-sy, g_map->tiles[tile_rowoff[sy] + sx]);
45 return TRUE;
48 static void door_open(switch_t *sw) {
49 if (toggle(sw->a, sw->b, MAP_DOOR, MAP_OPENDOOR | MAP_FORCECLEAR)) {
50 g_cells[sw->b*MAPW + sw->a] = MAP_OPENDOOR; // clear the clear flag to keep it there
51 map_set_tile(sw->a, sw->b, g_map->tiles[tile_rowoff[sw->b] + sw->a]);
55 static bool door_shut(switch_t *sw) {
56 toggle(sw->a, sw->b, MAP_OPENDOOR, MAP_DOOR);
57 return FALSE;
60 static inline void sw_trigger(switch_t *sw, u16 f) {
61 if (f & sw->flags) {
62 switch (sw->type) {
63 case SW_OPENDOOR:
64 if (g_cells[sw->b*MAPW + sw->a] != MAP_DOOR)
65 break;
66 door_open(sw);
67 sw->tm = 1;
68 break;
69 case SW_SHUTDOOR:
70 case SW_SHUTTRAP:
71 if (MTYPE(g_cells[sw->b*MAPW + sw->a]) != MAP_OPENDOOR)
72 break;
73 if (door_shut(sw)) {
74 sw->tm = 1;
75 sw->d = 0;
76 } else {
77 // if (!swsnd)
78 // swsnd = Z_sound(sndnoway, 128);
79 sw->d = 2;
81 break;
86 void sw_use(s16 x, s16 y, s16 r, s16 h, u16 f) {
87 s16 i, j, sx, sy, row;
88 sx = (x - r) >> 3;
89 sy = (y - h + 1) >> 3;
90 if (sx < 0) sx = 0;
91 if (sy < 0) sy = 0;
92 x = (x + r) >> 3;
93 y = (y ) >> 3;
94 if (x >= MAPW) x = MAPW - 1;
95 if (y >= MAPH) y = MAPH - 1;
96 row = sy*MAPW;
97 u8 swid;
98 for (j = sy; j <= y; ++j, row += MAPW) {
99 for (i = sx; i <= x; ++i) {
100 swid = g_map->swmap[row + i];
101 if (swid != 0xFF)
102 sw_trigger(g_sw + swid, f);