//--------------------------------------------------------------------------- void UpdateCentronicsBusyBit() { if ((stick[N_JOY_PARALLEL_1] & BIT_4)==0){ if (ParallelPort.IsOpen()){ if (psg_reg[PSGR_MIXER] & BIT_7){ // Output // If there are bytes being sent then input is high mfp_gpip_set_bit(MFP_GPIP_CENTRONICS_BIT,ParallelPort.AreBytesToOutput()); }else{ // Input // If there are bytes being received then input is high mfp_gpip_set_bit(MFP_GPIP_CENTRONICS_BIT,ParallelPort.AreBytesToRead()); } }else{ mfp_gpip_set_bit(MFP_GPIP_CENTRONICS_BIT,true); // Always busy if port closed } } }
/*---------------------------------------------------------------------------*/ void dma_sound_set_control(BYTE io_src_b) { if ((dma_sound_control & BIT_0) && (io_src_b & BIT_0)==0){ //Stopping dma_sound_start=next_dma_sound_start; dma_sound_end=next_dma_sound_end; dma_sound_fetch_address=dma_sound_start; }else if ((dma_sound_control & BIT_0)==0 && (io_src_b & BIT_0)){ //Start playing dma_sound_start=next_dma_sound_start; dma_sound_end=next_dma_sound_end; dma_sound_fetch_address=dma_sound_start; if (dma_sound_on_this_screen==0){ // Pad buffer with last byte from VBL to current position bool Mono=bool(dma_sound_mode & BIT_7); int freq_idx=0; if (shifter_freq_at_start_of_vbl==60) freq_idx=1; if (shifter_freq_at_start_of_vbl==MONO_HZ) freq_idx=2; WORD w1,w2; dma_sound_get_last_sample(&w1,&w2); for (int y=-scanlines_above_screen[freq_idx];y<scan_y;y++){ if (Mono){ //play half as many words dma_sound_samples_countdown+=dma_sound_freq*scanline_time_in_cpu_cycles_at_start_of_vbl/2; }else{ //stereo, 1 word per sample dma_sound_samples_countdown+=dma_sound_freq*scanline_time_in_cpu_cycles_at_start_of_vbl; } int loop=int(Mono ? 2:1); while (dma_sound_samples_countdown>=0){ for (int i=0;i<loop;i++){ dma_sound_output_countdown+=sound_freq; while (dma_sound_output_countdown>=0){ if (dma_sound_channel_buf_last_write_t>=DMA_SOUND_BUFFER_LENGTH) break; dma_sound_channel_buf[dma_sound_channel_buf_last_write_t++]=w1; dma_sound_channel_buf[dma_sound_channel_buf_last_write_t++]=w2; dma_sound_output_countdown-=dma_sound_freq; } } dma_sound_samples_countdown-=n_cpu_cycles_per_second; } } dma_sound_on_this_screen=1; } } log_to(LOGSECTION_SOUND,EasyStr("SOUND: ")+HEXSl(old_pc,6)+" - DMA sound control set to "+(io_src_b & 3)+" from "+(dma_sound_control & 3)); dma_sound_control=io_src_b; if (tos_version>=0x106) mfp_gpip_set_bit(MFP_GPIP_MONO_BIT,bool(COLOUR_MONITOR)^bool(dma_sound_control & BIT_0)); }
//--------------------------------------------------------------------------- // MIDI Port //--------------------------------------------------------------------------- void agenda_midi_replace(int) { if (MIDIPort.AreBytesToCome()){ MIDIPort.NextByte(); if (ACIA_MIDI.rx_not_read){ // discard data and set overrun log_to_section(LOGSECTION_MIDI,"MIDI: Overrun on ACIA! Byte lost!"); if (ACIA_MIDI.overrun!=ACIA_OVERRUN_YES) ACIA_MIDI.overrun=ACIA_OVERRUN_COMING; }else{ ACIA_MIDI.data=MIDIPort.ReadByte(); ACIA_MIDI.rx_not_read=true; } log_to_section(LOGSECTION_MIDI,EasyStr("MIDI: Fire ACIA interrupt")); if (ACIA_MIDI.rx_irq_enabled) ACIA_MIDI.irq=true; mfp_gpip_set_bit(MFP_GPIP_ACIA_BIT,!(ACIA_IKBD.irq || ACIA_MIDI.irq)); if (MIDIPort.AreBytesToCome()) agenda_add(agenda_midi_replace,ACIAClockToHBLS(ACIA_MIDI.clock_divide,true),0); } }
//--------------------------------------------------------------------------- BYTE ASMCALL io_read_b(MEM_ADDRESS addr) { /* Allowed addresses 000000 - 3FFFFF RAM D00000 - D7FFFF E00000 - E3FFFF TOS E40000 - EBFFFF FA0000 - FBFFFF Cart FE0000 - FE1FFF FF8000 - FF800F MMU FF8200 - FF820F SHIFTER FF8240 - FF827F pallette, res FF8608 - FF860F FDC FF8800 - FF88FF sound chip FF8900 - FF893F DMA sound, microwire FF8A00 - FF8A3F blitter FF9000 - FF9001 FF9201, FF9202, FF9203 paddles FF9211, FF9213, FF9215, FF9217 paddles FFFA01, odd addresses up to FFFA3F MFP FFFC00 - FFFDFF ACIA, realtime clock Word differences: FF8604 - FF860F FDC FF9200, FF9202 paddles FF9210, FF9212, FF9214, FF9216 paddles FF9220, FF9222 paddles FFFA00 - FFFA3F MFP */ DEBUG_CHECK_READ_IO_B(addr); #ifdef ONEGAME if (addr>=OG_TEXT_ADDRESS && addr<OG_TEXT_ADDRESS+OG_TEXT_LEN){ return BYTE(OG_TextMem[addr-OG_TEXT_ADDRESS]); } #endif switch (addr & 0xffff00){ //fffe00 case 0xfffc00: //----------------------------------- ACIAs { // Only cause bus jam once per word DEBUG_ONLY( if (mode==STEM_MODE_CPU) ) { if (io_word_access==0 || (addr & 1)==0){ // if (passed VBL or HBL point){ // BUS_JAM_TIME(4); // }else{ // Jorge Cwik: // Access to the ACIA is synchronized to the E signal. Which is a clock with // one tenth the frequency of the main CPU clock (800 Khz). So the timing // should depend on the phase relationship between both clocks. int rel_cycle=ABSOLUTE_CPU_TIME-shifter_cycle_base; rel_cycle=8000000-rel_cycle; rel_cycle%=10; BUS_JAM_TIME(rel_cycle+6); // BUS_JAM_TIME(8); } } switch (addr){ /******************** Keyboard ACIA ************************/ case 0xfffc00: //status { BYTE x=0; if (ACIA_IKBD.rx_not_read || ACIA_IKBD.overrun==ACIA_OVERRUN_YES) x|=BIT_0; //full bit if (ACIA_IKBD.tx_flag==0) x|=BIT_1; //empty bit // if (acia[ACIA_IKBD].rx_not_read && acia[ACIA_IKBD].rx_irq_enabled) x|=BIT_7; //irq bit if (ACIA_IKBD.irq) x|=BIT_7; //irq bit if (ACIA_IKBD.overrun==ACIA_OVERRUN_YES) x|=BIT_5; //overrun return x; } case 0xfffc02: //data { DEBUG_ONLY( if (mode!=STEM_MODE_CPU) return ACIA_IKBD.data; ) // if (acia[ACIA_IKBD].rx_not_read) keyboard_buffer_length--; ACIA_IKBD.rx_not_read=0; LOG_ONLY( bool old_irq=ACIA_IKBD.irq; ) if (ACIA_IKBD.overrun==ACIA_OVERRUN_COMING){ ACIA_IKBD.overrun=ACIA_OVERRUN_YES; if (ACIA_IKBD.rx_irq_enabled) ACIA_IKBD.irq=true; LOG_ONLY( log_to_section(LOGSECTION_IKBD,EasyStr("IKBD: ")+HEXSl(old_pc,6)+ " - OVERRUN! Read data ($"+HEXSl(ACIA_IKBD.data,2)+ "), changing ACIA IRQ bit from "+old_irq+" to "+ACIA_IKBD.irq); ) }else{ ACIA_IKBD.overrun=ACIA_OVERRUN_NO; // IRQ should be off for receive, but could be set for tx empty interrupt ACIA_IKBD.irq=(ACIA_IKBD.tx_irq_enabled && ACIA_IKBD.tx_flag==0); LOG_ONLY( if (ACIA_IKBD.irq!=old_irq) log_to_section(LOGSECTION_IKBD,Str("IKBD: ")+ HEXSl(old_pc,6)+" - Read data ($"+HEXSl(ACIA_IKBD.data,2)+ "), changing ACIA IRQ bit from "+old_irq+" to "+ACIA_IKBD.irq); ) } mfp_gpip_set_bit(MFP_GPIP_ACIA_BIT,!(ACIA_IKBD.irq || ACIA_MIDI.irq)); return ACIA_IKBD.data; }