// license:BSD-3-Clause // copyright-holders:David Viens /*************************************************************************** gic.c GI AY-3-8800-1 (Datasheet exists as AY-3-8500-1 Graphics Interface Chip) For the GIMINI "Challenger" programmable game system. Really only ever used in the Unisonic Champion 2711 More LA tests made by plgDavid on hardware pretty much confirmed what is found in the AY-3-8950-1 datasheet, but with more fine grained detail. the GIC does not have internal ram of any sort apart from shift registers, instead it relies on the external shared ram, (see page 7-85) Appendix AY-3-8950-1 Unverified on LA (since the video pins are all connected into a composite mix): at line 46 it lowers GIC_BUSY, until line 240 Verified using LA: It will read the external ram areas continuously while GIC_BUSY is low (for 12.36ms) (NOTE: OCTAL) 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?) 006,007,010,011,012,013, 110,111,112,113,114,115,116,117,120,121,122,123,124,125 (16 times) 014,015,016,017,020,021, 125,126,127,130,131,132,133,134,135,136,137,140,141,142 (16 times) 022,023,024,025,026,027, 125,126,127,130,131,132,133,134,135,136,137,140,141,142 (16 times) 030,031,032,033,034,035, 142,143,144,145,146,147,150,151,152,153,154,155,156,157 (16 times) 036,037,040,041,042,043, 142,143,144,145,146,147,150,151,152,153,154,155,156,157 (16 times) 044,045,046,047,050,051, 157,160,161,162,163,164,165,166,167,170,171,172,173,174 (16 times) 052,053,054,055,056,057, 157,160,161,162,163,164,165,166,167,170,171,172,173,174 (16 times) 060,061,062,063,064,065, 174,175,176,177,200,201,202,203,204,205,206,207,210,211 (16 times) 066,067,070,071,072,073, 174,175,176,177,200,201,202,203,204,205,206,207,210,211 (16 times) 074,075,076,077,100,101, 211,212,213,214,215,216,217,220,221,222,223,224,225,226 (16 times) 102,103,104,105,106,107, 211,212,213,214,215,216,217,220,221,222,223,224,225,226 (16 times) 000,001,002,003,004,005, 000,001,002,003,004,005,006,007,010,011,012,013,014,015 (once! padding?) for a total of (12*20*16) = 3840 RAM reads (3 clocks per read at 1.79MHz) Then it relingishes control to the CPU by raising BUSREQ. Cloking in more detail: (in 1.79MHz clocks) boot: busy:1 5360 clocks busy:0 22116 clocks busy:1 7752 clocks busy:0 22116 clocks busy:1 7752 clocks (...) There are NO IRQ handshakes, just BUSREQ sync shared RAM ***************************************************************************/ #include "emu.h" #include "gic.h" #include "screen.h" // device type definition DEFINE_DEVICE_TYPE(GIC, gic_device, "gic", "AY-3-8800-1 GIC") //Font data taken from Paul Robson's simulator //http://worstconsole.blogspot.ca/2012/12/the-worstconsoleever.html //A real AY-3-8800-1 (dead) is going to decap for a good dump ROM_START( gic_font ) ROM_REGION( 0x200, "cgrom", 0 ) ROM_LOAD( "ay-3-8800-1.bin", 0x0000, 0x200, BAD_DUMP CRC(d9f11d2b) SHA1(60ef45d51d102cd3af78787008d9aed848137bee)) ROM_END //------------------------------------------------- // gic_device - constructor //------------------------------------------------- gic_device::gic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : gic_device(mconfig, GIC, tag, owner, clock) { } gic_device::gic_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, type, tag, owner, clock) , device_sound_interface(mconfig, *this) , device_video_interface(mconfig, *this) , m_cgrom(*this, "cgrom") , m_audiocnt(0) , m_audioval(0) , m_audioreset(0) , m_ram(*this) { } const tiny_rom_entry *gic_device::device_rom_region() const { //there is only one... how do I get rid of this? return ROM_NAME( gic_font ); } //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- void gic_device::device_start() { // Let the screen create our temporary bitmap with the screen's dimensions screen().register_screen_bitmap(m_bitmap); m_vblank_timer = timer_alloc(TIMER_VBLANK); m_vblank_timer->adjust( screen().time_until_pos(1, END_ACTIVE_SCAN + 18 ), 0, screen().scan_period() ); // allocate the audio stream m_stream = stream_alloc( 0, 1, clock()/(2*228) ); m_ram.resolve_safe(0xff); } //------------------------------------------------- // device_reset - device-specific reset //------------------------------------------------- void gic_device::device_reset() { m_audiocnt=0; m_audioval=0; m_audioreset=0; } #define GIC_CLUB 28 #define GIC_SPACE 0 void gic_device::draw_char_left(int startx, int starty, uint8_t code, bitmap_ind16 &bitmap){ uint8_t*ptr = &m_cgrom[code*GIC_CHAR_H]; for (size_t y=0;y>4),m_bitmap,bgColor); }break; default:printf("gic unknown char! %02X\n",data); break; } } } copybitmap( bitmap, m_bitmap, 0, 0, 0, 0, cliprect ); return 0; } /* AUDIO SECTION */ void gic_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) { switch ( id ) { case TIMER_VBLANK: //flag the audio to reset m_audioreset = 1;//phase need to reset! on next clock/228 break; } } #define GIC_AUDIO_BYTE 0x96 void gic_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) { stream_sample_t *buffer = outputs[0]; //Audio is basic and badly implemented (doubt that was the intent) //The datasheet list the 3 different frequencies the GIC can generate: 500,1000 and 2000Hz //but it is clear (for an audio guy at least) that the resulting spectrum //is not a pure square wav. In fact, the counter is reset on vertical sync! //http://twitter.com/plgDavid/status/527269086016077825 //...thus creating a buzzing sound. //Dumping the audio pin value each time // either (PHI2 made a 0->1 transition (1.789MHz) // or (PHI1 made a 1->1 transition (1.789MHz) //I found that the granularity of audio transitions //(including phase resets and silences) was 228 clocks //The audio subsystem thus runs at 1.789MHz/228 = 7849.88Hz //when 1 //normal period:912 clocks (228*4) //hi for 456 clocks //lo for 456 clocks //reset period: (each frame) //hi for 228 clocks //lo for 456 clocks //when 2 //normal period lasts 1824 clocks (228*8) //hi for 912 clocks //lo for 912 clocks //reset period: (each frame) //hi for 912 (228*4) //lo for 1596 (228*7) //hi for 912 (228*4) //when 4 //normal period lasts 3648 clocks (228*16) //hi for 1824(228*8) //lo for 1824(228*8) //Reset period: //lo for 1824(228*8) //hi for 2508(228*11) //lo for 1824(228*8) //hi for 1824(228*8) uint8_t audioByte = m_ram(machine().dummy_space(), GIC_AUDIO_BYTE, 0xff)*2; if(!audioByte){ for(size_t i = 0; i < samples; i++) *buffer++ = 0; m_audioval = 0; m_audiocnt = 0; m_audioreset = 0; return;//early } //forced resynch @ 59.95Hz if(m_audioreset){ m_audioval = 0;//forced low m_audiocnt = 0; m_audioreset = 0; } for(size_t i=0; i < samples; i++){ m_audiocnt++; if(m_audiocnt >= audioByte){ m_audioval = !m_audioval; m_audiocnt=0; } *buffer++ = m_audioval<<13; } }