1 // license:BSD-3-Clause
2 // copyright-holders:David Viens
3 /***************************************************************************
4 
5    gic.c
6 
7    GI AY-3-8800-1 (Datasheet exists as AY-3-8500-1 Graphics Interface Chip)
8    For the GIMINI "Challenger" programmable game system.
9 
10    Really only ever used in the Unisonic Champion 2711
11 
12    More LA tests made by plgDavid on hardware pretty much confirmed what is found
13    in the AY-3-8950-1 datasheet, but with more fine grained detail.
14 
15    the GIC does not have internal ram of any sort apart from shift registers,
16    instead it relies on the external shared ram, (see page 7-85) Appendix AY-3-8950-1
17 
18    Unverified on LA (since the video pins are all connected into a composite mix):
19    at line 46 it lowers GIC_BUSY, until line 240
20 
21    Verified using LA:
22    It will read the external ram areas continuously while GIC_BUSY is low (for 12.36ms)
23 
24    (NOTE: OCTAL)
25 
26    000,001,002,003,004,005,  110,111,112,113,114,115,116,117,120,121,122,123,124,125 (15 times - No first bg line?)
27    006,007,010,011,012,013,  110,111,112,113,114,115,116,117,120,121,122,123,124,125 (16 times)
28 
29    014,015,016,017,020,021,  125,126,127,130,131,132,133,134,135,136,137,140,141,142 (16 times)
30    022,023,024,025,026,027,  125,126,127,130,131,132,133,134,135,136,137,140,141,142 (16 times)
31 
32    030,031,032,033,034,035,  142,143,144,145,146,147,150,151,152,153,154,155,156,157 (16 times)
33    036,037,040,041,042,043,  142,143,144,145,146,147,150,151,152,153,154,155,156,157 (16 times)
34 
35    044,045,046,047,050,051,  157,160,161,162,163,164,165,166,167,170,171,172,173,174 (16 times)
36    052,053,054,055,056,057,  157,160,161,162,163,164,165,166,167,170,171,172,173,174 (16 times)
37 
38    060,061,062,063,064,065,  174,175,176,177,200,201,202,203,204,205,206,207,210,211 (16 times)
39    066,067,070,071,072,073,  174,175,176,177,200,201,202,203,204,205,206,207,210,211 (16 times)
40 
41    074,075,076,077,100,101,  211,212,213,214,215,216,217,220,221,222,223,224,225,226 (16 times)
42    102,103,104,105,106,107,  211,212,213,214,215,216,217,220,221,222,223,224,225,226 (16 times)
43 
44    000,001,002,003,004,005,  000,001,002,003,004,005,006,007,010,011,012,013,014,015 (once! padding?)
45 
46    for a total of (12*20*16) = 3840 RAM reads (3 clocks per read at 1.79MHz)
47 
48    Then it relinquishes control to the CPU by raising BUSREQ.
49 
50    Clocking in more detail: (in 1.79MHz clocks)
51    boot:
52     busy:1  5360 clocks
53     busy:0 22116 clocks
54     busy:1  7752 clocks
55     busy:0 22116 clocks
56     busy:1  7752 clocks
57     (...)
58 
59    There are NO IRQ handshakes, just BUSREQ sync shared RAM
60 
61 ***************************************************************************/
62 
63 #include "emu.h"
64 #include "gic.h"
65 #include "screen.h"
66 
67 // device type definition
68 DEFINE_DEVICE_TYPE(GIC, gic_device, "gic", "AY-3-8800-1 GIC")
69 
70 
71 //Font data taken from Paul Robson's simulator
72 //http://worstconsole.blogspot.ca/2012/12/the-worstconsoleever.html
73 //A real AY-3-8800-1 (dead) is going to decap for a good dump
ROM_START(gic_font)74 ROM_START( gic_font )
75 	ROM_REGION( 0x200, "cgrom", 0 )
76 	ROM_LOAD( "ay-3-8800-1.bin", 0x0000, 0x200,  BAD_DUMP CRC(d9f11d2b) SHA1(60ef45d51d102cd3af78787008d9aed848137bee))
77 ROM_END
78 
79 
80 //-------------------------------------------------
81 //  gic_device - constructor
82 //-------------------------------------------------
83 
84 gic_device::gic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
85 	: gic_device(mconfig, GIC, tag, owner, clock)
86 {
87 }
88 
89 
gic_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)90 gic_device::gic_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
91 	: device_t(mconfig, type, tag, owner, clock)
92 	, device_sound_interface(mconfig, *this)
93 	, device_video_interface(mconfig, *this)
94 	, m_cgrom(*this, "cgrom")
95 	, m_audiocnt(0)
96 	, m_audioval(0)
97 	, m_audioreset(0)
98 	, m_ram(*this)
99 {
100 }
101 
device_rom_region() const102 const tiny_rom_entry *gic_device::device_rom_region() const
103 {
104 	//there is only one... how do I get rid of this?
105 	return ROM_NAME( gic_font );
106 }
107 
108 //-------------------------------------------------
109 //  device_start - device-specific startup
110 //-------------------------------------------------
111 
device_start()112 void gic_device::device_start()
113 {
114 	// Let the screen create our temporary bitmap with the screen's dimensions
115 	screen().register_screen_bitmap(m_bitmap);
116 
117 	m_vblank_timer = timer_alloc(TIMER_VBLANK);
118 	m_vblank_timer->adjust( screen().time_until_pos(1, END_ACTIVE_SCAN + 18 ), 0, screen().scan_period() );
119 
120 	// allocate the audio stream
121 	m_stream = stream_alloc( 0, 1, clock()/(2*228) );
122 
123 	m_ram.resolve_safe(0xff);
124 }
125 
126 
127 //-------------------------------------------------
128 //  device_reset - device-specific reset
129 //-------------------------------------------------
130 
device_reset()131 void gic_device::device_reset()
132 {
133 	m_audiocnt=0;
134 	m_audioval=0;
135 	m_audioreset=0;
136 }
137 
138 #define GIC_CLUB    28
139 #define GIC_SPACE    0
140 
draw_char_left(int startx,int starty,uint8_t code,bitmap_ind16 & bitmap)141 void gic_device::draw_char_left(int startx, int starty, uint8_t code, bitmap_ind16 &bitmap){
142 	uint8_t*ptr = &m_cgrom[code*GIC_CHAR_H];
143 
144 	for (size_t y=0;y<GIC_CHAR_H;y++){
145 		uint8_t current = *ptr++;
146 		uint8_t nextx=0;
147 		uint8_t curry= starty+y;
148 		for(uint8_t x=0x20;x!=0;x=x/2){
149 			if (current&x)
150 				m_bitmap.pix(curry,startx+nextx) = GIC_WHITE;
151 			nextx++;
152 		}
153 	}
154 }
155 
draw_char_right(int startx,int starty,uint8_t code,bitmap_ind16 & bitmap,int bg_col)156 void gic_device::draw_char_right(int startx, int starty, uint8_t code, bitmap_ind16 &bitmap, int bg_col){
157 	uint8_t*ptr = &m_cgrom[code*GIC_CHAR_H];
158 
159 	for (size_t y=0;y<GIC_CHAR_H;y++){
160 		uint8_t current = *ptr++;
161 		uint8_t nextx=0;
162 		uint8_t curry= starty+y;
163 
164 		m_bitmap.pix(curry,startx+nextx) = bg_col;
165 		nextx++;
166 		for(uint8_t x=0x20;x!=0;x=x/2){
167 			m_bitmap.pix(curry,startx+nextx) = (current&x)?GIC_WHITE:bg_col;
168 			nextx++;
169 		}
170 		m_bitmap.pix(curry,startx+nextx) = bg_col;
171 		nextx++;
172 		m_bitmap.pix(curry,startx+nextx) = bg_col;
173 	}
174 }
175 
screen_update(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)176 uint32_t gic_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
177 {
178 	m_bitmap.fill(GIC_GREEN);
179 
180 	size_t XSTART = BORDER_SIZE;
181 	size_t YSTART = START_ACTIVE_SCAN;
182 
183 	//left hand side first
184 	uint8_t current=0;
185 	for(uint8_t cy=0;cy<GIC_LEFT_H;cy++){
186 		for(uint8_t cx=0;cx<GIC_LEFT_W;cx++){
187 			draw_char_left(XSTART+(cx*GIC_CHAR_W),
188 							YSTART+(cy*GIC_CHAR_H),
189 							m_ram(current),
190 							m_bitmap);
191 			current++;
192 		}
193 	}
194 
195 	//right hand side is next
196 	current=0x48;//110 octal
197 	XSTART+=(GIC_LEFT_W*GIC_CHAR_W)+1;
198 
199 	for(uint8_t cy=0;cy<GIC_RIGHT_H;cy++){
200 		for(uint8_t cx=0;cx<GIC_RIGHT_W;cx++){
201 			//complex case
202 			uint8_t data = m_ram(current++);
203 
204 			size_t currX   = (XSTART+           (cx*(3+GIC_CHAR_W)));
205 			size_t currUP  = (YSTART+           (cy*(2*GIC_CHAR_H)));
206 			size_t currLOW = (YSTART+GIC_CHAR_H+(cy*(2*GIC_CHAR_H)));
207 
208 			switch(data&0xC0){
209 				case 0x00:{
210 					//lower rectangle only, normal char
211 					draw_char_right(currX,currLOW,data,m_bitmap,GIC_GREEN);
212 				}break;
213 
214 				//White block
215 				case 0xC0:{
216 					//upper rectangle
217 					draw_char_right(currX,currUP, GIC_SPACE,m_bitmap,GIC_WHITE);
218 					//lower rectangle
219 					draw_char_right(currX,currLOW,GIC_SPACE,m_bitmap,GIC_WHITE);
220 				}break;
221 
222 				//Draw a card
223 				case 0x40:{
224 					int bgColor = (data&0x10)?GIC_RED:GIC_BLACK;
225 					//upper rectangle
226 					draw_char_right(currX,currUP,           (data&0xF)+0x30,m_bitmap,bgColor);
227 					//lower rectangle
228 					draw_char_right(currX,currLOW,GIC_CLUB+((data&0x30)>>4),m_bitmap,bgColor);
229 				}break;
230 
231 				default:printf("gic unknown char! %02X\n",data); break;
232 			}
233 		}
234 	}
235 
236 	copybitmap( bitmap, m_bitmap, 0, 0, 0, 0, cliprect );
237 	return 0;
238 }
239 
240 /* AUDIO SECTION */
241 
device_timer(emu_timer & timer,device_timer_id id,int param,void * ptr)242 void gic_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
243 {
244 	switch ( id )
245 	{
246 		case TIMER_VBLANK:
247 			//flag the audio to reset
248 			m_audioreset = 1;//phase need to reset! on next clock/228
249 		break;
250 	}
251 }
252 
253 #define GIC_AUDIO_BYTE 0x96
254 
sound_stream_update(sound_stream & stream,std::vector<read_stream_view> const & inputs,std::vector<write_stream_view> & outputs)255 void gic_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
256 {
257 	auto &buffer = outputs[0];
258 
259 	//Audio is basic and badly implemented (doubt that was the intent)
260 	//The datasheet lists the 3 different frequencies the GIC can generate: 500,1000 and 2000Hz
261 	//but it is clear (for an audio guy at least) that the resulting spectrum
262 	//is not a pure square wave. In fact, the counter is reset on vertical sync!
263 	//http://twitter.com/plgDavid/status/527269086016077825
264 	//...thus creating a buzzing sound.
265 
266 	//Dumping the audio pin value each time
267 	// either (PHI2 made a 0->1 transition (1.789MHz)
268 	//     or (PHI1 made a 1->1 transition (1.789MHz)
269 	//I found that the granularity of audio transitions
270 	//(including phase resets and silences) was 228 clocks
271 	//The audio subsystem thus runs at 1.789MHz/228 = 7849.88Hz
272 
273 	//when 1
274 	//normal period:912 clocks (228*4)
275 	//hi for 456 clocks
276 	//lo for 456 clocks
277 	//reset period: (each frame)
278 	//hi for 228 clocks
279 	//lo for 456 clocks
280 	//when 2
281 	//normal period lasts 1824 clocks (228*8)
282 	//hi for 912 clocks
283 	//lo for 912 clocks
284 	//reset period: (each frame)
285 	//hi for 912   (228*4)
286 	//lo for 1596  (228*7)
287 	//hi for 912   (228*4)
288 	//when 4
289 	//normal period lasts 3648 clocks (228*16)
290 	//hi for 1824(228*8)
291 	//lo for 1824(228*8)
292 	//Reset period:
293 	//lo for 1824(228*8)
294 	//hi for 2508(228*11)
295 	//lo for 1824(228*8)
296 	//hi for 1824(228*8)
297 
298 	uint8_t audioByte = m_ram(GIC_AUDIO_BYTE)*2;
299 
300 	if(!audioByte){
301 		buffer.fill(0);
302 
303 		m_audioval   = 0;
304 		m_audiocnt   = 0;
305 		m_audioreset = 0;
306 		return;//early
307 	}
308 
309 	//forced resynch @ 59.95Hz
310 	if(m_audioreset){
311 		m_audioval   = 0;//forced low
312 		m_audiocnt   = 0;
313 		m_audioreset = 0;
314 	}
315 
316 	for(size_t i=0; i < buffer.samples(); i++){
317 		m_audiocnt++;
318 		if(m_audiocnt >= audioByte){
319 			m_audioval = !m_audioval;
320 			m_audiocnt=0;
321 		}
322 		buffer.put(i, m_audioval ? 1.0 : 0.0);
323 	}
324 }
325