libsidplayfp  2.4.0
lightpen.h
1 /*
2  * This file is part of libsidplayfp, a SID player engine.
3  *
4  * Copyright 2011-2021 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 LIGHTPEN_H
25 #define LIGHTPEN_H
26 
27 namespace libsidplayfp
28 {
29 
34 class Lightpen
35 {
36 private:
38  unsigned int lastLine;
39 
41  unsigned int cyclesPerLine;
42 
44  unsigned int lpx;
45 
47  unsigned int lpy;
48 
50  bool isTriggered;
51 
52 private:
59  uint8_t getXpos(unsigned int lineCycle) const
60  {
61  if (lineCycle < 13)
62  lineCycle += cyclesPerLine;
63 
64  lineCycle -= 13;
65 
66  // On NTSC the xpos is not incremented at lineCycle 61
67  if ((cyclesPerLine == 65) && (lineCycle > (61 - 13)))
68  {
69  lineCycle--;
70  }
71 
72  return lineCycle << 2;
73  }
74 
75 public:
82  void setScreenSize(unsigned int height, unsigned int width)
83  {
84  lastLine = height - 1;
85  cyclesPerLine = width;
86  }
87 
91  void reset()
92  {
93  lpx = 0;
94  lpy = 0;
95  isTriggered = false;
96  }
97 
101  uint8_t getX() const { return lpx; }
102 
106  uint8_t getY() const { return lpy; }
107 
113  bool retrigger()
114  {
115  if (isTriggered)
116  return false;
117 
118  isTriggered = true;
119 
120  switch (cyclesPerLine)
121  {
122  case 63:
123  default:
124  lpx = 0xd1;
125  break;
126  case 65:
127  lpx = 0xd5;
128  break;
129  }
130 
131  lpy = 0;
132 
133  return true;
134  }
135 
143  bool trigger(unsigned int lineCycle, unsigned int rasterY)
144  {
145  if (isTriggered)
146  return false;
147 
148  isTriggered = true;
149 
150  // don't latch on the last line, except on the first cycle
151  if ((rasterY == lastLine) && (lineCycle > 0))
152  {
153  return false;
154  }
155 
156  // Latch current coordinates
157  lpx = getXpos(lineCycle) + 2; // + 1 for MOS 85XX
158  lpy = rasterY;
159 
160  // On 6569R1 and 6567R56A the interrupt is triggered only
161  // when the line is low on the first cycle of the frame.
162  return true; // false for old chip revisions
163  }
164 
168  void untrigger() { isTriggered = false; }
169 };
170 
171 }
172 
173 #endif
Definition: lightpen.h:35
uint8_t getX() const
Definition: lightpen.h:101
uint8_t getY() const
Definition: lightpen.h:106
void reset()
Definition: lightpen.h:91
bool retrigger()
Definition: lightpen.h:113
bool trigger(unsigned int lineCycle, unsigned int rasterY)
Definition: lightpen.h:143
void setScreenSize(unsigned int height, unsigned int width)
Definition: lightpen.h:82
void untrigger()
Definition: lightpen.h:168