void* tick_th(void* p) { SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL); double old=os_GetSeconds(); for(;;) { Sleep(4); double newt=os_GetSeconds(); os_consume(newt-old); old=newt; } }
void WriteSample(s16 r, s16 l) { #if 0 #if HOST_OS==OS_WINDOWS #ifdef LOG_SOUND rawout.Write(l,r); #endif if (!asRingFreeCount()) { //printf("Buffer overrun\n"); if (settings.aica.LimitFPS) { //speed_limit.Wait(); } else return; } gen_samples++; //while limit on, 128 samples done, there is a buffer ready to be service AND speed is too fast then wait if (settings.aica.LimitFPS==1 && gen_samples>128) { for(;asRingUsedCount()>BufferSampleCount && (os_GetSeconds()-time_last)<=time_diff;) ; gen_samples=0; time_last=os_GetSeconds(); } #else if (!asRingFreeCount()) { if (settings.aica.LimitFPS) { while(!asRingFreeCount()) ; } else return; } #endif #endif const u32 ptr=(WritePtr+1)%RingBufferSampleCount; RingBuffer[ptr].r=r; RingBuffer[ptr].l=l; WritePtr=ptr; if (WritePtr==(SAMPLE_COUNT-1)) { os_Push(RingBuffer,SAMPLE_COUNT,settings.aica.LimitFPS); } }
bool QueueRender(TA_context* ctx) { verify(ctx != 0); if (FrameSkipping && frameskip) { frameskip=1-frameskip; tactx_Recycle(ctx); fskip++; return false; } //Try to limit speed to a "sane" level //Speed is also limited via audio, but audio //is sometimes not accurate enough (android, vista+) u32 cycle_span = sh4_sched_now64() - last_cyces; last_cyces = sh4_sched_now64(); double time_span = os_GetSeconds() - last_frame; last_frame = os_GetSeconds(); bool too_fast = (cycle_span / time_span) > (SH4_MAIN_CLOCK * 1.2); if (rqueue && too_fast && settings.pvr.SynchronousRender) { //wait for a frame if // we have another one queue'd and // sh4 run at > 120% on the last slice // and SynchronousRendering is enabled frame_finished.Wait(); verify(!rqueue); } if (rqueue) { tactx_Recycle(ctx); fskip++; return false; } frame_finished.Reset(); mtx_rqueue.Lock(); TA_context* old = rqueue; rqueue=ctx; mtx_rqueue.Unlock(); verify(!old); return true; }
//called from sh4 context , should update pvr/ta state and everything else int spg_line_sched(int tag, int cycl, int jit) { clc_pvr_scanline += cycl; while (clc_pvr_scanline >= Line_Cycles)//60 ~hertz = 200 mhz / 60=3333333.333 cycles per screen refresh { //ok .. here , after much effort , we did one line //now , we must check for raster beam interrupts and vblank prv_cur_scanline=(prv_cur_scanline+1)%pvr_numscanlines; clc_pvr_scanline -= Line_Cycles; //Check for scanline interrupts -- really need to test the scanline values if (SPG_VBLANK_INT.vblank_in_interrupt_line_number == prv_cur_scanline) asic_RaiseInterrupt(holly_SCANINT1); if (SPG_VBLANK_INT.vblank_out_interrupt_line_number == prv_cur_scanline) asic_RaiseInterrupt(holly_SCANINT2); if (SPG_VBLANK.vstart == prv_cur_scanline) in_vblank=1; if (SPG_VBLANK.vbend == prv_cur_scanline) in_vblank=0; SPG_STATUS.vsync=in_vblank; SPG_STATUS.scanline=prv_cur_scanline; //Vblank start -- really need to test the scanline values if (prv_cur_scanline==0) { if (SPG_CONTROL.interlace) SPG_STATUS.fieldnum=~SPG_STATUS.fieldnum; else SPG_STATUS.fieldnum=0; //Vblank counter vblk_cnt++; asic_RaiseInterrupt(holly_HBLank);// -> This turned out to be HBlank btw , needs to be emulated ;( //TODO : rend_if_VBlank(); rend_vblank();//notify for vblank :) if ((os_GetSeconds()-last_fps)>2) { static int Last_FC; double ts=os_GetSeconds()-last_fps; double spd_fps=(FrameCount-Last_FC)/ts; double spd_vbs=vblk_cnt/ts; double spd_cpu=spd_vbs*Frame_Cycles; spd_cpu/=1000000; //mrhz kthx double fullvbs=(spd_vbs/spd_cpu)*200; double mv=VertexCount/ts/(spd_cpu/200); char mv_c=' '; Last_FC=FrameCount; if (mv>750) { mv/=1000; //KV mv_c='K'; } if (mv>750) { mv/=1000; // mv_c='M'; } VertexCount=0; vblk_cnt=0; char fpsStr[256]; const char* mode=0; const char* res=0; res=SPG_CONTROL.interlace?"480i":"240p"; if (SPG_CONTROL.NTSC==0 && SPG_CONTROL.PAL==1) mode="PAL"; else if (SPG_CONTROL.NTSC==1 && SPG_CONTROL.PAL==0) mode="NTSC"; else { res=SPG_CONTROL.interlace?"480i":"480p"; mode="VGA"; } double frames_done=spd_cpu/2; double mspdf=1/frames_done*1000; full_rps=(spd_fps+fskip/ts); #ifdef TARGET_PANDORA sprintf(fpsStr,"CPU: %4.2f V: %4.2f (%s%s%4.2f) R: %4.2f+%4.2f", spd_cpu*100/200,spd_vbs, mode,res,fullvbs, spd_fps,fskip/ts); #else sprintf(fpsStr,"%s/%c - %4.2f (%4.2f) - %4.2f - V: %4.2f (%.2f, %s%s%4.2f) R: %4.2f+%4.2f VTX: %4.2f%c", VER_SHORTNAME,'n',mspdf,speed_load_mspdf,spd_cpu*100/200,spd_vbs, spd_vbs/full_rps,mode,res,fullvbs, spd_fps,fskip/ts ,mv,mv_c); #endif fskip=0; os_SetWindowText(fpsStr); last_fps=os_GetSeconds(); } } } //interrupts //0 //vblank_in_interrupt_line_number //vblank_out_interrupt_line_number //vstart //vbend //pvr_numscanlines u32 min_scanline=prv_cur_scanline+1; u32 min_active=pvr_numscanlines; if (min_scanline<SPG_VBLANK_INT.vblank_in_interrupt_line_number) min_active=min(min_active,SPG_VBLANK_INT.vblank_in_interrupt_line_number); if (min_scanline<SPG_VBLANK_INT.vblank_out_interrupt_line_number) min_active=min(min_active,SPG_VBLANK_INT.vblank_out_interrupt_line_number); if (min_scanline<SPG_VBLANK.vstart) min_active=min(min_active,SPG_VBLANK.vstart); if (min_scanline<SPG_VBLANK.vbend) min_active=min(min_active,SPG_VBLANK.vbend); if (min_scanline<pvr_numscanlines) min_active=min(min_active,pvr_numscanlines); min_active=max(min_active,min_scanline); return (min_active-prv_cur_scanline)*Line_Cycles; }
void webui_start() { char cert_path[1024]; char key_path[1024]; int n = 0; int use_ssl = 0; int opts = 0; char interface_name[128] = ""; const char *iface = NULL; #ifndef WIN32 int syslog_options = LOG_PID | LOG_PERROR; #endif struct lws_context_creation_info info; int debug_level = 7; #ifndef LWS_NO_DAEMONIZE int daemonize = 0; #endif memset(&info, 0, sizeof info); info.port = 5678; const string path = WEBUI_PATH; const char* resource_path = path.c_str(); #ifndef WIN32 /* we will only try to log things according to our debug_level */ setlogmask(LOG_UPTO (LOG_DEBUG)); openlog("lwsts", syslog_options, LOG_DAEMON); #endif /* tell the library what debug level to emit and to send it to syslog */ lws_set_log_level(debug_level, lwsl_emit_syslog); lwsl_notice("libwebsockets test server - " "(C) Copyright 2010-2013 Andy Green <*****@*****.**> - " "licensed under LGPL2.1\n"); #ifdef EXTERNAL_POLL max_poll_elements = getdtablesize(); pollfds = malloc(max_poll_elements * sizeof (struct pollfd)); fd_lookup = malloc(max_poll_elements * sizeof (int)); if (pollfds == NULL || fd_lookup == NULL) { lwsl_err("Out of memory pollfds=%d\n", max_poll_elements); return -1; } #endif info.iface = iface; info.protocols = protocols; #ifndef LWS_NO_EXTENSIONS info.extensions = libwebsocket_get_internal_extensions(); #endif if (!use_ssl) { info.ssl_cert_filepath = NULL; info.ssl_private_key_filepath = NULL; } else { if (strlen(resource_path) > sizeof(cert_path) - 32) { lwsl_err("resource path too long\n"); return ; } sprintf(cert_path, "%s/libwebsockets-test-server.pem", resource_path); if (strlen(resource_path) > sizeof(key_path) - 32) { lwsl_err("resource path too long\n"); return; } sprintf(key_path, "%s/libwebsockets-test-server.key.pem", resource_path); info.ssl_cert_filepath = cert_path; info.ssl_private_key_filepath = key_path; } info.gid = -1; info.uid = -1; info.options = opts; context = libwebsocket_create_context(&info); if (context == NULL) { lwsl_err("libwebsocket init failed\n"); return ; } n = 0; double old_time = 0; while (n >= 0 && !force_exit) { double time = os_GetSeconds(); /* * This provokes the LWS_CALLBACK_SERVER_WRITEABLE for every * live websocket connection using the DUMB_INCREMENT protocol, * as soon as it can take more packets (usually immediately) */ if ((time - old_time ) > 0.050) { libwebsocket_callback_on_writable_all_protocol(&protocols[PROTOCOL_DUMB_INCREMENT]); old_time = time; } #ifdef EXTERNAL_POLL /* * this represents an existing server's single poll action * which also includes libwebsocket sockets */ n = poll(pollfds, count_pollfds, 50); if (n < 0) continue; if (n) for (n = 0; n < count_pollfds; n++) if (pollfds[n].revents) /* * returns immediately if the fd does not * match anything under libwebsockets * control */ if (libwebsocket_service_fd(context, &pollfds[n]) < 0) goto done; #else /* * If libwebsockets sockets are all we care about, * you can use this api which takes care of the poll() * and looping through finding who needed service. * * If no socket needs service, it'll return anyway after * the number of ms in the second argument. */ n = libwebsocket_service(context, 50); #endif } #ifdef EXTERNAL_POLL done: #endif libwebsocket_context_destroy(context); lwsl_notice("libwebsockets-test-server exited cleanly\n"); #ifndef WIN32 closelog(); #endif return; }