File: mmio.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 (96 lines) | stat: -rw-r--r-- 2,327 bytes parent folder | download | duplicates (5)
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
#ifdef ICD2_CPP

//convert linear pixel data to 2bpp planar tiledata
void ICD2::render(const uint32* source) {
  memset(lcd.output, 0x00, 320 * sizeof(uint16));

  for(unsigned y = 0; y < 8; y++) {
    for(unsigned x = 0; x < 160; x++) {
      unsigned pixel = *source++;
      unsigned addr = y * 2 + (x / 8 * 16);
      lcd.output[addr + 0] |= ((pixel & 1) >> 0) << (7 - (x & 7));
      lcd.output[addr + 1] |= ((pixel & 2) >> 1) << (7 - (x & 7));
    }
  }
}

uint8 ICD2::read(unsigned addr) {
  addr &= 0xffff;

  //LY counter
  if(addr == 0x6000) {
    r6000_ly = GameBoy::ppu.status.ly;
    r6000_row = lcd.row;
    return r6000_ly;
  }

  //command ready port
  if(addr == 0x6002) {
    bool data = packetsize > 0;
    if(data) {
      for(unsigned i = 0; i < 16; i++) r7000[i] = packet[0][i];
      packetsize--;
      for(unsigned i = 0; i < packetsize; i++) packet[i] = packet[i + 1];
    }
    return data;
  }

  //ICD2 revision
  if(addr == 0x600f) {
    return 0x21;
  }

  //command port
  if((addr & 0xfff0) == 0x7000) {
    return r7000[addr & 15];
  }

  //VRAM port
  if(addr == 0x7800) {
    uint8 data = lcd.output[r7800];
    r7800 = (r7800 + 1) % 320;
    return data;
  }

  return 0x00;
}

void ICD2::write(unsigned addr, uint8 data) {
  addr &= 0xffff;

  //VRAM port
  if(addr == 0x6001) {
    r6001 = data;
    r7800 = 0;

    unsigned offset = (r6000_row - (4 - (r6001 - (r6000_ly & 3)))) & 3;
    render(lcd.buffer + offset * 160 * 8);

    return;
  }

  //control port
  //d7: 0 = halt, 1 = reset
  //d5,d4: 0 = 1-player, 1 = 2-player, 2 = 4-player, 3 = ???
  //d1,d0: 0 = frequency divider (clock rate adjust)
  if(addr == 0x6003) {
    if((r6003 & 0x80) == 0x00 && (data & 0x80) == 0x80) {
      reset();
    }
    switch(data & 3) {
    case 0: frequency = cpu.frequency / 4; break;  //fast (glitchy, even on real hardware)
    case 1: frequency = cpu.frequency / 5; break;  //normal
    case 2: frequency = cpu.frequency / 7; break;  //slow
    case 3: frequency = cpu.frequency / 9; break;  //very slow
    }
    r6003 = data;
    return;
  }

  if(addr == 0x6004) { r6004 = data; return; }  //joypad 1
  if(addr == 0x6005) { r6005 = data; return; }  //joypad 2
  if(addr == 0x6006) { r6006 = data; return; }  //joypad 3
  if(addr == 0x6007) { r6007 = data; return; }  //joypad 4
}

#endif