File: memory.cpp

package info (click to toggle)
libretro-bsnes-mercury 094%2Bgit20160126-3
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 9,632 kB
  • sloc: cpp: 109,056; ansic: 3,097; makefile: 638; xml: 11; sh: 1
file content (113 lines) | stat: -rw-r--r-- 2,957 bytes parent folder | download | duplicates (4)
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#ifdef SUPERFX_CPP

uint8 SuperFX::bus_read(unsigned addr) {
  if((addr & 0xc00000) == 0x000000) {  //$00-3f:0000-7fff, $00-3f:8000-ffff
    while(!regs.scmr.ron && scheduler.sync != Scheduler::SynchronizeMode::All) {
      step(6);
      synchronize_cpu();
    }
    return rom.read((((addr & 0x3f0000) >> 1) | (addr & 0x7fff)) & rom_mask);
  }

  if((addr & 0xe00000) == 0x400000) {  //$40-5f:0000-ffff
    while(!regs.scmr.ron && scheduler.sync != Scheduler::SynchronizeMode::All) {
      step(6);
      synchronize_cpu();
    }
    return rom.read(addr & rom_mask);
  }

  if((addr & 0xe00000) == 0x600000) {  //$60-7f:0000-ffff
    while(!regs.scmr.ran && scheduler.sync != Scheduler::SynchronizeMode::All) {
      step(6);
      synchronize_cpu();
    }
    return ram.read(addr & ram_mask);
  }

  // TODO: invalid address, what does real hardware do?
  return 0;
}

void SuperFX::bus_write(unsigned addr, uint8 data) {
  if((addr & 0xe00000) == 0x600000) {  //$60-7f:0000-ffff
    while(!regs.scmr.ran && scheduler.sync != Scheduler::SynchronizeMode::All) {
      step(6);
      synchronize_cpu();
    }
    return ram.write(addr & ram_mask, data);
  }
}

uint8 SuperFX::op_read(uint16 addr) {
  uint16 offset = addr - regs.cbr;
  if(offset < 512) {
    if(cache.valid[offset >> 4] == false) {
      unsigned dp = offset & 0xfff0;
      unsigned sp = (regs.pbr << 16) + ((regs.cbr + dp) & 0xfff0);
      for(unsigned n = 0; n < 16; n++) {
        step(memory_access_speed);
        cache.buffer[dp++] = bus_read(sp++);
      }
      cache.valid[offset >> 4] = true;
    } else {
      step(cache_access_speed);
    }
    return cache.buffer[offset];
  }

  if(regs.pbr <= 0x5f) {
    //$[00-5f]:[0000-ffff] ROM
    rombuffer_sync();
    step(memory_access_speed);
    return bus_read((regs.pbr << 16) + addr);
  } else {
    //$[60-7f]:[0000-ffff] RAM
    rambuffer_sync();
    step(memory_access_speed);
    return bus_read((regs.pbr << 16) + addr);
  }
}

uint8 SuperFX::peekpipe() {
  uint8 result = regs.pipeline;
  regs.pipeline = op_read(regs.r[15]);
  r15_modified = false;
  return result;
}

uint8 SuperFX::pipe() {
  uint8 result = regs.pipeline;
  regs.pipeline = op_read(++regs.r[15]);
  r15_modified = false;
  return result;
}

void SuperFX::cache_flush() {
  for(unsigned n = 0; n < 32; n++) cache.valid[n] = false;
}

uint8 SuperFX::cache_mmio_read(uint16 addr) {
  addr = (addr + regs.cbr) & 511;
  return cache.buffer[addr];
}

void SuperFX::cache_mmio_write(uint16 addr, uint8 data) {
  addr = (addr + regs.cbr) & 511;
  cache.buffer[addr] = data;
  if((addr & 15) == 15) cache.valid[addr >> 4] = true;
}

void SuperFX::memory_reset() {
  rom_mask = rom.size() - 1;
  ram_mask = ram.size() - 1;

  for(unsigned n = 0; n < 512; n++) cache.buffer[n] = 0x00;
  for(unsigned n = 0; n < 32; n++) cache.valid[n] = false;
  for(unsigned n = 0; n < 2; n++) {
    pixelcache[n].offset = ~0;
    pixelcache[n].bitpend = 0x00;
  }
}

#endif