22#include <gba_input.h>
33#include <gba_sound.h>
44#include <gba_video.h>
5+ #include "posprintf.h"
56
67extern const unsigned char helpsect_manual_lag_test [];
78#define PFMAP 23
8- #define NUM_PRESSES 10
9+ #define NUM_TRIALS 10
910#define BLANK_TILE 0x0004
11+ #define ARROW_TILE 0x0005
12+ #define CHECKED_TILE 0x0027
13+ #define UNCHECKED_TILE 0x0026
14+ #define RETICLE_TILE 0x0028
15+ #define WORD_OFF 0x0044
16+ #define WORD_ON 0x0046
1017
1118// The "On" and "Off" labels must come first because they cause
12- // text to be allocated with off at 0x0030 and on at 0x0032
19+ // text to be allocated with off and on at WORD_OFF and WORD_ON
1320static const char megaton_labels [] =
1421 "\x83" "\x88" "off\n"
1522 "\x84" "\x90" "on\n"
@@ -20,11 +27,39 @@ static const char megaton_labels[] =
2027 "\x44" "\x88" "Randomize\n"
2128 "\x44" "\x90" "Audio" ;
2229
30+ static void megaton_draw_boolean (unsigned int y , unsigned int value ) {
31+ MAP [PFMAP ][y ][15 ] = value ? CHECKED_TILE : UNCHECKED_TILE ;
32+ unsigned int onoff = value ? WORD_ON : WORD_OFF ;
33+ MAP [PFMAP ][y ][16 ] = onoff ;
34+ MAP [PFMAP ][y ][17 ] = onoff + 1 ;
35+ }
36+
37+ static void megaton_draw_reticle (unsigned int x , unsigned int y ) {
38+ unsigned int i = oam_used ;
39+ y = OBJ_Y (y ) | OBJ_16_COLOR | ATTR0_SQUARE ;
40+ x = OBJ_X (x ) | ATTR1_SIZE_16 ;
41+
42+ SOAM [i ].attr0 = y ;
43+ SOAM [i ].attr1 = x ;
44+ SOAM [i ++ ].attr2 = RETICLE_TILE ;
45+ SOAM [i ].attr0 = y ;
46+ SOAM [i ].attr1 = x + 16 + OBJ_HFLIP ;
47+ SOAM [i ++ ].attr2 = RETICLE_TILE ;
48+ y += 16 ;
49+ SOAM [i ].attr0 = y ;
50+ SOAM [i ].attr1 = x + OBJ_VFLIP ;
51+ SOAM [i ++ ].attr2 = RETICLE_TILE ;
52+ SOAM [i ].attr0 = y ;
53+ SOAM [i ].attr1 = x + 16 + OBJ_HFLIP + OBJ_VFLIP ;
54+ SOAM [i ++ ].attr2 = RETICLE_TILE ;
55+ oam_used = i ;
56+ }
57+
2358void activity_megaton () {
24- signed char lag [NUM_PRESSES ] = {-1 };
59+ signed char lag [NUM_TRIALS ] = {-1 };
2560 unsigned int x = 129 , xtarget = 160 ;
2661 unsigned int with_audio = 1 , dir = 1 , randomize = 1 ;
27- unsigned int progress = 0 ;
62+ unsigned int progress = 0 , y = 0 ;
2863
2964 load_common_bg_tiles ();
3065 load_common_obj_tiles ();
@@ -34,17 +69,84 @@ void activity_megaton() {
3469 REG_SOUNDCNT_L = 0xFF77 ; // PSG vol/pan
3570 REG_SOUND1CNT_L = 0x08 ; // no sweep
3671 dma_memset16 (MAP [PFMAP ], BLANK_TILE , 32 * 20 * 2 );
37- vwfDrawLabels (megaton_labels , PFMAP , 0x30 );
72+ vwfDrawLabels (megaton_labels , PFMAP , 0x44 );
73+
74+ // Draw stationary reticle
75+ for (unsigned int y = 0 ; y < 2 ; ++ y ) {
76+ for (unsigned int x = 0 ; x < 2 ; ++ x ) {
77+ unsigned int t = 0x0028 + y * 2 + x ;
78+ MAP [PFMAP ][7 + y ][13 + x ] = t ;
79+ MAP [PFMAP ][7 + y ][16 - x ] = t ^ 0x400 ;
80+ MAP [PFMAP ][10 - y ][13 + x ] = t ^ 0x800 ;
81+ MAP [PFMAP ][10 - y ][16 - x ] = t ^ 0xC00 ;
82+ }
83+ }
84+
85+ // Make space for results
86+ dma_memset16 (PATRAM4 (0 , 0x30 ), 0x0000 , 32 * 20 );
87+ loadMapRowMajor (& (MAP [PFMAP ][2 ][2 ]), 0x30 , 2 , 10 );
3888
3989 do {
4090 read_pad_help_check (helpsect_manual_lag_test );
4191
42- if (new_keys && KEY_B ) {
92+ if (new_keys & KEY_B ) {
4393 break ;
4494 }
95+ if (new_keys & KEY_A ) {
96+ signed int diff = x - 128 ;
97+ if (xtarget < 128 ) diff = - diff ;
98+ unsigned int early = diff < 0 ;
99+ unsigned int value = early ? - diff : diff ;
100+ uint32_t * tileaddr = PATRAM4 (0 , 0x30 + progress * 2 );
101+ dma_memset16 (tileaddr , 0x0000 , 32 * 2 );
102+ if (early ) {
103+ vwf8PutTile (tileaddr , 'E' , 0 , 1 );
104+ }
105+ unsigned int tens = value / 10 ;
106+ if (tens ) {
107+ vwf8PutTile (tileaddr , tens + '0' , 6 , 1 );
108+ }
109+ vwf8PutTile (tileaddr , (value - tens * 10 ) + '0' , 11 , 1 );
110+ if (!early && value <= 25 ) lag [progress ++ ] = value ;
111+ }
112+ REG_SOUND2CNT_L = ((new_keys & KEY_A ) && with_audio ) ? 0xA080 : 0x0000 ;
113+ REG_SOUND2CNT_H = (2048 - 262 ) | 0x8000 ;
114+ if ((new_keys & KEY_UP ) && y > 0 ) {
115+ -- y ;
116+ }
117+ if ((new_keys & KEY_DOWN ) && y < 2 ) {
118+ ++ y ;
119+ }
120+ if (new_keys & (KEY_LEFT | KEY_RIGHT )) {
121+ switch (y ) {
122+ case 0 : // change direction
123+ dir += (new_keys & KEY_LEFT ) ? 2 : 1 ;
124+ if (dir > 3 ) dir -= 3 ;
125+ break ;
126+ case 1 :
127+ randomize = !randomize ;
128+ break ;
129+ case 2 :
130+ with_audio = !with_audio ;
131+ break ;
132+ }
133+ }
45134
135+ // Move reticle
136+ x += (xtarget > x ) ? 1 : -1 ;
137+ if (x == xtarget ) {
138+ xtarget = 36 + 128 ;
139+ if (randomize ) xtarget += (lcg_rand () >> 12 ) - 8 ;
140+ if (x > 128 ) xtarget = 256 - xtarget ;
141+ }
142+
46143 oam_used = 0 ;
47- // Draw sprites
144+ if (dir & 0x01 ) {
145+ megaton_draw_reticle (104 + x - 128 , 56 );
146+ }
147+ if (dir & 0x02 ) {
148+ megaton_draw_reticle (104 , 56 + x - 128 );
149+ }
48150 ppu_clear_oam (oam_used );
49151
50152 VBlankIntrWait ();
@@ -53,12 +155,49 @@ void activity_megaton() {
53155 BG_OFFSET [0 ].x = BG_OFFSET [0 ].y = 0 ;
54156 BG_COLORS [0 ] = (x == 128 && with_audio ) ? RGB5 (31 , 31 , 31 ) : RGB5 (0 , 0 , 0 );
55157 BG_COLORS [1 ] = OBJ_COLORS [1 ] = RGB5 (31 , 31 , 31 );
158+ BG_COLORS [2 ] = RGB5 (20 , 25 , 31 );
56159 ppu_copy_oam ();
57160
58- } while (!(new_keys & KEY_B ));
161+ // Draw the cursor
162+ for (unsigned int i = 0 ; i < 3 ; ++ i ) {
163+ unsigned int tilenum = (i == y ) ? ARROW_TILE : BLANK_TILE ;
164+ MAP [PFMAP ][i + 16 ][7 ] = tilenum ;
165+ }
166+ MAP [PFMAP ][16 ][15 ] = (dir & 0x01 ) ? CHECKED_TILE : UNCHECKED_TILE ;
167+ MAP [PFMAP ][16 ][19 ] = (dir & 0x02 ) ? CHECKED_TILE : UNCHECKED_TILE ;
168+ megaton_draw_boolean (17 , randomize );
169+ megaton_draw_boolean (18 , with_audio );
170+
171+ // TODO: beep
172+ REG_SOUND1CNT_H = (x == 128 && with_audio ) ? 0xA080 : 0x0000 ;
173+ REG_SOUND1CNT_X = (2048 - 131 ) | 0x8000 ;
174+ } while (!(new_keys & KEY_B ) && (progress < NUM_TRIALS ));
175+
59176 BG_COLORS [0 ] = RGB5 (0 , 0 , 0 );
60177 REG_SOUNDCNT_X = 0 ; // reset audio
178+ if (progress < 10 ) return ;
179+
180+ // Display average: First throw away all labels below Y=120
181+ dma_memset16 (MAP [PFMAP ][15 ], BLANK_TILE , 32 * 4 * 2 );
182+
183+ unsigned int sum = 0 ;
184+ for (unsigned int i = 0 ; i < NUM_TRIALS ; ++ i ) {
185+ sum += lag [i ];
186+ }
187+ unsigned int whole_frames = sum / NUM_TRIALS ;
188+ posprintf (help_line_buffer , "\x40\x80" "Average lag: %d.%d frames" ,
189+ whole_frames , sum - whole_frames * NUM_TRIALS );
190+ vwfDrawLabels (help_line_buffer , PFMAP , 0x44 );
191+
192+ // Ignore spurious presses
193+ for (unsigned int i = 20 ; i > 0 ; -- i ) {
194+ VBlankIntrWait ();
195+ }
61196
62- if (new_keys && KEY_B ) return ;
197+ do {
198+ VBlankIntrWait ();
199+ read_pad ();
200+ } while (!new_keys );
63201
202+ // TODO: Display average lag
64203}
0 commit comments