/* * usbrecords_update * @param[elapsed] elapsed time * @ret 0 - success, -1 error */ int usbrecords_update(int elapsed) { recovery_entry_t *item; recovery_entry_t *tmp_item; LTRACEF("Update records\n"); platform_mutex_lock(&recovery_lock); /* check all entries */ for (item = TAILQ_FIRST(&t_recovery_queue); item != NULL; item = tmp_item) { tmp_item = TAILQ_NEXT(item, entries); /* update remaining recovery time */ item->timeout -= elapsed; PTRACEF(USB_RECOVERY, "Check entry(%p): timeout %d\n", item, item->timeout); /* expired? */ if(item->timeout < 0) { TRACEF("expired timeout::destroy record\n"); /* destroy handle */ novacom_usbll_destroy((novacom_usbll_handle_t)item->t_token->user_data); /* Remove the item from queue. */ TAILQ_REMOVE(&t_recovery_queue, item, entries); /* Free the item as we don't need it anymore. */ platform_free(item->t_token); platform_free(item); } } platform_mutex_unlock(&recovery_lock); return 0; }
/* * usbrecords_remove * @param[nduid] device nduid * @ret 0 - success, -1 error */ int usbrecords_remove(char *nduid) { recovery_entry_t *item; recovery_entry_t *tmp_item; LTRACEF("Update records\n"); platform_mutex_lock(&recovery_lock); /* check all entries */ for (item = TAILQ_FIRST(&t_recovery_queue); item != NULL; item = tmp_item) { tmp_item = TAILQ_NEXT(item, entries); if(0 == strncmp(item->t_token->nduid, nduid, sizeof(item->t_token->nduid)) ) { TRACEF("explicit remove::nduid(%s)\n", nduid); /* destroy handle */ novacom_usbll_destroy((novacom_usbll_handle_t)item->t_token->user_data); /* Remove the item from queue. */ TAILQ_REMOVE(&t_recovery_queue, item, entries); /* Free the item as we don't need it anymore. */ platform_free(item->t_token); platform_free(item); } } platform_mutex_unlock(&recovery_lock); return 0; }
/* * usbrecords_find * check if we can recover device based on recovery queue * @param[t_token] recovery token to compare against * @ret -1 unable to recover, 0 success (token->user_data has handle) */ int usbrecords_find(transport_recovery_token_t *t_token) { int rc = -1; recovery_entry_t *item; recovery_entry_t *tmp_item; platform_mutex_lock(&recovery_lock); /* check all entries */ for (item = TAILQ_FIRST(&t_recovery_queue); item != NULL; item = tmp_item) { transport_recovery_token_t *token = item->t_token; tmp_item = TAILQ_NEXT(item, entries); if (token->len == t_token->len) { if( 0 == memcmp(token->token, t_token->token, token->len) ) { TRACEF("Matches, nduid(%s)\n", token->nduid); /* Remove the item from queue. */ TAILQ_REMOVE(&t_recovery_queue, item, entries); /* restore handle */ t_token->user_data = token->user_data; /* Free the item as we don't need it anymore. */ platform_free(item->t_token); platform_free(item); /* success */ rc = 0; break; } } } platform_mutex_unlock(&recovery_lock); return rc; }
/* * @brief: free buffer */ int buffer_free(buffer_t *b) { /* check */ if (!b) return -1; /* free data if exist */ if(b->data) platform_free(b->data); platform_free(b); return 0; }
/* * @brief handle authrequest */ static int novacom_handle_authrequest(device_handle_t dev, uint32_t chan, buffer_t *b, buffer_t *r, unsigned char cmd) { int rc=-1; bool res = false; char *mode = NULL; char *str = NULL; /* skip version */ if ( 0 != buffer_getbyte(b, NULL) ) { goto done; } /* get mode */ if (0 != buffer_getstring(b, (unsigned char **)&mode) ) { goto done; } /* get hash */ if ( 0 != buffer_getstring(b, (unsigned char **)&str) ) { goto done; } LTRACEF("mode %s, hash %s\n", mode, str); rc = strlen(mode); if ( (AUTH_METHOD_PASSWORD_LEN == rc) && ( 0 == strncmp(mode, AUTH_METHOD_PASSWORD, rc)) ) { /*password request */ res = auth_process_passw(str, strlen(str), 0); } else if ( (AUTH_METHOD_TOKEN_LEN == rc) && ( 0 == strncmp(mode, AUTH_METHOD_TOKEN, rc)) ) { /*token request*/ res = auth_process_token(str, strlen(str)); } rc = (true == res)?0:-1; done: /* pickup res */ LTRACEF("result(%d)\n", rc); if (rc) buffer_putbyte(r, SSH_MSG_USERAUTH_FAILURE); else buffer_putbyte(r, SSH_MSG_USERAUTH_SUCCESS); buffer_putbyte(r, 0); buffer_putbyte(r, cmd); /*resources */ platform_free(mode); platform_free(str); return rc; }
/* * @brief reports device list * @param sc socket * @param channel * @param url command url * @param dev device handle * @param ssid session id * @ret -1 error, 0 success */ int novacom_hostcmd_devremove(SOCKET sc, uint32_t channel, novacom_command_url_t *url, void *_dev, const char *ssid) { int rc=-1; buffer_t *b = buffer_new(100); /* 44 + 44 + 2 */ device_handle_t dev = (device_handle_t)_dev; char *file = NULL; char hash[SHA1_HASH_STRSIZE]; if ( strlen(ssid) != NOVACOM_AUTHSESSION_LEN) { LTRACEF("invalid ssid length(%d)\n", strlen(ssid)); goto done; } /* buffer */ if (!b) goto done; /* expecting at least one parameter */ if (url->argcount < 1) { goto done; } /* message type(auth.h) */ rc = buffer_putbyte(b, SSH_MSG_USERAUTH_TOKENREQUEST_RM); if (rc) goto done; /* version info */ rc = buffer_putbyte(b, 0); if (rc) goto done; /* password info */ rc = buffer_putstring(b, (const unsigned char *)url->args[0], strlen(url->args[0])); if (rc) goto done; /* token hash info */ file = novacom_rnduid(dev); if (!file) goto done; rc = tokenstorage_readhash(file, ssid, hash, sizeof(hash)); if (-1 == rc) { LTRACEF("unable to get hashed token\n"); goto done; } /* pack it */ rc = buffer_putstring(b, (unsigned char *)hash, sizeof(hash)); if (rc) goto done; rc = novacom_write_channel_async(dev, channel, b->data, b->pos, ASYNC_FLAG_COPY, (novacom_async_callback)&socketcmd_write_callback, (void *)url); done: LTRACEF("rc(%d)\n", rc); platform_free(file); buffer_free(b); return rc; }
void openrct2_dispose() { network_close(); http_dispose(); language_close_all(); openrct2_release_rct2_segment(); platform_free(); }
void openrct2_dispose() { network_close(); http_dispose(); language_close_all(); rct2_dispose(); config_release(); #ifndef DISABLE_NETWORK EVP_MD_CTX_destroy(gHashCTX); #endif // DISABLE_NETWORK rct2_interop_dispose(); platform_free(); }
static long ioctl_add_module(char *file) { char *buf; int64_t ret; if (g_num_files >= MAX_NUM_MODULES) { ALERT("IOCTL_ADD_MODULE: too many modules have been loaded\n"); return BF_IOCTL_FAILURE; } buf = (char *)platform_alloc(g_module_length); if (buf == NULL) { ALERT("IOCTL_ADD_MODULE: failed to allocate memory for the module\n"); return BF_IOCTL_FAILURE; } ALERT("address to copy from %p size: 0x%" PRId64 "\n", file, g_module_length); ret = copyin((user_addr_t)file, (void *)buf, g_module_length); if (ret != 0) { ALERT("IOCTL_ADD_MODULE: failed to copy memory from userspace\n"); goto failed; } ret = common_add_module(buf, g_module_length); if (ret != BF_SUCCESS) { ALERT("IOCTL_ADD_MODULE: failed to add module\n"); goto failed; } files[g_num_files] = buf; files_sizes[g_num_files] = g_module_length; g_num_files++; DEBUG("IOCTL_ADD_MODULE: succeeded\n"); return BF_IOCTL_SUCCESS; failed: platform_free(buf, g_module_length); DEBUG("IOCTL_ADD_MODULE: failed\n"); return BF_IOCTL_FAILURE; }
/* * @brief: create new buffer */ buffer_t *buffer_new(size_t size) { buffer_t *buf = NULL; buf = (buffer_t *)platform_calloc(sizeof(buffer_t)); if (buf && size) { buf->data = (unsigned char *)platform_calloc(size); buf->len = size; if (!buf->data) { platform_free(buf); buf = NULL; } } return buf; }
void clean_up( void ) { sound_free(); game_list_free(); submenu_free(); platform_free(); menu_free(); hint_free(); font_free(); bg_free(); location_free(); event_free(); snap_free(); video_free(); sdl_free(); }
/* * @brief: set buffer data */ int buffer_setdata(buffer_t *b, unsigned char *data, size_t size) { if (b->data) { platform_free(b->data); } b->data = (unsigned char *)platform_calloc(size); if (!b->data) { return -1; } memcpy(b->data, data, size); #if LOCAL_TRACE hexdump8(b->data, MIN(size, 64)); #endif b->pos = 0; b->len = size; return 0; }
internal void *resize_pixel_buffer(struct pixel_buffer *buf, int height, int width) { debug(1, "Buffer was %d x %d, need %d x %d\n", buf->width, buf->height, width, height); if (buf->pixels) { platform_free(buf->pixels, buf->pixels_bytes_len); } buf->width = width; buf->height = height; buf->pixels_bytes_len = buf->height * buf->width * buf->bytes_per_pixel; buf->pitch = buf->width * buf->bytes_per_pixel; buf->pixels = platform_alloc(buf->pixels_bytes_len); if (!buf->pixels) { debug(0, "Could not alloc buf->pixels (%d)\n", buf->pixels_bytes_len); } return buf->pixels; }
static long ioctl_unload_vmm(void) { int i; int64_t ret; long status = BF_IOCTL_SUCCESS; ret = common_unload_vmm(); if (ret != BF_SUCCESS) { ALERT("IOCTL_UNLOAD_VMM: failed to unload vmm: %lld\n", ret); status = BF_IOCTL_FAILURE; } for (i = 0; i < g_num_files; i++) platform_free(files[i], files_sizes[i]); g_num_files = 0; if (status == BF_IOCTL_SUCCESS) DEBUG("IOCTL_UNLOAD_VMM: succeeded\n"); return status; }
static void *novacom_usb_tx_thread(void *arg) { novacom_usb_handle_t *handle = (novacom_usb_handle_t *)arg; int rc; struct novacom_tx_packet packet; char *buf; buf = platform_calloc(MAX_MTU); platform_assert(buf != NULL); LTRACEF("start::wait for startup event: %p\n", handle); platform_event_wait(&handle->tx_startup_event); //why waiting rx for starting ??? handle->tx_startup_wait = 0; //change status to started LTRACEF("start::startup event received, continue: %p\n", handle); handle->tx_timeout = novacom_usbll_get_timeout(handle->usbll_handle); while (!novacom_shutdown && !handle->shutdown) { // see if we have something to send packet.len = novacom_usbll_get_mtu(handle->usbll_handle); packet.buf = buf; if (novacom_usbll_prepare_tx_packet(handle->usbll_handle, &packet, 100) != TX_NO_PACKET) { // write a block back #if FAULTY_TX if (rand() < (RAND_MAX / 10)) { TRACEF("dropped tx packet\n"); } else { #endif rc = novacom_usb_write(handle, packet.buf, packet.len); if (rc < 0) { platform_time_t st; platform_time_t et; int time_used = 0; unsigned int count = 0; TRACEL(LOG_ALWAYS, "usbll(%08x) error writing packet, result(%d), errno %d\n", novacom_usbll_getuid(handle->usbll_handle), rc, errno); platform_get_time(&st); while (rc < 0 && !handle->shutdown) { //shutdown asap platform_get_time(&et); if (platform_delta_time_msecs(&st, &et) >= g_usbio_retry_timeout) { handle->shutdown = true; break; } if (g_usbio_retry_delay > 0) { if ((g_usbio_retry_timeout-time_used) >= g_usbio_retry_delay) { usleep(g_usbio_retry_delay * 1000); time_used += g_usbio_retry_delay; } else { usleep((g_usbio_retry_timeout - time_used) * 1000); time_used = g_usbio_retry_timeout; } } rc = novacom_usb_write(handle, packet.buf, packet.len); count++; } TRACEL(LOG_ALWAYS, "usbll(%08x) writing packet, writes(%ld), duration(%dms), result(%d), last_errno %ld\n", novacom_usbll_getuid(handle->usbll_handle), count, platform_delta_time_msecs(&st, &et), rc, errno); count = 0; } if (rc >=0) { TRACEF/*LOG_PRINTF*/("usbll(%08x) wrote tx packet len=%d\n", novacom_usbll_getuid(handle->usbll_handle), rc); } #if FAULTY_TX } #endif } } LTRACEF("shutting down handle %p\n", handle); platform_event_signal(&handle->tx_shutdown_event); platform_free(buf); return NULL; }
/* * @brief: service reply * @ret * -1 error * 0 ok */ int novacom_service_reply(const char *devid, struct novacom_command_url *url, const void *buf, size_t len) { int rc=-1; unsigned char type; /* reply cmd type */ unsigned char version; /* reply cmd version */ unsigned char cmd; /* reply cmd */ buffer_t *b = buffer_new(0); LTRACEF("len %d\n", len); /* buffer wrapper */ rc = buffer_setdata(b, (unsigned char *)buf, len); if (rc) goto done; /* recover message type, version, cmd */ rc = buffer_getbyte(b, &type); if (rc) goto done; rc = buffer_getbyte(b, &version); if (rc) goto done; rc = buffer_getbyte(b, &cmd); if (rc) goto done; LTRACEF("msg type: %d, cmd %d\n", type, cmd); switch(cmd) { case SSH_MSG_DISCONNECT: case SSH_MSG_USERAUTH_REQUEST: rc = (SSH_MSG_USERAUTH_FAILURE == type)? -1:0; break; case SSH_MSG_USERAUTH_TOKENREQUEST_RM: rc = (SSH_MSG_USERAUTH_FAILURE == type)? -1:0; /* delete local store */ if (SSH_MSG_USERAUTH_SUCCESS == type) { tokenstorage_remove(devid); } break; case SSH_MSG_USERAUTH_TOKENREQUEST_ADD: if (SSH_MSG_USERAUTH_TOKEN_REPLY == type) { unsigned char *token = NULL; rc = buffer_getblob(b, &token); LTRACEF("rc %d\n", rc); if (rc > 0) { LTRACEF("save token reply to local store\n"); rc = tokenstorage_store(devid, token, rc); if (rc < 0) { TRACEF("Unable to save token in local store\n"); } platform_free(token); } } else { rc = -1; } break; default: { rc = -1; } break; } done: buffer_free(b); return rc; }
/* * @brief handle token request * mode=0:add token request * mode=1:remove token request */ static int novacom_handle_tokenrequest(device_handle_t dev, uint32_t chan, buffer_t *b, buffer_t *r, unsigned char cmd) { int rc=-1; char *hash = NULL; char *token = NULL; char *blob = NULL; /* skip version */ if ( 0 != buffer_getbyte(b, NULL) ) { LTRACEF("missing version\n"); goto out; } /* get hash */ if ( 0 != buffer_getstring(b, (unsigned char **)&hash) ) { LTRACEF("missing password hash\n"); goto out; } /* get hashed token for "remove" */ if ( (SSH_MSG_USERAUTH_TOKENREQUEST_RM == cmd) && ( 0 != buffer_getstring(b, (unsigned char **)&token) ) ) { LTRACEF("missing token hash\n"); goto out; } /* verify that password hash is good */ if ( true != auth_process_passw(hash, strlen(hash), 1) ) { LTRACEF("invalid password hash\n"); goto out; } /* process tokens */ if (SSH_MSG_USERAUTH_TOKENREQUEST_RM == cmd) { rc = auth_tokenfile_delete(token, strlen(token)); /* pickup res */ if (!rc) { buffer_putbyte(r, SSH_MSG_USERAUTH_SUCCESS); buffer_putbyte(r, 0); /* version */ buffer_putbyte(r, cmd); /* command */ } } else { blob = platform_calloc(NOVACOM_AUTHTOKEN_LEN); if (!blob) { LTRACEF("unable to allocate token\n"); goto out; } /* fill with random data */ LTRACEF("generate token\n"); rc = auth_tokenfile_buffergenerate(blob, NOVACOM_AUTHTOKEN_LEN); if (rc) { LTRACEF("unable to generate token\n"); goto out; } /* save token: creating file with name:<rnduid> */ LTRACEF("save token\n"); char *file = novacom_rnduid(dev); if (!file) { LTRACEF("unable to retrieve rnduid\n"); goto out; } rc = auth_tokenfile_create(file, blob, NOVACOM_AUTHTOKEN_LEN); platform_free(file); if (rc) { LTRACEF("unable to store token\n"); goto out; } LTRACEF("token generated && saved\n"); /* pickup res */ buffer_putbyte(r, SSH_MSG_USERAUTH_TOKEN_REPLY); buffer_putbyte(r, 0); /* version */ buffer_putbyte(r, cmd); /* command */ /* resize output buffer to fit token data */ rc = buffer_resize(r, 16 + NOVACOM_AUTHTOKEN_LEN); if (rc) goto out; rc = buffer_putblob(r, (unsigned char *)blob, NOVACOM_AUTHTOKEN_LEN); LTRACEF("token placed\n"); } out: /* error result */ if (rc) { buffer_setpos(r, 0); buffer_putbyte(r, SSH_MSG_USERAUTH_FAILURE); buffer_putbyte(r, 0); /* version */ buffer_putbyte(r, cmd); /* command */ } LTRACEF("result(%d), r->pos %d, r->size %d\n", rc, r->pos, r->len); /* free resources */ platform_free(hash); platform_free(token); platform_free(blob); return rc; }
static void *novacom_usb_rx_thread(void *arg) { novacom_usb_handle_t *handle = (novacom_usb_handle_t *)arg; transport_recovery_token_t *rec_token = NULL; ///< recovery token int rc; int packet_type; char *buf; int sniff = 1; buf = platform_calloc(MAX_MTU); platform_assert(buf != NULL); LTRACEF("start, handle %p\n", handle); handle->rx_timeout = novacom_usbll_get_timeout(handle->usbll_handle); while (!novacom_shutdown && !handle->shutdown) { platform_time_t st; int time_used; // read a block from the pmux rc = novacom_usb_read(handle, buf, novacom_usbll_get_mtu(handle->usbll_handle)); platform_get_time(&st); time_used = 0; if (rc <= 0) { platform_time_t et; unsigned int count = 0; TRACEL(LOG_ALWAYS, "%s:%d -- usbll(%08x) error: reading packet, result(%d), errno %d\n", __FUNCTION__, __LINE__, novacom_usbll_getuid(handle->usbll_handle), rc, errno); while (rc <= 0 && !handle->shutdown) { //shutdown asap platform_get_time(&et); if (platform_delta_time_msecs(&st, &et) >= g_usbio_retry_timeout) { handle->shutdown = true; break; } if (g_usbio_retry_delay > 0) { if ((g_usbio_retry_timeout-time_used) >= g_usbio_retry_delay) { usleep(g_usbio_retry_delay * 1000); time_used += g_usbio_retry_delay; } else { usleep((g_usbio_retry_timeout - time_used) * 1000); time_used = g_usbio_retry_timeout; } } rc = novacom_usb_read(handle, buf, novacom_usbll_get_mtu(handle->usbll_handle)); count++; } TRACEL(LOG_ALWAYS, "%s:%d -- usbll(%08x) reading packet, reads(%ld), duration(%dms), result(%d), last_errno %ld\n", __FUNCTION__, __LINE__, novacom_usbll_getuid(handle->usbll_handle), count, platform_delta_time_msecs(&st, &et), rc, errno); count = 0; } /* sniff */ if(sniff) { uint32_t uid = ((handle->busnum & 0x0FFFF) << 16) | (handle->devnum & 0x0FFFF); transport_recovery_token_t sniff_token; int ret; /* generate token from packet */ ret = novacom_usbll_generate_recovery_token(buf, rc, &sniff_token); if(ret == -1) { TRACEL(LOG_ERROR, "%s:%d -- Used out system resouce, exit now !!!\n", __FUNCTION__, __LINE__); abort(); } /* check queue for saved connections */ ret = usbrecords_find(&sniff_token); /* free interface recovery token */ platform_free(sniff_token.token); /* check result: create new handle, or recover */ if(ret) { LTRACEF("Unable to recover(%d)\n", ret); handle->usbll_handle = novacom_usbll_create(handle->devtype, MAX_MTU, 0, USBDEVFS_IOCTL_TIMEOUT); } else { TRACEL(LOG_ERROR, "Recovered record...\n"); handle->usbll_handle = sniff_token.user_data; } /* update uid */ novacom_usbll_setuid(handle->usbll_handle, uid); handle->rx_timeout = novacom_usbll_get_timeout(handle->usbll_handle); handle->tx_timeout = novacom_usbll_get_timeout(handle->usbll_handle); sniff = 0; } /* process */ packet_type = PACKET_TYPE_NULL; if (rc > 0) { // process it packet_type = novacom_usbll_process_packet(handle->usbll_handle, buf, rc); if (packet_type == PACKET_TYPE_BADPACKET) { platform_time_t et; TRACEF("received bad packet\n"); platform_get_time(&et); if (platform_delta_time_msecs(&st, &et) >= g_usbio_retry_timeout) { handle->shutdown = true; break; } if (g_usbio_retry_delay > 0) { if ((g_usbio_retry_timeout-time_used) >= g_usbio_retry_delay) { usleep(g_usbio_retry_delay * 1000); time_used += g_usbio_retry_delay; } else { usleep((g_usbio_retry_timeout - time_used) * 1000); time_used = g_usbio_retry_timeout; } } ///handle->shutdown = true; ///break; } else if(handle->tx_startup_wait) { platform_event_signal(&handle->tx_startup_event); } } else { #if TRACE_ZERO_LEN_PACKETS log_printf(LOG_TRACE, "RX zero len\n"); #endif } } LTRACEF("shutting down handle %p\n", handle); /* wake up tx thread (if still waits for startup) */ if(handle->tx_startup_wait) { LTRACEF("wake up tx thread\n"); platform_event_signal(&handle->tx_startup_event); } /* wait for the tx thread to exit */ LTRACEF("waiting on tx thread\n"); platform_event_wait(&handle->tx_shutdown_event); /* RX thread is responsible for cleaning up */ LTRACEF("cleaning up handle %p\n", handle); /* grab recovery token if available */ if(handle->usbll_handle) { rc = -1; rec_token = platform_calloc(sizeof(transport_recovery_token_t)); if(rec_token) { snprintf(rec_token->nduid, sizeof(rec_token->nduid), "%s", novacom_usbll_get_nduid(handle->usbll_handle)); rc = novacom_usbll_get_recovery_token(handle->usbll_handle, rec_token); if(rc != -1) { rc = usbrecords_add(rec_token); } else { LTRACEF("unable to recovery token!!!\n"); } } /* error: free memory, destroy device */ if(rc == -1) { //we should never go here. novacom_usbll_destroy(handle->usbll_handle); platform_free(rec_token); } } novacom_usb_close(handle); platform_event_destroy(&handle->tx_startup_event); platform_event_destroy(&handle->tx_shutdown_event); platform_free(handle); platform_free(buf); return NULL; }
int main(int argc, char *argv[]) { char *title; SDL_Window *window; Uint32 flags; int x, y, width, height, shutdown; SDL_Renderer *renderer; SDL_Event event; SDL_AudioDeviceID sdl_audio_dev; struct timespec start, last_print, now, elapsed; unsigned long total_elapsed_seconds; double fps; unsigned long int frame_count, frames_since_print; struct game_memory mem; struct pixel_buffer *virtual_win; struct pixel_buffer blit_buf; struct human_input input[2]; struct human_input *tmp_input; struct human_input *new_input; struct human_input *old_input; struct sdl_texture_buffer texture_buf; struct sdl_event_context event_ctx; struct audio_ring_buffer audio_ring_buf; struct audio_buffer audio_buf; pixel_buffer_init(&blit_buf); texture_buf.texture = NULL; texture_buf.pixel_buf = &blit_buf; flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC; if (SDL_Init(flags) != 0) { return 1; } height = 480; width = 640; mem.is_initialized = 0; mem.fixed_memory_size = 4 * 1024 * 1024; mem.transient_memory_size = 1 * 1024 * 1024; mem.fixed_memory = platform_alloc(mem.fixed_memory_size + mem.transient_memory_size); if (mem.fixed_memory == 0) { debug(0, "did not alloc game memory\n"); return 1; } mem.transient_memory = mem.fixed_memory + mem.fixed_memory_size; init_game(&mem, HANDMAIDEN_AUDIO_DEFAULT_VOLUME, HANDMAIDEN_AUDIO_START_VOLUME); virtual_win = NULL; update_pixel_buffer(&mem, &virtual_win); if (!virtual_win) { debug(0, "did not assign virtual_win\n"); } sdl_init_joysticks(&event_ctx); title = (argc > 1) ? argv[1] : "Handmaiden Hero"; x = SDL_WINDOWPOS_UNDEFINED; y = SDL_WINDOWPOS_UNDEFINED; flags = SDL_WINDOW_RESIZABLE; window = SDL_CreateWindow(title, x, y, width, height, flags); if (!window) { debug(0, "Could not SDL_CreateWindow\n"); return 2; } renderer = SDL_CreateRenderer(window, FIRST_SUPPORTING, NONE); if (!renderer) { return 3; } sdl_resize_texture_buf(window, renderer, &texture_buf); if (init_audio_ring_buffer(&audio_ring_buf)) { sdl_audio_dev = sdl_init_audio(&audio_ring_buf); } else { sdl_audio_dev = 0; } if (sdl_audio_dev && audio_ring_buf.buf_len) { audio_buf.stream_pos = 0; audio_buf.num_samples = 0; audio_buf.samples = (int *)platform_alloc(audio_ring_buf.buf_len); if (!audio_buf.samples) { debug(0, "could not allocate audio_buf.samples[%u]\n", audio_ring_buf.buf_len); audio_buf.buf_len = 0; } else { audio_buf.buf_len = audio_ring_buf.buf_len; } } /* start audio playing by setting "pause" to zero */ if (sdl_audio_dev && audio_buf.samples) { SDL_PauseAudioDevice(sdl_audio_dev, 0); } event_ctx.event = &event; event_ctx.texture_buf = &texture_buf; event_ctx.renderer = renderer; event_ctx.window = window; event_ctx.win_id = SDL_GetWindowID(window); clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start); last_print.tv_sec = start.tv_sec; last_print.tv_nsec = start.tv_nsec; total_elapsed_seconds = 0; frames_since_print = 0; frame_count = 0; shutdown = 0; old_input = &input[0]; new_input = &input[1]; init_input(old_input); init_input(new_input); while (!shutdown) { tmp_input = new_input; new_input = old_input; old_input = tmp_input; init_input(new_input); while (SDL_PollEvent(&event)) { if ((shutdown = process_event(&event_ctx, new_input))) { break; } } process_joysticks(&event_ctx, old_input, new_input); if (shutdown || (shutdown = process_input(&mem, new_input))) { break; } update_pixel_buffer(&mem, &virtual_win); stretch_buffer(virtual_win, &blit_buf); sdl_blit_texture(renderer, &texture_buf); if (sdl_audio_dev && audio_buf.samples) { if ((audio_ring_buf.write_cursor - audio_ring_buf.play_cursor) < audio_ring_buf.buf_len) { SDL_LockAudio(); if (fill_ring_buf (&audio_ring_buf, &mem, &audio_buf) < 0) { shutdown = 1; } SDL_UnlockAudio(); } } frame_count++; frames_since_print++; clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &now); diff_timespecs(last_print, now, &elapsed); if (((elapsed.tv_sec * 1000000000) + elapsed.tv_nsec) > 100000000) { fps = ((double)frames_since_print) / (((double)elapsed.tv_sec) * 1000000000.0 + ((double)elapsed.tv_nsec) / 1000000000.0); frames_since_print = 0; last_print.tv_sec = now.tv_sec; last_print.tv_nsec = now.tv_nsec; diff_timespecs(start, now, &elapsed); total_elapsed_seconds = elapsed.tv_sec + 1; if (FPS_PRINTER) { debug(0, "fps: %.02f (avg fps: %.f) %u, %u%s", fps, (double)frame_count / (double)total_elapsed_seconds, audio_ring_buf.play_cursor, audio_ring_buf.write_cursor, ERIC_DEBUG ? "\n" : "\r"); } } } debug(0, "\n"); if (sdl_audio_dev) { SDL_CloseAudioDevice(sdl_audio_dev); } close_audio_debug_logging(&audio_ring_buf); sdl_close_joysticks(&event_ctx); /* we probably do not need to do these next steps */ if (HANDMAIDEN_TRY_TO_MAKE_VALGRIND_HAPPY) { /* first cleanup SDL stuff */ if (texture_buf.texture) { SDL_DestroyTexture(texture_buf.texture); } SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); /* then collect our own garbage */ if (blit_buf.pixels) { platform_free(blit_buf.pixels, blit_buf.pixels_bytes_len); } if (audio_ring_buf.buf) { platform_free(audio_ring_buf.buf, audio_ring_buf.buf_len); } if (audio_buf.samples) { platform_free(audio_buf.samples, audio_buf.buf_len); } if (mem.fixed_memory) { platform_free(mem.fixed_memory, mem.fixed_memory_size + mem.transient_memory_size); } } return 0; }