Beispiel #1
0
void uae_PutMsg (uaecptr port, uaecptr msg)
{
	uae_sem_wait (&n2asem);
	write_comm_pipe_int (&native2amiga_pending, 1, 0);
	write_comm_pipe_u32 (&native2amiga_pending, port, 0);
	write_comm_pipe_u32 (&native2amiga_pending, msg, 1);
	do_uae_int_requested ();
	uae_sem_post (&n2asem);
}
Beispiel #2
0
void uae_PutMsg(uaecptr port, uaecptr msg)
{
    uae_pt data;
    data.i = 1;
    write_comm_pipe_int (&native2amiga_pending, 1, 0);
    write_comm_pipe_u32 (&native2amiga_pending, port, 0);
    write_comm_pipe_u32 (&native2amiga_pending, msg, 1);

    uae_int_requested = 1;
}
Beispiel #3
0
static uae_u32 REGPARAM2 dev_beginio (TrapContext *context)
{
    uae_u32 request = m68k_areg (&context->regs, 1);
    uae_u8 flags = get_byte (request + 30);
    int command = get_word (request + 28);
    struct priv_devstruct *pdev = getpdevstruct (request);
    struct devstruct *dev = getdevstruct (pdev->unit);

    put_byte (request+8, NT_MESSAGE);
    if (!dev || !pdev) {
	put_byte (request + 31, 32);
	return get_byte (request + 31);
    }
    put_byte (request+31, 0);
    if ((flags & 1) && dev_canquick (dev, request)) {
	if (dev_do_io (dev, request))
	    write_log ("device %s command %d bug with IO_QUICK\n", getdevname (pdev->type), command);
	return get_byte (request + 31);
    } else {
	add_async_request (dev, request, ASYNC_REQUEST_TEMP, 0);
	put_byte (request+30, get_byte (request + 30) & ~1);
	write_comm_pipe_u32 (&dev->requests, request, 1);
	return 0;
    }
}
Beispiel #4
0
static void dev_close_3 (struct devstruct *dev)
{
	uaeser_close (dev->sysdata);
	dev->open = 0;
	xfree (dev->sysdata);
	write_comm_pipe_u32 (&dev->requests, 0, 1);
}
Beispiel #5
0
static void do_abort_async (struct s2devstruct *dev, uaecptr request)
{
	put_byte (request + 30, get_byte (request + 30) | 0x20);
	put_byte (request + 31, IOERR_ABORTED);
	put_long (request + 32, S2WERR_GENERIC_ERROR);
	write_comm_pipe_u32 (&dev->requests, request, 1);
}
Beispiel #6
0
static void dev_reset (void)
{
	int i;
	struct s2devstruct *dev;
	int unitnum = 0;

	write_log (_T("%s reset\n"), getdevname());
	for (i = 0; i < MAX_TOTAL_NET_DEVICES; i++) {
		dev = &devst[i];
		if (dev->opencnt) {
			struct asyncreq *ar = dev->ar;
			while (ar) {
				if (!ar->ready) {
					dev->ar->ready = 1;
					do_abort_async (dev, ar->request);
				}
				ar = ar->next;
			}
			write_comm_pipe_u32 (&dev->requests, 0, 1);
			uae_sem_wait (&dev->sync_sem);
		}
		while (dev->mc)
			delmulticastaddresses (dev, dev->mc->start, dev->mc->end);
		memset (dev, 0, sizeof (struct s2devstruct));
	}
	for (i = 0; i < MAX_OPEN_DEVICES; i++)
		memset (&pdevst[i], 0, sizeof (struct priv_s2devstruct));
	uaenet_vsync_requested = 0;
	uaenet_int_requested = 0;
	irq_init = 0;

}
Beispiel #7
0
static void open_screen(struct uae_prefs *p)
{
  graphics_subshutdown();
  
  current_resource_amigafb = 0;

	currprefs.gfx_correct_aspect = changed_prefs.gfx_correct_aspect;
	currprefs.gfx_fullscreen_ratio = changed_prefs.gfx_fullscreen_ratio;

#ifdef PICASSO96
	if (screen_is_picasso) {
		display_width = picasso_vidinfo.width ? picasso_vidinfo.width : 640;
		display_height = picasso_vidinfo.height ? picasso_vidinfo.height : 256;
	} else
#endif
	{
		p->gfx_resolution = p->gfx_monitor.gfx_size.width ? (p->gfx_monitor.gfx_size.width > 600 ? 1 : 0) : 1;
		display_width = p->gfx_monitor.gfx_size.width ? p->gfx_monitor.gfx_size.width : 640;
		display_height = (p->gfx_monitor.gfx_size.height ? p->gfx_monitor.gfx_size.height : 256) << p->gfx_vresolution;
	}

	write_comm_pipe_u32(display_pipe, DISPLAY_SIGNAL_OPEN, 1);
  uae_sem_wait (&display_sem);
  
	if (prSDLScreen != NULL) {
		InitAmigaVidMode(p);
		init_row_map();
	}    

  calibrate_done = false;
  reset_sync();
}
Beispiel #8
0
/*
 * Shut down SCSI layer
 */
static void dev_exit (void)
{
    int i, j;
    struct devstruct *dev;

    for (i = 0; i < MAX_TOTAL_DEVICES; i++) {
	dev = &devst[i];
	if (dev->opencnt > 0) {
	    /* Abort any outstanding requests */
	    for (j = 0; j < MAX_ASYNC_REQUESTS; j++) {
		uaecptr request;
		if ((request = dev->d_request[i]))
		    abort_async (dev, request, 0, 0);
	    }

	    /* Kill dev thread and wait for it to die */
	    write_comm_pipe_u32 (&dev->requests, 0, 1);
	    uae_sem_wait (&dev->sync_sem);

	    /* Close device */
	    dev->opencnt = 0;
	    sys_command_close (DF_SCSI, dev->unitnum);
	    sys_command_close (DF_IOCTL, dev->unitnum);
	}
	memset (dev, 0, sizeof (struct devstruct));
	dev->unitnum = dev->aunit = -1;
    }
}
Beispiel #9
0
void uae_ReplyMsg(uaecptr msg)
{
    write_comm_pipe_int (&native2amiga_pending, 2, 0);
    write_comm_pipe_u32 (&native2amiga_pending, msg, 1);

    uae_int_requested = 1;
}
Beispiel #10
0
void uae_Signal(uaecptr task, uae_u32 mask)
{
    write_comm_pipe_int (&native2amiga_pending, 0, 0);
    write_comm_pipe_u32 (&native2amiga_pending, task, 0);
    write_comm_pipe_int (&native2amiga_pending, mask, 1);
    
    uae_int_requested = 1;
}
Beispiel #11
0
void uae_Cause (uaecptr interrupt)
{
	uae_sem_wait (&n2asem);
	write_comm_pipe_int (&native2amiga_pending, 3, 0);
	write_comm_pipe_u32 (&native2amiga_pending, interrupt, 1);
	do_uae_int_requested ();
	uae_sem_post (&n2asem);
}
Beispiel #12
0
void graphics_subshutdown(void)
{
	if(display_tid != 0) {
		wait_for_display_thread();
		write_comm_pipe_u32(display_pipe, DISPLAY_SIGNAL_SUBSHUTDOWN, 1);
	  uae_sem_wait (&display_sem);
	}
}
Beispiel #13
0
void uae_ReplyMsg(uaecptr msg)
{
	uae_nativesem_wait();
  write_comm_pipe_int (&native2amiga_pending, 2, 0);
  write_comm_pipe_u32 (&native2amiga_pending, msg, 1);
  do_uae_int_requested();
	uae_nativesem_post();
}
Beispiel #14
0
static uae_u32 REGPARAM2 dev_beginio (TrapContext *context)
{
	uae_u32 request = m68k_areg (regs, 1);
	uae_u8 flags = get_byte (request + 30);
	int command = get_word (request + 28);
	struct priv_s2devstruct *pdev = getps2devstruct (request);
	struct s2devstruct *dev;

	put_byte (request + 8, NT_MESSAGE);
	if (!pdev) {
		write_log (_T("%s unknown iorequest (1) %08x\n"), getdevname (), request);
		put_byte (request + 31, 32);
		return get_byte (request + 31);
	}
	dev = gets2devstruct (pdev->unit);
	if (!dev) {
		write_log (_T("%s unknown iorequest (2) %08x\n"), getdevname (), request);
		put_byte (request + 31, 32);
		return get_byte (request + 31);
	}
	put_byte (request + 31, 0);
	if ((flags & 1) && dev_canquick (dev, request)) {
		if (dev_do_io (dev, request, 1))
			write_log (_T("%s: command %d bug with IO_QUICK\n"), SANA2NAME, command);
		return get_byte (request + 31);
	} else {
		if (command == CMD_WRITE || command == S2_BROADCAST || command == S2_MULTICAST) {
			struct s2packet *s2p;
			if (!pdev->copyfrombuff || !pdev->copytobuff) {
				put_long (request + 32, S2ERR_BAD_ARGUMENT);
				put_byte (request + 31, S2WERR_BUFF_ERROR);
			} else {
				if (command == S2_BROADCAST) {
					uaecptr dstaddr = request + 32 + 4 + 4 + SANA2_MAX_ADDR_BYTES;
					put_byte (dstaddr +  0, 0xff);
					put_byte (dstaddr +  1, 0xff);
					put_byte (dstaddr +  2, 0xff);
					put_byte (dstaddr +  3, 0xff);
					put_byte (dstaddr +  4, 0xff);
					put_byte (dstaddr +  5, 0xff);
				}
				s2p = createwritepacket (context, request);
				if (s2p) {
					uae_sem_wait (&async_sem);
					add_async_packet (dev, s2p, request);
					uae_sem_post (&async_sem);
				}
				if (!s2p) {
					put_long (request + 32, S2WERR_BUFF_ERROR);
					put_byte (request + 31, S2ERR_NO_RESOURCES);
				}
			}
		}
		put_byte (request + 30, get_byte (request + 30) & ~1);
		write_comm_pipe_u32 (&dev->requests, request, 1);
		return 0;
	}
}
Beispiel #15
0
void show_screen(int mode)
{
  unsigned long start = read_processor_time();

  last_synctime = start;
  while(last_synctime < next_amiga_frame_ends && last_synctime < start + time_per_frame) {
    usleep(10);
    last_synctime = read_processor_time();
  }
  amiga_frame = amiga_frame + 1 + currprefs.gfx_framerate;

  if(amiga_frame == currVSyncRate) {
    bool do_check = true;
    if(host_frame < host_hz) {
      // we are here before relevant vsync occured
      wait_for_vsync();
      if(sync_was_bogus)
        do_check = false;
    }
    if(do_check && host_frame == host_hz) {
      // Check time difference between Amiga and host sync.
      // If difference is too big, slightly ajust time per frame.
      long diff;
      static long last_diff = 0;
      if(next_amiga_frame_ends > host_frame_timestamp) {
        diff = next_amiga_frame_ends - host_frame_timestamp;
        if(diff > 50 && last_diff != 0 && diff > last_diff)
          time_per_frame--;
        last_diff = diff;
      } else {
        diff = host_frame_timestamp - next_amiga_frame_ends;
        if(diff > time_per_frame / 2) {
          next_amiga_frame_ends += time_per_frame;
          diff = -diff;
          last_diff = 0;
        } else {
          diff = -diff;
          if(diff < -50 && last_diff != 0 && diff < last_diff)
            time_per_frame++;
          last_diff = diff;
        }
      }
      write_log("Diff Amiga frame to host: %6d, time_per_frame = %6d\n", diff, time_per_frame);
    }
    host_frame = 0;
    amiga_frame = 0;
  }
  
  next_amiga_frame_ends += time_per_frame;
  if(currprefs.gfx_framerate)
    next_amiga_frame_ends += time_per_frame;
    
	wait_for_display_thread();
	write_comm_pipe_u32(display_pipe, DISPLAY_SIGNAL_SHOW, 1);

  idletime += last_synctime - start;
}
Beispiel #16
0
void uae_Signal (uaecptr task, uae_u32 mask)
{
	uae_sem_wait (&n2asem);
	write_comm_pipe_int (&native2amiga_pending, 0, 0);
	write_comm_pipe_u32 (&native2amiga_pending, task, 0);
	write_comm_pipe_int (&native2amiga_pending, mask, 1);
	do_uae_int_requested ();
	uae_sem_post (&n2asem);
}
Beispiel #17
0
static void signalasync (struct s2devstruct *dev, struct asyncreq *ar, int actual, int err)
{
	uaecptr request = ar->request;
	int command = get_word (request + 28);
	if (log_net)
		write_log (_T("%s:%d CMD=%d async request %x completed\n"), getdevname(), dev->unit, command, request);
	put_long (request + 32, actual);
	put_byte (request + 31, err);
	ar->ready = 1;
	write_comm_pipe_u32 (&dev->requests, request, 1);
}
Beispiel #18
0
static void cdtvcr_4510_do_something(void)
{
	if (cdtvcr_4510_ram[CDTVCR_INTACK]) {
		cdtvcr_4510_ram[CDTVCR_INTACK] = 0;
		rethink_cdtvcr();
	}
	if (cdtvcr_4510_ram[CDTVCR_CD_CMD_DO]) {
		cdtvcr_4510_ram[CDTVCR_CD_CMD_DO] = 0;
		cdtvcr_4510_ram[CDTVCR_SYS_STATE] |= 2;
		write_comm_pipe_u32 (&requests, 0x0100, 1);
	}
}
Beispiel #19
0
static void dev_close_3 (struct devstruct *dev, struct priv_devstruct *pdev)
{
    if (!dev->opencnt) return;
    dev->opencnt--;
    if (!dev->opencnt) {
	if (pdev->scsi)
	    sys_command_close (DF_SCSI, dev->unitnum);
	if (pdev->ioctl)
	    sys_command_close (DF_IOCTL, dev->unitnum);
	pdev->inuse = 0;
	write_comm_pipe_u32 (&dev->requests, 0, 1);
    }
}
Beispiel #20
0
static void abort_async (struct devstruct *dev, uaecptr request)
{
	struct asyncreq *ar = get_async_request (dev, request, 1);
	if (!ar) {
		write_log (_T("%s:%d: abort async but no request %x found!\n"), getdevname(), dev->unit, request);
		return;
	}
	if (log_uaeserial)
		write_log (_T("%s:%d asyncronous request=%08X aborted\n"), getdevname(), dev->unit, request);
	put_byte (request + 31, IOERR_ABORTED);
	put_byte (request + 30, get_byte (request + 30) | 0x20);
	write_comm_pipe_u32 (&dev->requests, request, 1);
}
Beispiel #21
0
void graphics_thread_leave(void)
{
	if(display_tid != 0) {
	  write_comm_pipe_u32 (display_pipe, DISPLAY_SIGNAL_QUIT, 1);
	  while(display_tid != 0) {
	    sleep_millis(10);
	  }
	  destroy_comm_pipe(display_pipe);
	  xfree(display_pipe);
	  display_pipe = 0;
	  uae_sem_destroy(&display_sem);
	  display_sem = 0;
	}
}
Beispiel #22
0
int graphics_setup(void)
{
#ifdef PICASSO96
	picasso_InitResolutions();
	InitPicasso96();
#endif
  VCHI_INSTANCE_T vchi_instance;
  VCHI_CONNECTION_T *vchi_connection;
  TV_DISPLAY_STATE_T tvstate;

  if(vchi_initialise(&vchi_instance) == 0) {
    if(vchi_connect(NULL, 0, vchi_instance) == 0) {
      vc_vchi_tv_init(vchi_instance, &vchi_connection, 1);
      if(vc_tv_get_display_state(&tvstate) == 0) {
        HDMI_PROPERTY_PARAM_T property;
        property.property = HDMI_PROPERTY_PIXEL_CLOCK_TYPE;
        vc_tv_hdmi_get_property(&property);
        float frame_rate = property.param1 == HDMI_PIXEL_CLOCK_TYPE_NTSC ? tvstate.display.hdmi.frame_rate * (1000.0f/1001.0f) : tvstate.display.hdmi.frame_rate;
        host_hz = (int)frame_rate;
        time_per_host_frame = time_for_host_hz_frames / host_hz;
      }
      vc_vchi_tv_stop();
      vchi_disconnect(vchi_instance);
    }
  }

  if(display_pipe == 0) {
    display_pipe = xmalloc (smp_comm_pipe, 1);
    init_comm_pipe(display_pipe, 20, 1);
  }
  if(display_sem == 0) {
    uae_sem_init (&display_sem, 0, 0);
  }
  if(display_tid == 0 && display_pipe != 0 && display_sem != 0) {
    uae_start_thread(_T("render"), display_thread, NULL, &display_tid);
  }
	write_comm_pipe_u32(display_pipe, DISPLAY_SIGNAL_SETUP, 1);
	
	return 1;
}
Beispiel #23
0
static uint32_t REGPARAM2 dev_beginio (TrapContext *context)
{
	uint32_t request = m68k_areg (regs, 1);
	uint8_t flags = get_byte (request + 30);
	int32_t command = get_word (request + 28);
	struct devstruct *dev = getdevstruct (get_long (request + 24));

	put_byte (request + 8, NT_MESSAGE);
	if (!dev) {
		put_byte (request + 31, 32);
		return get_byte (request + 31);
	}
	put_byte (request + 31, 0);
	if ((flags & 1) && dev_canquick (dev, request)) {
		if (dev_do_io (dev, request, 1))
			write_log (_T("device %s:%d command %d bug with IO_QUICK\n"), getdevname(), dev->unit, command);
		return get_byte (request + 31);
	} else {
		put_byte (request + 30, get_byte (request + 30) & ~1);
		write_comm_pipe_u32 (&dev->requests, request, 1);
		return 0;
	}
}
Beispiel #24
0
static uae_u32 REGPARAM2 dev_close_2 (TrapContext *context)
{
	uae_u32 request = m68k_areg (regs, 1);
	struct priv_s2devstruct *pdev = getps2devstruct (request);
	struct s2devstruct *dev;

	if (!pdev) {
		write_log (_T("%s close with unknown request %08X!?\n"), SANA2NAME, request);
		return 0;
	}
	dev = gets2devstruct (pdev->unit);
	if (!dev) {
		write_log (_T("%s:%d close with unknown request %08X!?\n"), SANA2NAME, pdev->unit, request);
		return 0;
	}
	if (log_net)
		write_log (_T("%s:%d close, open=%d req=%08X\n"), SANA2NAME, pdev->unit, dev->opencnt, request);
	put_long (request + 24, 0);
	dev->opencnt--;
	pdev->inuse = 0;
	if (!dev->opencnt) {
		dev->exclusive = 0;
		if (pdev->tempbuf) {
			m68k_areg (regs, 1) = pdev->tempbuf;
			m68k_dreg (regs, 0) = pdev->td->mtu + ETH_HEADER_SIZE + 2;
			CallLib (context, get_long (4), -0xD2); /* FreeMem */
			pdev->tempbuf = 0;
		}
		ethernet_close (pdev->td, dev->sysdata);
		xfree (dev->sysdata);
		dev->sysdata = NULL;
		write_comm_pipe_u32 (&dev->requests, 0, 1);
		write_log (_T("%s: opencnt == 0, all instances closed\n"), SANA2NAME);
	}
	put_word (m68k_areg (regs, 6) + 32, get_word (m68k_areg (regs, 6) + 32) - 1);
	return 0;
}
Beispiel #25
0
static uae_u32 REGPARAM2 uaenet_int_handler (TrapContext *ctx)
{
	int i, j;
	int gotit;
	struct asyncreq *ar;

	if (uae_sem_trywait (&async_sem)) {
		uaenet_int_requested = 0;
		uaenet_int_late = 1;
		return 0;
	}
	for (i = 0; i < MAX_OPEN_DEVICES; i++)
		pdevst[i].tmp = 0;

	for (i = 0; i < MAX_TOTAL_NET_DEVICES; i++) {
		struct s2devstruct *dev = &devst[i];
		struct s2packet *p;
		if (dev->online) {
			while (dev->readqueue) {
				uae_u16 type;
				p = dev->readqueue;
				type = (p->data[2 * ADDR_SIZE] << 8) | p->data[2 * ADDR_SIZE + 1];
				ar = dev->ar;
				gotit = 0;
				while (ar) {
					if (!ar->ready) {
						uaecptr request = ar->request;
						int command = get_word (request + 28);
						uae_u32 packettype = get_long (request + 32 + 4);
						if (command == CMD_READ && (packettype == type || (packettype <= 1500 && type <= 1500))) {
							struct priv_s2devstruct *pdev = getps2devstruct (request);
							if (pdev && pdev->tmp == 0) {
								if (handleread (ctx, pdev, request, p->data, p->len, command)) {
									if (log_net)
										write_log (_T("-> %p Accepted, CMD_READ, REQ=%08X LEN=%d\n"), p, request, p->len);
									ar->ready = 1;
									write_comm_pipe_u32 (&dev->requests, request, 1);
									dev->packetsreceived++;
									gotit = 1;
									pdev->tmp = 1;
								} else {
									if (log_net)
										write_log (_T("-> %p PacketFilter() rejected, CMD_READ, REQ=%08X LEN=%d\n"), p, request, p->len);
									pdev->tmp = -1;
								}
							}
						}
					}
					ar = ar->next;
				}
				ar = dev->ar;
				while (ar) {
					if (!ar->ready) {
						uaecptr request = ar->request;
						int command = get_word (request + 28);
						if (command == S2_READORPHAN) {
							struct priv_s2devstruct *pdev = getps2devstruct (request);
							if (pdev && pdev->tmp <= 0) {
								if (log_net)
									write_log (_T("-> %p Accepted, S2_READORPHAN, REQ=%08X LEN=%d\n"), p, request, p->len);
								handleread (ctx, pdev, request, p->data, p->len, command);
								ar->ready = 1;
								write_comm_pipe_u32 (&dev->requests, request, 1);
								dev->packetsreceived++;
								dev->unknowntypesreceived++;
								gotit = 1;
								pdev->tmp = 1;
							}
						}
					}
					ar = ar->next;
				}
				if (!gotit) {
					if (log_net)
						write_log (_T("-> %p packet dropped, LEN=%d\n"), p, p->len);
					for (j = 0; j < MAX_OPEN_DEVICES; j++) {
						if (pdevst[j].unit == dev->unit) {
							if (pdevst[j].tracks[type])
								pdevst[j].packetsdropped++;
						}
					}
				}
				dev->readqueue = dev->readqueue->next;
				freepacket (p);
			}
		} else {
			while (dev->readqueue) {
				p = dev->readqueue;
				dev->readqueue = dev->readqueue->next;
				freepacket (p);
			}
		}

		ar = dev->ar;
		while (ar) {
			if (!ar->ready) {
				uaecptr request = ar->request;
				int command = get_word (request + 28);
				if (command == S2_ONLINE) {
					struct priv_s2devstruct *pdev = getps2devstruct (request);
					dev->packetsreceived = 0;
					dev->packetssent = 0;
					dev->baddata = 0;
					dev->overruns = 0;
					dev->unknowntypesreceived = 0;
					dev->reconfigurations = 0;
					if (pdev && pdev->timerbase) {
						m68k_areg (regs, 0) = pdev->tempbuf;
						CallLib (ctx, pdev->timerbase, -0x42); /* GetSysTime() */
					} else {
						put_long (pdev->tempbuf + 0, 0);
						put_long (pdev->tempbuf + 4, 0);
					}
					dev->online_secs = get_long (pdev->tempbuf + 0);
					dev->online_micro = get_long (pdev->tempbuf + 4);
					checkevents (dev, S2EVENT_ONLINE, 0);
					dev->online = 1;
					ar->ready = 1;
					write_comm_pipe_u32 (&dev->requests, request, 1);
					uaenet_vsync_requested--;
				} else if (command == CMD_FLUSH) {
					/* do not reply CMD_FLUSH until all other requests are gone */
					if (dev->ar->next == NULL) {
						if (log_net)
							write_log (_T("CMD_FLUSH replied %08x\n"), request);
						ar->ready = 1;
						write_comm_pipe_u32 (&dev->requests, request, 1);
						uaenet_vsync_requested--;
					} else {
						struct priv_s2devstruct *pdev = getps2devstruct (request);
						if (pdev) {
							dev->flush_timeout--;
							if (dev->flush_timeout <= 0) {
								dev->flush_timeout = FLUSH_TIMEOUT;
								if (dev->flush_timeout_cnt > 1)
									write_log (_T("WARNING: %s:%d CMD_FLUSH possibly frozen..\n"), getdevname(), pdev->unit);
								dev->flush_timeout_cnt++;
								flush (pdev);
							}
						}
					}
				}
			}
			ar = ar->next;
		}
	}
	if (uaenet_int_late)
		uaenet_int_requested = 1;
	else
		uaenet_int_requested = 0;
	uaenet_int_late = 0;
	uae_sem_post (&async_sem);
	return 0;
}
Beispiel #26
0
static void *cdda_play_func (void *v)
{
	int cdda_pos;
	int num_sectors = CDDA_BUFFERS;
	int quit = 0;
	int bufnum;
	int bufon[2];
	int oldplay;
	int idleframes;
	bool foundsub;
	struct cdunit *cdu = (struct cdunit*)v;

	while (cdu->cdda_play == 0)
		Sleep (10);
	oldplay = -1;

	bufon[0] = bufon[1] = 0;
	bufnum = 0;

	cda_audio *cda = new cda_audio (num_sectors);

	while (cdu->cdda_play > 0) {

		if (oldplay != cdu->cdda_play) {
			struct cdtoc *t;
			int sector, diff;
			struct _timeb tb1, tb2;

			idleframes = 0;
			foundsub = false;
			_ftime (&tb1);
			cdda_pos = cdu->cdda_start;
			oldplay = cdu->cdda_play;
			sector = cdu->cd_last_pos = cdda_pos;
			t = findtoc (cdu, &sector);
			if (!t) {
				write_log (_T("IMAGE CDDA: illegal sector number %d\n"), cdu->cdda_start);
				setstate (cdu, AUDIO_STATUS_PLAY_ERROR);
			} else {
				write_log (_T("IMAGE CDDA: playing from %d to %d, track %d ('%s', offset %lld, secoffset %d)\n"),
					cdu->cdda_start, cdu->cdda_end, t->track, t->fname, t->offset, sector);
				// do this even if audio is not compressed, t->handle also could be
				// compressed and we want to unpack it in background too
				while (cdimage_unpack_active == 1)
					Sleep (10);
				cdimage_unpack_active = 0;
				write_comm_pipe_u32 (&unpack_pipe, cdu - &cdunits[0], 0);
				write_comm_pipe_u32 (&unpack_pipe, t - &cdu->toc[0], 1);
				while (cdimage_unpack_active == 0)
					Sleep (10);
			}
			idleframes = cdu->cdda_delay_frames;
			while (cdu->cdda_paused && cdu->cdda_play > 0) {
				Sleep (10);
				idleframes = -1;
			}

			if (cdu->cdda_scan == 0) {
				// find possible P-subchannel=1 and fudge starting point so that
				// buggy CD32/CDTV software CD+G handling does not miss any frames
				bool seenindex = false;
				for (sector = cdda_pos - 200; sector < cdda_pos; sector++) {
					int sec = sector;
					t = findtoc (cdu, &sec);
					if (t) {
						uae_u8 subbuf[SUB_CHANNEL_SIZE];
						getsub_deinterleaved (subbuf, cdu, t, sector);
						if (seenindex) {
							for (int i = 2 * SUB_ENTRY_SIZE; i < SUB_CHANNEL_SIZE; i++) {
								if (subbuf[i]) { // non-zero R-W subchannels
									int diff = cdda_pos - sector + 2;
									write_log (_T("-> CD+G start pos fudge -> %d (%d)\n"), sector, -diff);
									idleframes -= diff;
									cdda_pos = sector;
									break;
								}
							}
						} else if (subbuf[0] == 0xff) { // P == 1?
							seenindex = true;
						}
					}
				}
			}
			cdda_pos -= idleframes;

			_ftime (&tb2);
			diff = (tb2.time * (uae_s64)1000 + tb2.millitm) - (tb1.time * (uae_s64)1000 + tb1.millitm);
			diff -= cdu->cdda_delay;
			if (idleframes >= 0 && diff < 0 && cdu->cdda_play > 0)
				Sleep (-diff);
			setstate (cdu, AUDIO_STATUS_IN_PROGRESS);
		}

		cda->wait(bufnum);
		bufon[bufnum] = 0;
		if (!cdu->cdda_play)
			goto end;

		if (idleframes <= 0 && cdda_pos >= cdu->cdda_start && !isaudiotrack (&cdu->di.toc, cdda_pos)) {
			setstate (cdu, AUDIO_STATUS_PLAY_ERROR);
			write_log (_T("IMAGE CDDA: attempted to play data track %d\n"), cdda_pos);
			goto end; // data track?
		}

		if ((cdda_pos < cdu->cdda_end || cdu->cdda_end == 0xffffffff) && !cdu->cdda_paused && cdu->cdda_play > 0) {
			struct cdtoc *t;
			int sector, cnt;
			int dofinish = 0;

			gui_flicker_led (LED_CD, cdu->di.unitnum - 1, LED_CD_AUDIO);

			memset (cda->buffers[bufnum], 0, num_sectors * 2352);

			for (cnt = 0; cnt < num_sectors; cnt++) {
				uae_u8 *dst = cda->buffers[bufnum] + cnt * 2352;
				uae_u8 subbuf[SUB_CHANNEL_SIZE];
				sector = cdda_pos;

				memset (subbuf, 0, SUB_CHANNEL_SIZE);

				t = findtoc (cdu, &sector);
				if (t) {
					if (!(t->ctrl & 4)) {
						if (t->enctype == ENC_CHD) {
							do_read (cdu, t, dst, sector, 0, t->size);
							for (int i = 0; i < 2352; i+=2) {
								uae_u8 p;
								p = dst[i + 0];
								dst[i + 0] = dst[i + 1];
								dst[i +1] = p;
							}
						} else if (t->handle) {
							int totalsize = t->size + t->skipsize;
							if ((t->enctype == AUDENC_MP3 || t->enctype == AUDENC_FLAC) && t->data) {
								if (t->filesize >= sector * totalsize + t->offset + t->size)
									memcpy (dst, t->data + sector * totalsize + t->offset, t->size);
							} else if (t->enctype == AUDENC_PCM) {
								if (sector * totalsize + t->offset + totalsize < t->filesize) {
									zfile_fseek (t->handle, (uae_u64)sector * totalsize + t->offset, SEEK_SET);
									zfile_fread (dst, t->size, 1, t->handle);
								}
							}
						}
					}
					getsub_deinterleaved (subbuf, cdu, t, cdda_pos);
				}

				if (idleframes > 0) {
					idleframes--;
					memset (dst, 0, 2352);
					memset (subbuf, 0, SUB_CHANNEL_SIZE);
				}

				if (cdda_pos < cdu->cdda_start && cdu->cdda_scan == 0)
					memset (dst, 0, 2352);

				dosub (cdu, subbuf);

				if (cdu->cdda_scan) {
					cdda_pos += cdu->cdda_scan;
					if (cdda_pos < 0)
						cdda_pos = 0;
				} else  {
					cdda_pos++;
				}

				if (cdda_pos - num_sectors < cdu->cdda_end && cdda_pos >= cdu->cdda_end)
					dofinish = 1;

			}
	
			if (idleframes <= 0)
				cdu->cd_last_pos = cdda_pos;

			bufon[bufnum] = 1;
			cda->setvolume (currprefs.sound_volume_cd >= 0 ? currprefs.sound_volume_cd : currprefs.sound_volume, cdu->cdda_volume[0], cdu->cdda_volume[1]);
			if (!cda->play (bufnum)) {
				setstate (cdu, AUDIO_STATUS_PLAY_ERROR);
				goto end;
			}

			if (dofinish) {
				setstate (cdu, AUDIO_STATUS_PLAY_COMPLETE);
				cdu->cdda_play = -1;
				cdda_pos = cdu->cdda_end + 1;
			}

		}

		if (bufon[0] == 0 && bufon[1] == 0) {
			while (cdu->cdda_paused && cdu->cdda_play == oldplay)
				Sleep (10);
		}

		bufnum = 1 - bufnum;
	}

end:
	cda->wait (0);
	cda->wait (1);

	while (cdimage_unpack_active == 1)
		Sleep (10);

	delete cda;

	cdu->cdda_play = 0;
	write_log (_T("IMAGE CDDA: thread killed\n"));
	return NULL;
}
Beispiel #27
0
void uaeser_signal (void *vdev, int32_t sigmask)
{
	struct devstruct *dev = (struct devstruct*)vdev;
	struct asyncreq *ar;
	int32_t i = 0;

	uae_sem_wait (&async_sem);
	ar = dev->ar;
	while (ar) {
		if (!ar->ready) {
			uaecptr request = ar->request;
			uint32_t io_data = get_long (request + 40); // 0x28
			uint32_t io_length = get_long (request + 36); // 0x24
			int32_t command = get_word (request + 28);
			uint32_t io_error = 0, io_actual = 0;
			uint8_t *addr;
			int32_t io_done = 0;

			switch (command)
			{
			case SDCMD_BREAK:
				if (ar == dev->ar) {
					uaeser_break (dev->sysdata,  get_long (request + io_BrkTime));
					io_done = 1;
				}
				break;
			case CMD_READ:
				if (sigmask & 1) {
					addr = memmap(io_data, io_length);
					if (addr) {
						if (uaeser_read (dev->sysdata, addr, io_length)) {
							io_error = 0;
							io_actual = io_length;
							io_done = 1;
						}
					} else {
						io_error = IOERR_BADADDRESS;
						io_done = 1;
					}
				}
				break;
			case CMD_WRITE:
				if (sigmask & 2) {
					io_error = IOERR_BADADDRESS;
					addr = memmap(io_data, io_length);
					if (addr && uaeser_write (dev->sysdata, addr, io_length))
						io_error = 0;
					io_actual = io_length;
					io_done = 1;
				}
				break;
			default:
				write_log (_T("%s:%d incorrect async request %x (cmd=%d) signaled?!"), getdevname(), dev->unit, request, command);
				break;
			}

			if (io_done) {
				if (log_uaeserial)
					write_log (_T("%s:%d async request %x completed\n"), getdevname(), dev->unit, request);
				put_long (request + 32, io_actual);
				put_byte (request + 31, io_error);
				ar->ready = 1;
				write_comm_pipe_u32 (&dev->requests, request, 1);
			}

		}
		ar = ar->next;
	}
	uae_sem_post (&async_sem);
}