@@ -1016,8 +1016,8 @@ restart:;
10161016 }
10171017 }
10181018
1019- // The noise channel can step even if inactive on the DMG
1020- if (gb -> apu .is_active [ GB_NOISE ] || ! GB_is_cgb ( gb ) ) {
1019+ // TODO: verify these conditions one a DMG somehow
1020+ if (gb -> apu .noise_counter_active || gb -> apu . noise_background_counter_active ) {
10211021 uint16_t cycles_left = cycles ;
10221022 unsigned divisor = (gb -> io_registers [GB_IO_NR43 ] & 0x07 ) << 2 ;
10231023 if (!divisor ) divisor = 2 ;
@@ -1027,25 +1027,33 @@ restart:;
10271027 // This while doesn't get an unlikely because the noise channel steps frequently enough
10281028 while (cycles_left >= gb -> apu .noise_channel .counter_countdown ) {
10291029 cycles_left -= gb -> apu .noise_channel .counter_countdown ;
1030- gb -> apu .noise_channel .counter_countdown = divisor + gb -> apu .noise_channel .delta ;
1031- gb -> apu .noise_channel .delta = 0 ;
1030+ gb -> apu .noise_channel .counter_countdown = divisor ;
10321031 uint16_t mask = 1 << (gb -> io_registers [GB_IO_NR43 ] >> 4 );
10331032 bool old_bit = gb -> apu .noise_channel .counter & mask ;
10341033 gb -> apu .noise_channel .counter ++ ;
10351034 gb -> apu .noise_channel .counter &= 0x3FFF ;
1035+ gb -> apu .noise_channel .did_step_counter = true;
10361036 bool new_bit = gb -> apu .noise_channel .counter & mask ;
10371037
10381038 /* Step LFSR */
1039- if (new_bit && !old_bit ) {
1039+ if (new_bit && !old_bit && gb -> apu . is_active [ GB_NOISE ] ) {
10401040 if (cycles_left == 0 && gb -> apu .samples [GB_NOISE ] == 0 && !gb -> cgb_double_speed ) {
10411041 gb -> apu .pcm_mask [1 ] &= 0x0F ;
10421042 }
10431043 step_lfsr (gb , cycles - cycles_left );
10441044 }
1045+ if (divisor != 2 ) {
1046+ gb -> apu .noise_background_counter_active = false;
1047+ if (unlikely (!gb -> apu .noise_counter_active )) {
1048+ break ;
1049+ }
1050+ }
10451051 }
10461052 if (cycles_left ) {
1047- gb -> apu .noise_channel .counter_countdown -= cycles_left ;
1048- gb -> apu .noise_channel .countdown_reloaded = false;
1053+ if (likely (gb -> apu .noise_counter_active || gb -> apu .noise_background_counter_active )) {
1054+ gb -> apu .noise_channel .counter_countdown -= cycles_left ;
1055+ gb -> apu .noise_channel .countdown_reloaded = false;
1056+ }
10491057 }
10501058 else {
10511059 gb -> apu .noise_channel .countdown_reloaded = true;
@@ -1319,6 +1327,124 @@ static noinline void nr10_write_glitch(GB_gameboy_t *gb, uint8_t value)
13191327
13201328}
13211329
1330+ static void prepare_noise_start (GB_gameboy_t * gb )
1331+ {
1332+ /*
1333+ TODO: When restarting a channel right after starting it, before it has the chance to tick the counter, things
1334+ behave differently. Only certain behaviors of this edge case are emulated.
1335+ */
1336+
1337+ /*
1338+ TODO: Restarting a channel in double speed mode under CGB-C and older is not accurate if the divisor is 0 or 1.
1339+ Specifically in the 0 case, the initial LFSR value seems to be deterministic, but dependant on various
1340+ parameters. It is neither 0 or the equaly unexplained 0x0055.
1341+ */
1342+ gb -> apu .noise_counter_active = gb -> io_registers [GB_IO_NR42 ] & 0xF8 ; // Resets on APU off and DAC disable
1343+ unsigned divisor = (gb -> io_registers [GB_IO_NR43 ] & 0x07 );
1344+ bool was_background_counting = gb -> apu .noise_background_counter_active ;
1345+ gb -> apu .noise_background_counter_active = divisor == 0 ;
1346+ bool instant_step = false;
1347+ bool div_1_glitch = false;
1348+
1349+ if (divisor > 1 && gb -> apu .noise_channel .counter_countdown == 1 ) {
1350+ gb -> apu .noise_channel .counter ++ ;
1351+ gb -> apu .noise_channel .counter &= 0x3FFF ;
1352+ }
1353+ else if (divisor > 1 && gb -> apu .noise_channel .counter_countdown == 2 && gb -> apu .is_active [GB_NOISE ] && gb -> model <= GB_MODEL_CGB_C && gb -> cgb_double_speed ) {
1354+ gb -> apu .noise_channel .counter ++ ;
1355+ gb -> apu .noise_channel .counter &= 0x3FFF ;
1356+ }
1357+ else if (gb -> apu .noise_channel .counter_countdown == 2 &&
1358+ (gb -> apu .noise_channel .alignment & 3 ) == 0 &&
1359+ gb -> apu .is_active [GB_NOISE ]) {
1360+ if (divisor == 0 ) {
1361+ divisor = 8 ;
1362+ }
1363+ else if (divisor == 1 ) {
1364+ /* TODO: I'm not 100% sure this only affects NR43 = 1X */
1365+ if ((gb -> io_registers [GB_IO_NR43 ] & 0xf0 ) == 0x10 && (gb -> apu .noise_channel .counter & 1 )) {
1366+ instant_step = true;
1367+ }
1368+ if (gb -> apu .noise_channel .did_step_counter ) {
1369+ gb -> apu .noise_channel .counter ++ ;
1370+ gb -> apu .noise_channel .counter &= 0x3FFF ;
1371+ }
1372+ /* TODO: needs further research, the conditions are very odd. What if NR43 changes before stepping? */
1373+ if ((gb -> io_registers [GB_IO_NR43 ] & 0xf0 ) == 0x10 && !gb -> apu .noise_channel .did_step_counter ) {
1374+ div_1_glitch = true;
1375+ }
1376+ }
1377+ }
1378+ gb -> apu .noise_channel .counter_countdown = divisor == 0 ? 6 : divisor * 4 + 6 ;
1379+ if (gb -> apu .noise_channel .alignment & 1 ) {
1380+ if (!divisor ) {
1381+ if (gb -> model <= GB_MODEL_CGB_C ) {
1382+ gb -> apu .noise_channel .counter_countdown ++ ;
1383+ }
1384+ else if (was_background_counting ) {
1385+ gb -> apu .noise_channel .counter_countdown -- ;
1386+ }
1387+ else {
1388+ gb -> apu .noise_channel .counter_countdown ++ ;
1389+ }
1390+ }
1391+ else {
1392+ if (gb -> apu .noise_channel .alignment & 2 ) {
1393+ if (divisor == 1 && !gb -> apu .is_active [GB_NOISE ]) {
1394+ gb -> apu .noise_channel .counter_countdown ++ ;
1395+ }
1396+ else {
1397+ gb -> apu .noise_channel .counter_countdown -= 3 ;
1398+ }
1399+ }
1400+ else {
1401+ gb -> apu .noise_channel .counter_countdown -- ;
1402+ if (divisor == 1 && gb -> apu .is_active [GB_NOISE ]) {
1403+ gb -> apu .noise_channel .counter_countdown -= 4 ;
1404+ }
1405+ }
1406+ }
1407+ }
1408+ else {
1409+ if (divisor ) {
1410+ if (gb -> apu .noise_channel .alignment & 2 ) {
1411+ if (gb -> cgb_double_speed && gb -> model <= GB_MODEL_CGB_C && divisor == 1 ) {
1412+ gb -> apu .noise_channel .counter_countdown += 2 ;
1413+ }
1414+ else {
1415+ gb -> apu .noise_channel .counter_countdown -= 2 ;
1416+ }
1417+ }
1418+ else if (divisor > 1 && (!gb -> cgb_double_speed || gb -> model > GB_MODEL_CGB_C )) {
1419+ gb -> apu .noise_channel .counter_countdown -= 4 ;
1420+ }
1421+ }
1422+ else if (gb -> cgb_double_speed && gb -> model <= GB_MODEL_CGB_C ) {
1423+ gb -> apu .noise_channel .counter_countdown += 2 ;
1424+ }
1425+ }
1426+
1427+ /* TODO: This is weird, is the clock going out of sync? */
1428+ if (!divisor && gb -> model <= GB_MODEL_CGB_C && was_background_counting && !gb -> apu .is_active [GB_NOISE ]) {
1429+ gb -> apu .noise_channel .counter_countdown -- ;
1430+ }
1431+ if (div_1_glitch ) {
1432+ gb -> apu .noise_channel .counter_countdown -= 4 ;
1433+ }
1434+
1435+ if (!divisor && gb -> apu .is_active [GB_NOISE ] && (gb -> apu .noise_channel .alignment & 3 ) == 3 ) {
1436+ /* TODO: I have no clue where this number comes from, but this number is confirmed for this edge case even for
1437+ side LFSR, despite being seemingly arbitrary. */
1438+ gb -> apu .noise_channel .lfsr = 0x0055 ;
1439+ }
1440+ else {
1441+ gb -> apu .noise_channel .lfsr = 0 ;
1442+ }
1443+ if (instant_step ) {
1444+ step_lfsr (gb , 0 );
1445+ }
1446+ }
1447+
13221448void GB_apu_write (GB_gameboy_t * gb , uint8_t reg , uint8_t value )
13231449{
13241450 GB_apu_run (gb , true);
@@ -1692,6 +1818,7 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value)
16921818 gb -> io_registers [reg ] = value ;
16931819 gb -> apu .is_active [GB_NOISE ] = false;
16941820 update_sample (gb , GB_NOISE , 0 , 0 );
1821+ gb -> apu .noise_counter_active = false;
16951822 }
16961823 else if (gb -> apu .is_active [GB_NOISE ]) {
16971824 nrx2_glitch (gb , & gb -> apu .noise_channel .current_volume ,
@@ -1722,7 +1849,6 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value)
17221849 gb -> apu .noise_channel .counter_countdown =
17231850 divisor + (divisor == 2 ? 0 : inline_const (uint8_t [ ], {2 , 1 , 4 , 3 })[(gb -> apu .noise_channel .alignment ) & 3 ]);
17241851 }
1725- gb -> apu .noise_channel .delta = 0 ;
17261852 }
17271853 /* Step LFSR */
17281854 if (new_bit && (!old_bit || gb -> model <= GB_MODEL_CGB_C )) {
@@ -1747,59 +1873,12 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value)
17471873 gb -> apu .noise_channel .dmg_delayed_start = 6 ;
17481874 }
17491875 else {
1750- unsigned divisor = (gb -> io_registers [GB_IO_NR43 ] & 0x07 ) << 2 ;
1751- if (!divisor ) divisor = 2 ;
1752- gb -> apu .noise_channel .delta = 0 ;
1753- gb -> apu .noise_channel .counter_countdown = divisor + 4 ;
1754- if (divisor == 2 ) {
1755- if (gb -> model <= GB_MODEL_CGB_C ) {
1756- gb -> apu .noise_channel .counter_countdown += gb -> apu .lf_div ;
1757- if (!gb -> cgb_double_speed ) {
1758- gb -> apu .noise_channel .counter_countdown -= 1 ;
1759- }
1760- }
1761- else {
1762- gb -> apu .noise_channel .counter_countdown += 1 - gb -> apu .lf_div ;
1763- }
1764- }
1765- else {
1766- if (gb -> model <= GB_MODEL_CGB_C ) {
1767- gb -> apu .noise_channel .counter_countdown += inline_const (uint8_t [ ], {2 , 1 , 4 , 3 })[gb -> apu .noise_channel .alignment & 3 ];
1768- }
1769- else {
1770- gb -> apu .noise_channel .counter_countdown += inline_const (uint8_t [ ], {2 , 1 , 0 , 3 })[gb -> apu .noise_channel .alignment & 3 ];
1771- }
1772- if (((gb -> apu .noise_channel .alignment + 1 ) & 3 ) < 2 ) {
1773- if ((gb -> io_registers [GB_IO_NR43 ] & 0x07 ) == 1 ) {
1774- gb -> apu .noise_channel .counter_countdown -= 2 ;
1775- gb -> apu .noise_channel .delta = 2 ;
1776- }
1777- else {
1778- gb -> apu .noise_channel .counter_countdown -= 4 ;
1779- }
1780- }
1781- }
1876+ prepare_noise_start (gb );
17821877
1783- /* TODO: These are quite weird. Verify further */
1784- if (gb -> model <= GB_MODEL_CGB_C ) {
1785- if (gb -> cgb_double_speed ) {
1786- if (!(gb -> io_registers [GB_IO_NR43 ] & 0xF0 ) && (gb -> io_registers [GB_IO_NR43 ] & 0x07 )) {
1787- gb -> apu .noise_channel .counter_countdown -= 1 ;
1788- }
1789- else if ((gb -> io_registers [GB_IO_NR43 ] & 0xF0 ) && !(gb -> io_registers [GB_IO_NR43 ] & 0x07 )) {
1790- gb -> apu .noise_channel .counter_countdown += 1 ;
1791- }
1792- }
1793- else {
1794- gb -> apu .noise_channel .counter_countdown -= 2 ;
1795- }
1796- }
1797-
17981878 gb -> apu .noise_channel .current_volume = gb -> io_registers [GB_IO_NR42 ] >> 4 ;
1799-
1800- gb -> apu .noise_channel .lfsr = 0 ;
18011879 gb -> apu .noise_channel .current_lfsr_sample = false;
18021880 gb -> apu .noise_channel .volume_countdown = gb -> io_registers [GB_IO_NR42 ] & 7 ;
1881+ gb -> apu .noise_channel .did_step_counter = false;
18031882
18041883 if (gb -> io_registers [GB_IO_NR42 ] & 0xF8 ) {
18051884 gb -> apu .is_active [GB_NOISE ] = true;
0 commit comments