/*---------------------------------------------------------------------------*/ 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)); }
//--------------------------------------------------------------------------- void dma_sound_set_mode(BYTE new_mode) { dma_sound_mode=new_mode; dma_sound_freq=dma_sound_mode_to_freq[dma_sound_mode & 3]; log_to(LOGSECTION_SOUND,EasyStr("SOUND: ")+HEXSl(old_pc,6)+" - DMA sound mode set to $"+HEXSl(dma_sound_mode,2)+" freq="+dma_sound_freq); }
//--------------------------------------------------------------------------- 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; }