xfree (tmp2);
xfree (tmp1);
}
+static void cfgfile_dwrite_coords(struct zfile *f, const TCHAR *option, int x, int y)
+{
+ cfgfile_dwrite(f, option, _T("%d,%d"), x, y);
+}
static void cfg_dowrite (struct zfile *f, const TCHAR *option, const TCHAR *value, int d, int target)
{
cfg_dowrite (f, option, NULL, value, d, target);
cfgfile_dwrite(f, _T("genlock_mix"), _T("%d"), p->genlock_mix);
cfgfile_dwrite(f, _T("genlock_scale"), _T("%d"), p->genlock_scale);
cfgfile_dwrite_str(f, _T("monitoremu"), specialmonitors[p->monitoremu]);
+ cfgfile_dwrite_coords(f, _T("lightpen_offset"), p->lightpen_offset[0], p->lightpen_offset[1]);
cfgfile_dwrite_bool(f, _T("lightpen_crosshair"), p->lightpen_crosshair);
cfgfile_dwrite_bool (f, _T("show_leds"), !!(p->leds_on_screen & STATUSLINE_CHIPSET));
write_inputdevice_config (p, f);
}
+static int cfgfile_coords(const TCHAR *option, const TCHAR *value, const TCHAR *name, int *x, int *y)
+{
+ if (name != NULL && _tcscmp (option, name) != 0)
+ return 0;
+ TCHAR tmp[MAX_DPATH];
+ _tcscpy(tmp, value);
+ TCHAR *p = _tcschr(tmp, ',');
+ if (!p)
+ return 0;
+ *p++ = 0;
+ *x = _tstol(tmp);
+ *y = _tstol(p);
+ return 1;
+}
+
static int cfgfile_yesno (const TCHAR *option, const TCHAR *value, const TCHAR *name, int *location, bool numbercheck)
{
if (name != NULL && _tcscmp (option, name) != 0)
|| cfgfile_yesno(option, value, _T("gfxcard_hardware_sprite"), &p->rtg_hardwaresprite)
|| cfgfile_yesno(option, value, _T("synchronize_clock"), &p->tod_hack)
|| cfgfile_yesno(option, value, _T("keyboard_connected"), &p->keyboard_connected)
+ || cfgfile_coords(option, value, _T("lightpen_offset"), &p->lightpen_offset[0], &p->lightpen_offset[1])
|| cfgfile_yesno(option, value, _T("lightpen_crosshair"), &p->lightpen_crosshair)
|| cfgfile_yesno (option, value, _T("kickshifter"), &p->kickshifter)
static int vpos_previous, hpos_previous;
static int vpos_lpen, hpos_lpen, lightpen_triggered;
int lightpen_x[2], lightpen_y[2];
-int lightpen_cx, lightpen_cy, lightpen_active, lightpen_enabled;
+int lightpen_cx[2], lightpen_cy[2], lightpen_active, lightpen_enabled, lightpen_enabled2;
static uae_u32 sprtaba[256],sprtabb[256];
static uae_u32 sprite_ab_merge[256];
{
if (beamcon0 & 0x2000) // LPENDIS
return 0;
- return lightpen_triggered > 0;
+ return lightpen_triggered != 0;
}
STATIC_INLINE int issyncstopped (void)
{
hpos_previous = hpos;
}
- if (bplcon0 & 4)
+ if (v & 4) {
bplcon0_interlace_seen = true;
+ }
+
+ if ((v & 8) && !lightpen_triggered && vpos < sprite_vblank_endline) {
+ // setting lightpen bit immediately freezes VPOSR if inside vblank and not already frozen
+ lightpen_triggered = 1;
+ vpos_lpen = vpos;
+ hpos_lpen = hpos;
+ }
+ if (!(v & 8)) {
+ // clearing lightpen bit immediately returns VPOSR back to normal
+ lightpen_triggered = 0;
+ }
bplcon0 = v;
events_dmal (7);
}
+static void lightpen_trigger_func(uae_u32 v)
+{
+ vpos_lpen = vpos;
+ hpos_lpen = v;
+ lightpen_triggered = 1;
+}
+
static bool is_custom_vsync (void)
{
int vp = vpos + 1;
do_playfield_collisions ();
}
hsync_record_line_state (next_lineno, nextline_how, thisline_changed);
+
/* reset light pen latch */
if (vpos == sprite_vblank_endline) {
lightpen_triggered = 0;
sprite_0 = 0;
}
- if (lightpen_enabled && lightpen_cx > 0 && (bplcon0 & 8) && !lightpen_triggered && lightpen_cy == vpos) {
- vpos_lpen = vpos;
- hpos_lpen = lightpen_cx;
- lightpen_triggered = 1;
+
+ if (!lightpen_triggered && vpos >= sprite_vblank_endline && (bplcon0 & 8)) {
+ // lightpen always triggers at the beginning of the last line
+ if (vpos + 1 == maxvpos + lof_store) {
+ vpos_lpen = vpos;
+ hpos_lpen = 1;
+ lightpen_triggered = 1;
+ } else if (lightpen_enabled) {
+ int lpnum = inputdevice_get_lightpen_id();
+ if (lpnum < 0)
+ lpnum = 0;
+ if (lightpen_cx[lpnum] > 0 && lightpen_cy[lpnum] == vpos) {
+ event2_newevent_xx (-1, lightpen_cx[lpnum] * CYCLE_UNIT, lightpen_cx[lpnum], lightpen_trigger_func);
+ }
+ }
}
hardware_line_completed (next_lineno);
if (doflickerfix () && interlace_seen > 0)
if (onvsync) {
// vpos_count >= MAXVPOS just to not crash if VPOSW writes prevent vsync completely
- if ((bplcon0 & 8) && !lightpen_triggered) {
- vpos_lpen = vpos - 1;
- hpos_lpen = maxhpos;
- lightpen_triggered = 1;
- }
vpos = 0;
vsync_handler_post ();
vpos_count = 0;
lightpen_active = -1;
lightpen_triggered = 0;
- lightpen_cx = lightpen_cy = -1;
+ lightpen_cx[0] = lightpen_cy[0] = -1;
+ lightpen_cx[1] = lightpen_cy[1] = -1;
lightpen_x[0] = -1;
lightpen_y[0] = -1;
lightpen_x[1] = -1;
drawing_color_matches = -1;
}
-static int lightpen_y1, lightpen_y2;
+static int lightpen_y1[2], lightpen_y2[2];
static int statusbar_y1, statusbar_y2;
void putpixel(uae_u8 *buf, uae_u8 *genlockbuf, int bpp, int x, xcolnr c8, int opaq)
"------.....------"
};
-static void draw_lightpen_cursor (int x, int y, int line, int onscreen)
+static void draw_lightpen_cursor (int x, int y, int line, int onscreen, int lpnum)
{
- int i;
const char *p;
- int color1 = onscreen ? 0xff0 : 0xf00;
+ int color1 = onscreen ? (lpnum ? 0x0ff : 0xff0) : (lpnum ? 0x0f0 : 0xf00);
int color2 = 0x000;
- if (!currprefs.lightpen_crosshair)
- return;
-
xlinebuffer = gfxvidinfo.drawbuffer.linemem;
if (xlinebuffer == 0)
xlinebuffer = row_map[line];
xlinebuffer_genlock = row_map_genlock[line];
p = lightpen_cursor + y * LIGHTPEN_WIDTH;
- for (i = 0; i < LIGHTPEN_WIDTH; i++) {
+ for (int i = 0; i < LIGHTPEN_WIDTH; i++) {
int xx = x + i - LIGHTPEN_WIDTH / 2;
if (*p != '-' && xx >= 0 && xx < gfxvidinfo.drawbuffer.outwidth) {
putpixel (xlinebuffer, xlinebuffer_genlock, gfxvidinfo.drawbuffer.pixbytes, xx, *p == 'x' ? xcolors[color1] : xcolors[color2], 1);
static void lightpen_update (struct vidbuffer *vb, int lpnum)
{
+ if (lightpen_x[lpnum] < 0 || lightpen_y[lpnum] < 0)
+ return;
+
if (lightpen_x[lpnum] < LIGHTPEN_WIDTH + 1)
lightpen_x[lpnum] = LIGHTPEN_WIDTH + 1;
if (lightpen_x[lpnum] >= gfxvidinfo.drawbuffer.inwidth - LIGHTPEN_WIDTH - 1)
if (lightpen_y[lpnum] >= max_ypos_thisframe - LIGHTPEN_HEIGHT - 1)
lightpen_y[lpnum] = max_ypos_thisframe - LIGHTPEN_HEIGHT - 2;
- lightpen_cx = (((lightpen_x[lpnum] + visible_left_border) >> lores_shift) >> 1) + DISPLAY_LEFT_SHIFT - DIW_DDF_OFFSET;
+ int cx = (((lightpen_x[lpnum] + visible_left_border) >> lores_shift) >> 1) + DISPLAY_LEFT_SHIFT - DIW_DDF_OFFSET - 2;
- lightpen_cy = lightpen_y[lpnum];
- lightpen_cy >>= linedbl;
- lightpen_cy += minfirstline;
+ int cy = lightpen_y[lpnum];
+ cy >>= linedbl;
+ cy += minfirstline;
- if (lightpen_cx < 0x18)
- lightpen_cx = 0x18;
- if (lightpen_cx >= maxhpos)
- lightpen_cx -= maxhpos;
- if (lightpen_cy < minfirstline)
- lightpen_cy = minfirstline;
- if (lightpen_cy >= maxvpos)
- lightpen_cy = maxvpos - 1;
+ cx += currprefs.lightpen_offset[0];
+ cy += currprefs.lightpen_offset[1];
+
+ if (cx < 0x18)
+ cx = 0x18;
+ if (cx >= maxhpos)
+ cx -= maxhpos;
+ if (cy < minfirstline)
+ cy = minfirstline;
+ if (cy >= maxvpos)
+ cy = maxvpos - 1;
for (int i = 0; i < LIGHTPEN_HEIGHT; i++) {
int line = lightpen_y[lpnum] + i - LIGHTPEN_HEIGHT / 2;
if (line >= 0 || line < max_ypos_thisframe) {
- if (lightpen_active > 0)
- draw_lightpen_cursor (lightpen_x[lpnum], i, line, lightpen_cx > 0);
- flush_line (vb, line);
+ if (lightpen_active > 0 && currprefs.lightpen_crosshair) {
+ draw_lightpen_cursor (lightpen_x[lpnum], i, line, cx > 0, lpnum);
+ flush_line (vb, line);
+ }
}
}
- lightpen_y1 = lightpen_y[lpnum] - LIGHTPEN_HEIGHT / 2 - 1 + min_ypos_for_screen;
- lightpen_y2 = lightpen_y1 + LIGHTPEN_HEIGHT + 2;
+
+ lightpen_y1[lpnum] = lightpen_y[lpnum] - LIGHTPEN_HEIGHT / 2 - 1 + min_ypos_for_screen;
+ lightpen_y2[lpnum] = lightpen_y1[lpnum] + LIGHTPEN_HEIGHT + 2;
+
+ lightpen_cx[lpnum] = cx;
+ lightpen_cy[lpnum] = cy;
if (lightpen_active < 0)
lightpen_active = 0;
}
}
- if (lightpen_active)
- lightpen_update (vb, inputdevice_get_lightpen());
+ if (lightpen_active) {
+ lightpen_update (vb, 0);
+ if (inputdevice_get_lightpen_id() >= 0)
+ lightpen_update (vb, 1);
+ }
if (refresh_indicator_buffer)
refresh_indicator_update(vb);
state = linestate + lineno;
changed |= frame_redraw_necessary != 0 || refresh_indicator_buffer != NULL ||
- ((lineno >= lightpen_y1 && lineno < lightpen_y2) ||
+ ((lineno >= lightpen_y1[0] && lineno < lightpen_y2[0]) ||
+ (lineno >= lightpen_y1[1] && lineno < lightpen_y2[1]) ||
(lineno >= statusbar_y1 && lineno < statusbar_y2));
switch (how) {
notice_screen_contents_lost ();
frame_res_cnt = currprefs.gfx_autoresolution_delay;
- lightpen_y1 = lightpen_y2 = -1;
+ lightpen_y1[0] = lightpen_y2[0] = -1;
+ lightpen_y1[1] = lightpen_y2[1] = -1;
reset_custom_limits ();
extern void fpscounter_reset (void);
extern unsigned long idletime;
extern int lightpen_x[2], lightpen_y[2];
-extern int lightpen_cx, lightpen_cy, lightpen_active, lightpen_enabled;
+extern int lightpen_cx[2], lightpen_cy[2], lightpen_active, lightpen_enabled, lightpen_enabled2;
struct customhack {
uae_u16 v;
#define JOYBUTTON_CD32_RED 8
#define JOYBUTTON_CD32_BLUE 9
+#define JOYBUTTON_LIGHTPEN2 10
+
#define IDTYPE_JOYSTICK 0
#define IDTYPE_MOUSE 1
#define IDTYPE_KEYBOARD 2
extern void inputdevice_tablet_info (int maxx, int maxy, int maxz, int maxax, int maxay, int maxaz, int xres, int yres);
extern void inputdevice_tablet_strobe (void);
extern void tablet_lightpen(int x, int y, int maxx, int maxy, int touch, int buttonmask, bool touchmode, int devid, int lpnum);
-extern int inputdevice_get_lightpen(void);
+extern int inputdevice_get_lightpen_id(void);
extern uae_u64 input_getqualifiers (void);
int lightboost_strobo_ratio;
bool gfx_grayscale;
bool lightpen_crosshair;
+ int lightpen_offset[2];
struct gfx_filterdata gf[2];
static uae_s16 mouse_deltanoreset[MAX_JPORTS][MOUSE_AXIS_TOTAL];
static uae_s16 lightpen_delta[2][2];
static uae_s16 lightpen_deltanoreset[2][2];
+static int lightpen_trigger2;
static int joybutton[MAX_JPORTS];
static int joydir[MAX_JPORTS];
static int joydirpot[MAX_JPORTS][2];
static int pot_dat_act[NORMAL_JPORTS][2];
static int analog_port[NORMAL_JPORTS][2];
static int digital_port[NORMAL_JPORTS][2];
+static int lightpen_port[NORMAL_JPORTS];
#define POTDAT_DELAY_PAL 8
#define POTDAT_DELAY_NTSC 7
put_byte_host(mousehack_address + MH_CNT, get_byte_host(mousehack_address + MH_CNT) + 1);
}
-int inputdevice_get_lightpen(void)
+int inputdevice_get_lightpen_id(void)
{
- if (!alg_flag)
- return 0;
- return alg_get_player(potgo_value);
+ if (!alg_flag) {
+ if (lightpen_enabled2)
+ return alg_get_player(potgo_value);
+ return -1;
+ } else {
+ return alg_get_player(potgo_value);
+ }
}
void tablet_lightpen(int tx, int ty, int tmaxx, int tmaxy, int touch, int buttonmask, bool touchmode, int devid, int lpnum)
return mouse_pullup;
}
+static int lightpen_port_number(void)
+{
+ return currprefs.cs_dipagnus ? 0 : 1;
+}
+
static void charge_cap (int joy, int idx, int charge)
{
if (charge < -1 || charge > 1)
continue;
}
+ // two lightpens use multiplexer chip
+ if (lightpen_enabled2 && lightpen_port_number() == joy)
+ continue;
+
dong = dongle_analogjoy (joy, i);
if (dong >= 0) {
isbutton = 0;
if (cd32_pad_enabled[joy] && i == 1 && charge == 0)
charge = 2;
- /* official Commodore mouse has pull-up resistors in button lines
- * NOTE: 3rd party mice may not have pullups! */
- if (dong < 0 && (is_mouse_pullup (joy) && mouse_port[joy] && digital_port[joy][i]) && charge == 0)
- charge = 2;
+ if (dong < 0 && charge == 0) {
- /* emulate pullup resistor if button mapped because there too many broken
- * programs that read second button in input-mode (and most 2+ button pads have
- * pullups)
- */
- if (dong < 0 && (is_joystick_pullup (joy) && digital_port[joy][i]) && charge == 0)
- charge = 2;
+ if (lightpen_port[joy])
+ charge = 2;
+
+ /* official Commodore mouse has pull-up resistors in button lines
+ * NOTE: 3rd party mice may not have pullups! */
+ if (is_mouse_pullup (joy) && mouse_port[joy] && digital_port[joy][i])
+ charge = 2;
+
+ /* emulate pullup resistor if button mapped because there too many broken
+ * programs that read second button in input-mode (and most 2+ button pads have
+ * pullups)
+ */
+ if (is_joystick_pullup (joy) && digital_port[joy][i])
+ charge = 2;
+ }
charge_cap (joy, i, charge);
}
potgor = alg_potgor(potgo_value);
+ } else if (lightpen_enabled2 && lightpen_port_number() == i) {
+
+ int button;
+
+ if (inputdevice_get_lightpen_id() == 1)
+ button = lightpen_trigger2;
+ else
+ button = getbuttonstate(i, JOYBUTTON_3);
+
+ potgor |= 0x1000;
+ if (button)
+ potgor &= ~0x1000;
+
} else {
potgor &= ~p5dat;
switch (ie->unit)
{
case 5: /* lightpen/gun */
+ case 6: /* lightpen/gun #2 */
{
int unit = (ie->data & 1) ? 1 : 0;
- int lpnum = (ie->data & 2) ? 1 : 0;
- if (!lightpen_active) {
- for (int i = 0; i < 2; i++) {
- lightpen_x[i] = gfxvidinfo.outbuffer->outwidth / 2;
- lightpen_y[i] = gfxvidinfo.outbuffer->outheight / 2;
- }
+ int lpnum = ie->unit - 5;
+ if (lightpen_active <= 0) {
+ lightpen_x[0] = gfxvidinfo.outbuffer->outwidth / 2;
+ lightpen_y[0] = gfxvidinfo.outbuffer->outheight / 2;
+ lightpen_x[1] = -1;
+ lightpen_y[1] = -1;
}
lightpen_active = true;
lightpen_enabled = true;
lightpen_delta[lpnum][unit] = delta;
else
lightpen_delta[lpnum][unit] += delta;
+ } else if (ie->type == 2) {
+ lightpen_trigger2 = state;
} else {
- int delta = currprefs.input_joymouse_speed;
- if (ie->data & DIR_LEFT)
- lightpen_x[lpnum] -= delta;
- if (ie->data & DIR_RIGHT)
- lightpen_x[lpnum] += delta;
- if (ie->data & DIR_UP)
- lightpen_y[lpnum] -= delta;
- if (ie->data & DIR_DOWN)
- lightpen_y[lpnum] += delta;
+ if (state) {
+ int delta = currprefs.input_joymouse_speed;
+ if (ie->data & DIR_LEFT)
+ lightpen_x[lpnum] -= delta;
+ if (ie->data & DIR_RIGHT)
+ lightpen_x[lpnum] += delta;
+ if (ie->data & DIR_UP)
+ lightpen_y[lpnum] -= delta;
+ if (ie->data & DIR_DOWN)
+ lightpen_y[lpnum] += delta;
+ }
}
}
break;
lastmxy_abs[i][0] = 0;
lastmxy_abs[i][1] = 0;
}
+ lightpen_trigger2 = 0;
}
static int getoldport (struct uae_input_device *id)
static int islightpen (int ei)
{
+ if (ei >= INPUTEVENT_LIGHTPEN_HORIZ2 && ei < INPUTEVENT_LIGHTPEN_DOWN2) {
+ lightpen_enabled2 = true;
+ }
if (ei >= INPUTEVENT_LIGHTPEN_FIRST && ei < INPUTEVENT_LIGHTPEN_LAST) {
lightpen_enabled = true;
+ lightpen_port[lightpen_port_number()] = 1;
return 1;
}
return 0;
}
}
lightpen_enabled = false;
+ lightpen_enabled2 = false;
if (lightpen_active > 0)
lightpen_active = -1;
DEFEVENT(LIGHTPEN_RIGHT,_T("Lightpen Right"),AM_K,1,5,DIR_RIGHT)
DEFEVENT(LIGHTPEN_UP,_T("Lightpen Up"),AM_K,1,5,DIR_UP)
DEFEVENT(LIGHTPEN_DOWN,_T("Lightpen Down"),AM_K,1,5,DIR_DOWN)
+DEFEVENT(LIGHTPEN_HORIZ2,_T("Dual Lightpen Horizontal #2"),AM_MOUSE_AXIS|AM_JOY_AXIS,0,6,0)
+DEFEVENT(LIGHTPEN_VERT2,_T("Dual Lightpen Vertical #2"),AM_MOUSE_AXIS|AM_JOY_AXIS,0,6,1)
+DEFEVENT(LIGHTPEN_LEFT2,_T("Dual Lightpen Left #2"),AM_K,1,6,DIR_LEFT)
+DEFEVENT(LIGHTPEN_RIGHT2,_T("Dual Lightpen Right #2"),AM_K,1,6,DIR_RIGHT)
+DEFEVENT(LIGHTPEN_UP2,_T("Dual Lightpen Up #2"),AM_K,1,6,DIR_UP)
+DEFEVENT(LIGHTPEN_DOWN2,_T("Dual Lightpen Down #2"),AM_K,1,6,DIR_DOWN)
+DEFEVENT(LIGHTPEN_TRIGGER2,_T("Dual Lightpen Trigger"),AM_K,2,6,JOYBUTTON_LIGHTPEN2)
DEFEVENT(LIGHTPEN_LAST, _T(""), AM_DUMMY, 0,0,0)
DEFEVENT(SPC_ALG_RTRIGGER,_T("American Laser Games Right Trigger"),AM_K,0,0,AKS_ALGRTRIGGER)
DEFEVENT(SPC_ALG_LHOLSTER,_T("American Laser Games Left Holster"),AM_K,0,0,AKS_ALGLHOLSTER)
DEFEVENT(SPC_ALG_RHOLSTER,_T("American Laser Games Right Holster"),AM_K,0,0,AKS_ALGRHOLSTER)
-DEFEVENT(SPC_ALG_LIGHTPEN_HORIZ2,_T("American Laser Games Lightpen Horizontal #2"),AM_MOUSE_AXIS|AM_JOY_AXIS,0,5,2)
-DEFEVENT(SPC_ALG_LIGHTPEN_VERT2,_T("American Laser Games Lightpen Vertical #2"),AM_MOUSE_AXIS|AM_JOY_AXIS,0,5,3)
DEFEVENT(SPC_CDTV_FRONT_PANEL_STOP,_T("CDTV Front Panel Stop"),AM_K,0,0,AKS_CDTV_FRONT_PANEL_STOP)
DEFEVENT(SPC_CDTV_FRONT_PANEL_PLAYPAUSE,_T("CDTV Front Panel Play/Pause"),AM_K,0,0,AKS_CDTV_FRONT_PANEL_PLAYPAUSE)