Ejemplo n.º 1
0
void updatescreen(void)
{
	/* update sound */
	sound_frame_update();

	/* if we're not skipping this frame, draw the screen */
	if (!osd_skip_this_frame())
	{
		profiler_mark(PROFILER_VIDEO);
		draw_screen();
		profiler_mark(PROFILER_END);
	}

	/* the user interface must be called between vh_update() and osd_update_video_and_audio(), */
	/* to allow it to overlay things on the game display. We must call it even */
	/* if the frame is skipped, to keep a consistent timing. */
	ui_update_and_render(artwork_get_ui_bitmap());

	/* update our movie recording state */
	if (!mame_is_paused())
		record_movie_frame(scrbitmap[0]);

	/* blit to the screen */
	update_video_and_audio();

	/* call the end-of-frame callback */
	if (Machine->drv->video_eof && !mame_is_paused())
	{
		profiler_mark(PROFILER_VIDEO);
		(*Machine->drv->video_eof)();
		profiler_mark(PROFILER_END);
	}
}
Ejemplo n.º 2
0
void video_manager::frame_update(bool debug)
{
	// only render sound and video if we're in the running phase
	int phase = machine().phase();
	bool skipped_it = m_skipping_this_frame;
	if (phase == MACHINE_PHASE_RUNNING && (!machine().paused() || machine().options().update_in_pause()))
	{
		bool anything_changed = finish_screen_updates();

		// if none of the screens changed and we haven't skipped too many frames in a row,
        // mark this frame as skipped to prevent throttling; this helps for games that
        // don't update their screen at the monitor refresh rate
		if (!anything_changed && !m_auto_frameskip && m_frameskip_level == 0 && m_empty_skip_count++ < 3)
			skipped_it = true;
		else
			m_empty_skip_count = 0;
	}

	// draw the user interface
	ui_update_and_render(machine(), &machine().render().ui_container());

	// update the internal render debugger
	debugint_update_during_game(machine());

	// if we're throttling, synchronize before rendering
	attotime current_time = machine().time();
	if (!debug && !skipped_it && effective_throttle())
		update_throttle(current_time);

	// ask the OSD to update
	g_profiler.start(PROFILER_BLIT);
	machine().osd().update(!debug && skipped_it);
	g_profiler.stop();

	// perform tasks for this frame
	if (!debug)
		machine().call_notifiers(MACHINE_NOTIFY_FRAME);

	// update frameskipping
	if (!debug)
		update_frameskip();

	// update speed computations
	if (!debug && !skipped_it)
		recompute_speed(current_time);

	// call the end-of-frame callback
	if (phase == MACHINE_PHASE_RUNNING)
	{
		// reset partial updates if we're paused or if the debugger is active
		if (machine().primary_screen != NULL && (machine().paused() || debug || debugger_within_instruction_hook(machine())))
			machine().primary_screen->reset_partial_updates();
	}
}
Ejemplo n.º 3
0
void video_frame_update(void)
{
	int skipped_it = video_skip_this_frame();
	int paused = mame_is_paused(Machine);
	int phase = mame_get_phase(Machine);
	int livemask;
	int scrnum;

	/* only render sound and video if we're in the running phase */
	if (phase == MAME_PHASE_RUNNING)
	{
		/* update sound */
		sound_frame_update();

		/* finish updating the screens */
		for (scrnum = 0; scrnum < MAX_SCREENS; scrnum++)
			if (Machine->drv->screen[scrnum].tag != NULL)
				video_screen_update_partial(scrnum, Machine->screen[scrnum].visarea.max_y);

		/* now add the quads for all the screens */
		livemask = render_get_live_screens_mask();
		for (scrnum = 0; scrnum < MAX_SCREENS; scrnum++) {
			if (livemask & (1 << scrnum))
			{
				internal_screen_info *screen = &scrinfo[scrnum];

				/* only update if empty and not a vector game; otherwise assume the driver did it directly */
				if (render_container_is_empty(render_container_get_screen(scrnum)) && !(Machine->drv->video_attributes & VIDEO_TYPE_VECTOR))
				{
					mame_bitmap *bitmap = screen->bitmap[screen->curbitmap];
					if (!skipping_this_frame && screen->changed)
					{
						rectangle fixedvis = Machine->screen[scrnum].visarea;
						fixedvis.max_x++;
						fixedvis.max_y++;
						render_texture_set_bitmap(screen->texture, bitmap, &fixedvis, Machine->drv->screen[scrnum].palette_base, screen->format);
						screen->curbitmap = 1 - screen->curbitmap;
					}
					render_screen_add_quad(scrnum, 0.0f, 0.0f, 1.0f, 1.0f, MAKE_ARGB(0xff,0xff,0xff,0xff), screen->texture, PRIMFLAG_BLENDMODE(BLENDMODE_NONE) | PRIMFLAG_SCREENTEX(1));
				}
			}
        }

		/* update our movie recording state */
		if (!paused)
			movie_record_frame(0);

		/* reset the screen changed flags */
		for (scrnum = 0; scrnum < MAX_SCREENS; scrnum++)
			scrinfo[scrnum].changed = 0;
	}

	/* draw any crosshairs */
	crosshair_render();

	/* draw the user interface */
	ui_update_and_render();

	/* call the OSD to update */
	skipping_this_frame = osd_update(mame_timer_get_time());

	/* empty the containers */
	for (scrnum = 0; scrnum < MAX_SCREENS; scrnum++)
		if (Machine->drv->screen[scrnum].tag != NULL)
			render_container_empty(render_container_get_screen(scrnum));

	/* update FPS */
	recompute_fps(skipped_it);

	/* call the end-of-frame callback */
	if (phase == MAME_PHASE_RUNNING)
	{
		/* reset partial updates if we're paused or if the debugger is active */
		if (paused || mame_debug_is_active())
			video_reset_partial_updates();

		/* otherwise, call the video EOF callback */
		else if (Machine->drv->video_eof != NULL)
		{
			profiler_mark(PROFILER_VIDEO);
			(*Machine->drv->video_eof)(Machine);
			profiler_mark(PROFILER_END);
		}
	}
}
Ejemplo n.º 4
0
void Server::initialSync(const RakNet::SystemAddress &sa,running_machine *machine)
{
    unsigned char checksum = 0;

    waitingForClientCatchup=true;
    machine->osd().pauseAudio(true);

    int syncBytes;
    {
    RakNet::BitStream uncompressedStream;

    uncompressedStream.Write(startupTime);

    uncompressedStream.Write(globalCurtime);

    if(getSecondsBetweenSync())
    {
        while(memoryBlocksLocked)
        {
            ;
        }
        memoryBlocksLocked=true;
        cout << "IN CRITICAL SECTION\n";
        cout << "SERVER: Sending initial snapshot\n";

        int numBlocks = int(blocks.size());
        cout << "NUMBLOCKS: " << numBlocks << endl;
        uncompressedStream.Write(numBlocks);

        // NOTE: The server must send stale data to the client for the first time
        // So that future syncs will be accurate
        for(int blockIndex=0; blockIndex<int(initialBlocks.size()); blockIndex++)
        {
            //cout << "BLOCK SIZE FOR INDEX " << blockIndex << ": " << staleBlocks[blockIndex].size << endl;
            uncompressedStream.Write(initialBlocks[blockIndex].size);

            cout << "BLOCK " << blockIndex << ": ";
            for(int a=0; a<staleBlocks[blockIndex].size; a++)
            {
                checksum = checksum ^ staleBlocks[blockIndex].data[a];
                //cout << int(staleBlocks[blockIndex].data[a]) << ' ';
                unsigned char value = initialBlocks[blockIndex].data[a] ^ staleBlocks[blockIndex].data[a];
                uncompressedStream.WriteBits(&value,8);
            }
            cout << int(checksum) << endl;
        }
    }

    for(
        map<int,vector< string > >::iterator it = peerInputs.begin();
        it != peerInputs.end();
        it++
    )
    {
        uncompressedStream.Write(it->first);
        uncompressedStream.Write(int(oldPeerInputs[it->first].size()) + int(it->second.size()));
        for(int a=0; a<(int)it->second.size(); a++)
        {
            uncompressedStream.Write(int(it->second[a].length()));
            uncompressedStream.WriteBits((const unsigned char*)it->second[a].c_str(),it->second[a].length()*8);

            for(int b=0;b<it->second[a].length();b++)
            {
                checksum = checksum ^ it->second[a][b];
            }
        }
        for(int a=0; a<int(oldPeerInputs[it->first].size()); a++)
        {
            uncompressedStream.Write(int(oldPeerInputs[it->first][a].length()));
            uncompressedStream.WriteBits((const unsigned char*)oldPeerInputs[it->first][a].c_str(),oldPeerInputs[it->first][a].length()*8);

            for(int b=0;b<oldPeerInputs[it->first][a].length();b++)
            {
                checksum = checksum ^ oldPeerInputs[it->first][a][b];
            }
        }
    }
    uncompressedStream.Write(int(-1));
    uncompressedStream.Write(checksum);
    cout << "CHECKSUM: " << int(checksum) << endl;

    if(uncompressedBufferSize<uncompressedStream.GetNumberOfBytesUsed()+sizeof(int))
    {
        uncompressedBufferSize = uncompressedStream.GetNumberOfBytesUsed()+sizeof(int);
	free(uncompressedBuffer);
        uncompressedBuffer = (unsigned char*)malloc(uncompressedBufferSize);
        if(!uncompressedBuffer)
        {
            cout << __FILE__ << ":" << __LINE__ << " OUT OF MEMORY\n";
            exit(1);
        }
    }
    syncBytes = uncompressedStream.GetNumberOfBytesUsed();
    memcpy(uncompressedBuffer,uncompressedStream.GetData(),uncompressedStream.GetNumberOfBytesUsed());

    int uncompressedStateSize = (int)uncompressedStream.GetNumberOfBytesUsed();
    printf("INITIAL UNCOMPRESSED STATE SIZE: %d\n",uncompressedStateSize);
    }

    cout << "PUTTING NVRAM AT LOCATION " << syncBytes << endl;

	// open the file; if it exists, call everyone to read from it
	emu_file file(machine->options().nvram_directory(), OPEN_FLAG_READ);
	if (file.open(machine->basename(), ".nv") == FILERR_NONE && file.size()<=1024*1024*64) //Don't bother sending huge NVRAM's
    {
        int nvramSize = file.size();
        if(uncompressedBufferSize<syncBytes+sizeof(int)+nvramSize)
        {
            uncompressedBufferSize = syncBytes+sizeof(int)+nvramSize;
	    free(uncompressedBuffer);
            uncompressedBuffer = (unsigned char*)malloc(uncompressedBufferSize);
            if(!uncompressedBuffer)
            {
                cout << __FILE__ << ":" << __LINE__ << " OUT OF MEMORY\n";
                exit(1);
            }
        }
        cout << "SENDING NVRAM OF SIZE: " << nvramSize << endl;
        memcpy(uncompressedBuffer+syncBytes,&nvramSize,sizeof(int));
        file.read(uncompressedBuffer+syncBytes+sizeof(int),nvramSize);
        file.close();
        syncBytes += sizeof(int) + nvramSize;
    }
	else
	{
	    int dummy=0;
        memcpy(uncompressedBuffer+syncBytes,&dummy,sizeof(int));
        syncBytes += sizeof(int);
	}

    cout << "BYTES USED: " << syncBytes << endl;

    //The application should ensure that this value be at least (sourceLen 1.001) + 12.
    //JJG: Doing more than that to account for header and provide some padding
    //vector<unsigned char> compressedInitialSyncBuffer(
            //sizeof(int)*2 + lzmaGetMaxCompressedSize(uncompressedStream.GetNumberOfBytesUsed()), '\0');

    //JJG: Take a risk and assume the compressed size will be smaller than the uncompressed size
    int newCompressedSize = max(1024*1024,int(sizeof(int)*2 + lzmaGetMaxCompressedSize(syncBytes)));
    if(compressedBufferSize < newCompressedSize )
    {
        compressedBufferSize = newCompressedSize;
        cout << "NEW COMPRESSED BUFFER SIZE: " << compressedBufferSize << endl;
	free(compressedBuffer);
        compressedBuffer = (unsigned char*)malloc(compressedBufferSize);
        if(!compressedBuffer)
        {
            cout << __FILE__ << ":" << __LINE__ << " OUT OF MEMORY\n";
            exit(1);
        }
    }

    int compressedSizeLong = compressedBufferSize;

    //FILE *stateptr = fopen("initialState.dat","wb");
    //fwrite(uncompressedStream.GetData(),uncompressedStream.GetNumberOfBytesUsed(),1,stateptr);
    //fclose(stateptr);

    lzmaCompress(
        compressedBuffer+sizeof(int)+sizeof(int),
        compressedSizeLong,
        uncompressedBuffer,
        syncBytes,
        6
    );

    int uncompressedSize = (int)syncBytes;
    memcpy(compressedBuffer,&uncompressedSize,sizeof(int));

    int compressedSize = (int)compressedSizeLong;
    memcpy(compressedBuffer+sizeof(int),&compressedSize,sizeof(int));

    printf("INITIAL UNCOMPRESSED SIZE: %d\n",uncompressedSize);
    printf("INITIAL COMPRESSED SIZE: %d\n",compressedSize);

    /*
    rakInterface->Send(
    	(char*)(&compressedInitialSyncBuffer[0]),
    	compressedSize+1+sizeof(int),
    	HIGH_PRIORITY,
    	RELIABLE_ORDERED,
    	ORDERING_CHANNEL_SYNC,
    	guid,
    	false
           );
    */

    //
    unsigned char *sendPtr = compressedBuffer;
    int sizeRemaining = compressedSize+sizeof(int)+sizeof(int);
    printf("INITIAL COMPRESSED SIZE: %dKB\n",sizeRemaining/1024);
    int packetSize = max(256,min(1024,sizeRemaining/100));

    oldInputTime.seconds = oldInputTime.attoseconds = 0;

    while(sizeRemaining>packetSize)
    {
        RakNet::BitStream bitStreamPart(65536);
        unsigned char header = ID_INITIAL_SYNC_PARTIAL;
        bitStreamPart.WriteBits((const unsigned char*)&header,8*sizeof(unsigned char));
        bitStreamPart.WriteBits((const unsigned char*)sendPtr,8*packetSize);
        sizeRemaining -= packetSize;
        sendPtr += packetSize;
        rakInterface->Send(
            &bitStreamPart,
            HIGH_PRIORITY,
            RELIABLE_ORDERED,
            ORDERING_CHANNEL_SYNC,
            sa,
            false
        );
        ui_update_and_render(*machine, &machine->render().ui_container());
        machine->osd().update(false);
        RakSleep(10);
    }
    {
        RakNet::BitStream bitStreamPart(65536);
        unsigned char header = ID_INITIAL_SYNC_COMPLETE;
        bitStreamPart.WriteBits((const unsigned char*)&header,8*sizeof(unsigned char));
        bitStreamPart.WriteBits((const unsigned char*)sendPtr,8*sizeRemaining);
        rakInterface->Send(
            &bitStreamPart,
            HIGH_PRIORITY,
            RELIABLE_ORDERED,
            ORDERING_CHANNEL_SYNC,
            sa,
            false
        );
        ui_update_and_render(*machine, &machine->render().ui_container());
        machine->osd().update(false);
        RakSleep(10);
    }
    //

    cout << "FINISHED SENDING BLOCKS TO CLIENT\n";
    cout << "SERVER: Done with initial snapshot\n";
    cout << "OUT OF CRITICAL AREA\n";
    cout.flush();
    memoryBlocksLocked=false;
}