summaryrefslogtreecommitdiffstats
path: root/src/mame/includes/spectrum.h
blob: 10003c3f3132ea03bf1ab4328ea34c1b6704eab8 (plain) (blame)
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
// license:GPL-2.0+
// copyright-holders:Kevin Thacker
/*****************************************************************************
 *
 * includes/spectrum.h
 *
 ****************************************************************************/

#ifndef MAME_INCLUDES_SPECTRUM_H
#define MAME_INCLUDES_SPECTRUM_H

#pragma once

#include "machine/spec_snqk.h"
#include "machine/bankdev.h"
#include "bus/spectrum/exp.h"
#include "imagedev/cassette.h"
#include "imagedev/snapquik.h"
#include "machine/ram.h"
#include "sound/spkrdev.h"
#include "emupal.h"
#include "screen.h"
#include "cpu/z80/z80.h"

/* Spectrum crystals */

#define X1 14_MHz_XTAL          // Main clock (48k Spectrum)
#define X2 XTAL(4'433'619)      // PAL color subcarrier

/* Spectrum screen size in pixels */
#define SPEC_UNSEEN_LINES  16   /* Non-visible scanlines before first border
                                   line. Some of these may be vertical retrace. */
#define SPEC_TOP_BORDER    48   /* Number of border lines before actual screen */
#define SPEC_DISPLAY_YSIZE 192  /* Vertical screen resolution */
#define SPEC_BOTTOM_BORDER 56   /* Number of border lines at bottom of screen */
#define SPEC_SCREEN_HEIGHT (SPEC_TOP_BORDER + SPEC_DISPLAY_YSIZE + SPEC_BOTTOM_BORDER)

#define SPEC_LEFT_BORDER   48   /* Number of left hand border pixels */
#define SPEC_DISPLAY_XSIZE 256  /* Horizontal screen resolution */
#define SPEC_RIGHT_BORDER  48   /* Number of right hand border pixels */
#define SPEC_SCREEN_WIDTH (SPEC_LEFT_BORDER + SPEC_DISPLAY_XSIZE + SPEC_RIGHT_BORDER)

#define SPEC_LEFT_BORDER_CYCLES   24   /* Cycles to display left hand border */
#define SPEC_DISPLAY_XSIZE_CYCLES 128  /* Horizontal screen resolution */
#define SPEC_RIGHT_BORDER_CYCLES  24   /* Cycles to display right hand border */
#define SPEC_RETRACE_CYCLES       48   /* Cycles taken for horizontal retrace */
#define SPEC_CYCLES_PER_LINE      224  /* Number of cycles to display a single line */

class spectrum_state : public driver_device
{
public:
	spectrum_state(const machine_config &mconfig, device_type type, const char *tag) :
		driver_device(mconfig, type, tag),
		m_video_ram(*this, "video_ram"),
		m_maincpu(*this, "maincpu"),
		m_screen(*this, "screen"),
		m_cassette(*this, "cassette"),
		m_ram(*this, RAM_TAG),
		m_specmem(*this, "specmem"),
		m_speaker(*this, "speaker"),
		m_exp(*this, "exp"),
		m_io_line0(*this, "LINE0"),
		m_io_line1(*this, "LINE1"),
		m_io_line2(*this, "LINE2"),
		m_io_line3(*this, "LINE3"),
		m_io_line4(*this, "LINE4"),
		m_io_line5(*this, "LINE5"),
		m_io_line6(*this, "LINE6"),
		m_io_line7(*this, "LINE7"),
		m_io_nmi(*this, "NMI"),
		m_io_config(*this, "CONFIG"),
		m_io_plus0(*this, "PLUS0"),
		m_io_plus1(*this, "PLUS1"),
		m_io_plus2(*this, "PLUS2"),
		m_io_plus3(*this, "PLUS3"),
		m_io_plus4(*this, "PLUS4"),
		m_io_joy1(*this, "JOY1"),
		m_io_joy2(*this, "JOY2")
	{ }

	void spectrum_common(machine_config &config);
	void spectrum(machine_config &config);
	void spectrum_clone(machine_config &config);

	void init_spectrum();

protected:
	virtual void machine_start() override;
	virtual void machine_reset() override;
	virtual void video_start() override;

	// until machine/spec_snqk.cpp gets somehow disentangled
	virtual void plus3_update_memory() { }
	virtual void spectrum_128_update_memory() { }
	virtual void ts2068_update_memory() { }

	TIMER_CALLBACK_MEMBER(irq_on);
	TIMER_CALLBACK_MEMBER(irq_off);
	TIMER_CALLBACK_MEMBER(finish_screen_update);

	emu_timer *m_irq_on_timer;
	emu_timer *m_irq_off_timer;
	emu_timer *m_finish_screen_update_timer;

	int m_port_fe_data;
	int m_port_7ffd_data;
	int m_port_1ffd_data;   /* scorpion and plus3 */
	int m_port_ff_data; /* Display enhancement control */
	int m_port_f4_data; /* Horizontal Select Register */

	/* video support */
	int m_frame_invert_count; /* Used for handling FLASH 1 */
	optional_shared_ptr<uint8_t> m_video_ram;
	uint8_t *m_screen_location;

	std::vector<u8> m_contention_pattern;
	/* Pixel offset in 8px chunk (4T) when current chunk is rendered. */
	u8 m_border4t_render_at = 0;
	/* Defines offset in CPU cycles from screen left side. Early model (48/128/+2) typically use -1, later (+2A/+3) +1 */
	s8 m_contention_offset = -1;
	u64 m_int_at;

	uint8_t pre_opcode_fetch_r(offs_t offset);
	void spectrum_rom_w(offs_t offset, uint8_t data);
	uint8_t spectrum_rom_r(offs_t offset);
	uint8_t spectrum_data_r(offs_t offset);
	void spectrum_data_w(offs_t offset, uint8_t data);
	virtual bool is_contended(offs_t offset);
	virtual bool is_vram_write(offs_t offset);
	void content_early(s8 shift = 0);
	void content_late();

	void spectrum_nomreq(offs_t offset, uint8_t data);
	void spectrum_ula_w(offs_t offset, uint8_t data);
	uint8_t spectrum_ula_r(offs_t offset);
	void spectrum_port_w(offs_t offset, uint8_t data);
	virtual uint8_t spectrum_port_r(offs_t offset);
	uint8_t floating_bus_r();
	uint8_t spectrum_clone_port_r(offs_t offset);

	void spectrum_palette(palette_device &palette) const;
	virtual u32 screen_update_spectrum(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
	INTERRUPT_GEN_MEMBER(spec_interrupt);

	DECLARE_SNAPSHOT_LOAD_MEMBER(snapshot_cb);
	DECLARE_QUICKLOAD_LOAD_MEMBER(quickload_cb);

	required_device<z80_device> m_maincpu;
	required_device<screen_device> m_screen;

	void spectrum_io(address_map &map);
	void spectrum_clone_io(address_map &map);
	void spectrum_opcodes(address_map &map);
	void spectrum_map(address_map &map);
	void spectrum_data(address_map &map);

	required_device<cassette_image_device> m_cassette;
	required_device<ram_device> m_ram;
	optional_device<address_map_bank_device> m_specmem;
	required_device<speaker_sound_device> m_speaker;
	optional_device<spectrum_expansion_slot_device> m_exp;

	// Regular spectrum ports; marked as optional because of other subclasses
	optional_ioport m_io_line0;
	optional_ioport m_io_line1;
	optional_ioport m_io_line2;
	optional_ioport m_io_line3;
	optional_ioport m_io_line4;
	optional_ioport m_io_line5;
	optional_ioport m_io_line6;
	optional_ioport m_io_line7;
	optional_ioport m_io_nmi;
	optional_ioport m_io_config;

	// Plus ports
	optional_ioport m_io_plus0;
	optional_ioport m_io_plus1;
	optional_ioport m_io_plus2;
	optional_ioport m_io_plus3;
	optional_ioport m_io_plus4;

	// Joystick ports
	optional_ioport m_io_joy1;
	optional_ioport m_io_joy2;

	virtual u8 get_border_color(u16 hpos = ~0, u16 vpos = ~0);
	// Defines position of main screen excluding border
	virtual rectangle get_screen_area();
	virtual void spectrum_update_border(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
	virtual void spectrum_update_screen(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);

	// snapshot helpers
	void update_paging();
	void page_basicrom();
	void border_update(int data);
	void setup_sp(uint8_t *snapdata, uint32_t snapsize);
	void setup_sna(uint8_t *snapdata, uint32_t snapsize);
	void setup_ach(uint8_t *snapdata, uint32_t snapsize);
	void setup_prg(uint8_t *snapdata, uint32_t snapsize);
	void setup_plusd(uint8_t *snapdata, uint32_t snapsize);
	void setup_sem(uint8_t *snapdata, uint32_t snapsize);
	void setup_sit(uint8_t *snapdata, uint32_t snapsize);
	void setup_zx(uint8_t *snapdata, uint32_t snapsize);
	void setup_snp(uint8_t *snapdata, uint32_t snapsize);
	void snx_decompress_block(address_space &space, uint8_t *source, uint16_t dest, uint16_t size);
	void setup_snx(uint8_t *snapdata, uint32_t snapsize);
	void setup_frz(uint8_t *snapdata, uint32_t snapsize);
	void z80_decompress_block(address_space &space, uint8_t *source, uint16_t dest, uint16_t size);
	void setup_z80(uint8_t *snapdata, uint32_t snapsize);

	// quickload helpers
	void log_quickload(const char *type, uint32_t start, uint32_t length, uint32_t exec, const char *exec_format);
	void setup_scr(uint8_t *quickdata, uint32_t quicksize);
	void setup_raw(uint8_t *quickdata, uint32_t quicksize);
};

/*----------- defined in drivers/spectrum.cpp -----------*/

INPUT_PORTS_EXTERN( spectrum );
INPUT_PORTS_EXTERN( spec128 );
INPUT_PORTS_EXTERN( spec_plus );

#endif // MAME_INCLUDES_SPECTRUM_H