libsidplayfp  2.12.0
sprites.h
1 /*
2  * This file is part of libsidplayfp, a SID player engine.
3  *
4  * Copyright 2011-2014 Leandro Nini <drfiemost@users.sourceforge.net>
5  * Copyright 2009-2014 VICE Project
6  * Copyright 2007-2010 Antti Lankila
7  * Copyright 2001 Simon White
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22  */
23 
24 #ifndef SPRITES_H
25 #define SPRITES_H
26 
27 #include <stdint.h>
28 
29 #include <algorithm>
30 #include <iterator>
31 
32 namespace libsidplayfp
33 {
34 
38 class Sprites
39 {
40 private:
41  static constexpr int SPRITES = 8;
42 
43  const uint8_t &enable, &y_expansion;
44 
45  uint8_t exp_flop;
46  uint8_t dma;
47  uint8_t mc_base[SPRITES];
48  uint8_t mc[SPRITES];
49 
50 public:
51  Sprites(uint8_t regs[0x40]) :
52  enable(regs[0x15]),
53  y_expansion(regs[0x17]) {}
54 
55  void reset()
56  {
57  exp_flop = 0xff;
58  dma = 0;
59 
60  std::fill(std::begin(mc_base), std::end(mc_base), 0);
61  std::fill(std::begin(mc), std::end(mc), 0);
62  }
63 
68  void updateMc()
69  {
70  uint8_t mask = 1;
71  for (unsigned int i = 0; i < SPRITES; i++, mask <<= 1)
72  {
73  if (dma & mask)
74  mc[i] = (mc[i] + 3) & 0x3f;
75  }
76  }
77 
81  void updateMcBase()
82  {
83  uint8_t mask = 1;
84  for (unsigned int i = 0; i < SPRITES; i++, mask <<= 1)
85  {
86  if (exp_flop & mask)
87  {
88  mc_base[i] = mc[i];
89  if (mc_base[i] == 0x3f)
90  dma &= ~mask;
91  }
92  }
93  }
94 
98  void checkExp()
99  {
100  exp_flop ^= dma & y_expansion;
101  }
102 
107  {
108  for (unsigned int i = 0; i < SPRITES; i++)
109  {
110  mc[i] = mc_base[i];
111  }
112  }
113 
120  void checkDma(unsigned int rasterY, uint8_t regs[0x40])
121  {
122  const uint8_t y = rasterY & 0xff;
123  uint8_t mask = 1;
124  for (unsigned int i = 0; i < SPRITES; i++, mask <<= 1)
125  {
126  if ((enable & mask) && (y == regs[(i << 1) + 1]) && !(dma & mask))
127  {
128  dma |= mask;
129  mc_base[i] = 0;
130  exp_flop |= mask;
131  }
132  }
133  }
134 
141  void lineCrunch(uint8_t data, unsigned int lineCycle)
142  {
143  uint8_t mask = 1;
144  for (unsigned int i = 0; i < SPRITES; i++, mask <<= 1)
145  {
146  if (!(data & mask) && !(exp_flop & mask))
147  {
148  // sprite crunch
149  if (lineCycle == 14)
150  {
151  const uint8_t mc_i = mc[i];
152  const uint8_t mcBase_i = mc_base[i];
153 
154  mc[i] = (0x2a & (mcBase_i & mc_i)) | (0x15 & (mcBase_i | mc_i));
155 
156  // mcbase will be set from mc on the following clock call
157  }
158 
159  exp_flop |= mask;
160  }
161  }
162  }
163 
169  inline bool isDma(unsigned int val) const
170  {
171  return dma & val;
172  }
173 };
174 
175 }
176 
177 #endif
Definition: sprites.h:39
void checkExp()
Definition: sprites.h:98
void checkDisplay()
Definition: sprites.h:106
void updateMcBase()
Definition: sprites.h:81
void checkDma(unsigned int rasterY, uint8_t regs[0x40])
Definition: sprites.h:120
void updateMc()
Definition: sprites.h:68
bool isDma(unsigned int val) const
Definition: sprites.h:169
void lineCrunch(uint8_t data, unsigned int lineCycle)
Definition: sprites.h:141