File: rumble.c

package info (click to toggle)
sameboy 1.0.2%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 10,528 kB
  • sloc: ansic: 29,948; objc: 22,249; asm: 1,424; pascal: 1,373; makefile: 1,065; xml: 111
file content (57 lines) | stat: -rw-r--r-- 2,616 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include "rumble.h"
#include "gb.h"

void GB_set_rumble_mode(GB_gameboy_t *gb, GB_rumble_mode_t mode)
{
    gb->rumble_mode = mode;
    if (gb->rumble_callback) {
        gb->rumble_callback(gb, 0);
    }
}

void GB_handle_rumble(GB_gameboy_t *gb)
{
    if (gb->rumble_callback) {
        if (gb->rumble_mode == GB_RUMBLE_DISABLED) {
            return;
        }
        if (gb->cartridge_type->has_rumble &&
            (gb->cartridge_type->mbc_type != GB_TPP1 || (gb->rom[0x153] & 1))) {
            if (gb->rumble_on_cycles + gb->rumble_off_cycles) {
                gb->rumble_callback(gb, gb->rumble_on_cycles / (double)(gb->rumble_on_cycles + gb->rumble_off_cycles));
                gb->rumble_on_cycles = gb->rumble_off_cycles = 0;
            }
        }
        else if (gb->rumble_mode == GB_RUMBLE_ALL_GAMES) {
            unsigned volume = (gb->io_registers[GB_IO_NR50] & 7) + 1 + ((gb->io_registers[GB_IO_NR50] >> 4) & 7) + 1;
            unsigned ch4_volume = volume * (!!(gb->io_registers[GB_IO_NR51] & 8) + !!(gb->io_registers[GB_IO_NR51] & 0x80));
            unsigned ch1_volume = volume * (!!(gb->io_registers[GB_IO_NR51] & 1) + !!(gb->io_registers[GB_IO_NR51] & 0x10));
            unsigned ch4_divisor = (gb->io_registers[GB_IO_NR43] & 0x07) << 1;
            if (!ch4_divisor) ch4_divisor = 1;
            unsigned ch4_sample_length = (ch4_divisor << (gb->io_registers[GB_IO_NR43] >> 4)) - 1;
        
            double ch4_rumble = (MIN(ch4_sample_length * (gb->apu.noise_channel.narrow? 8 : 1) , 4096) * ((signed) gb->apu.noise_channel.current_volume * gb->apu.noise_channel.current_volume * ch4_volume / 32.0 - 50) - 2048) / 2048.0;
            
            ch4_rumble = MIN(ch4_rumble, 1.0);
            ch4_rumble = MAX(ch4_rumble, 0.0);
            
            double ch1_rumble = 0;
            if ((gb->io_registers[GB_IO_NR10] & 0x7) && (gb->io_registers[GB_IO_NR10] & 0x70)) {
                double sweep_speed = (gb->io_registers[GB_IO_NR10] & 7) / (double)((gb->io_registers[GB_IO_NR10] >> 4) & 7);
                ch1_rumble = gb->apu.square_channels[GB_SQUARE_1].current_volume * ch1_volume / 32.0 * sweep_speed / 8.0 - 0.5;
                ch1_rumble = MIN(ch1_rumble, 1.0);
                ch1_rumble = MAX(ch1_rumble, 0.0);
            }
            
            if (!gb->apu.is_active[GB_NOISE]) {
                ch4_rumble = 0;
            }
            
            if (!gb->apu.is_active[GB_SQUARE_1]) {
                ch1_rumble = 0;
            }
            
            gb->rumble_callback(gb, MIN(MAX(ch1_rumble / 2 + ch4_rumble, 0.0), 1.0));
        }
    }
}