Ejemplo n.º 1
0
void load_texture(fs_emu_texture *texture) {
    fs_image *image = texture->image;
    //printf("loading texture from image %p\n", image);
    if (!image) {
        return;
    }
    unsigned int opengl_texture;
    glGenTextures(1, &opengl_texture);
    //texture->opengl_context_stamp = g_fs_ml_opengl_context_stamp;
    fs_gl_bind_texture(opengl_texture);
    fs_gl_unpack_row_length(0);
    int gl_buffer_format = GL_RGBA;
    if (fs_emu_get_video_format() == FS_EMU_VIDEO_FORMAT_BGRA) {
        gl_buffer_format = GL_BGRA;
    }
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image->width, image->height,
            0, gl_buffer_format, GL_UNSIGNED_BYTE, image->data);
    CHECK_GL_ERROR();
    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
    //        GL_LINEAR_MIPMAP_LINEAR);
    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
    //        GL_LINEAR_MIPMAP_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    CHECK_GL_ERROR();
    //glGenerateMipmapEXT(GL_TEXTURE_2D);
    texture->texture = opengl_texture;
}
Ejemplo n.º 2
0
static void create_texture_if_needed(int width, int height) {
    //g_frame_texture.video_version = g_fs_emu_video_version;
    if (g_frame_texture && g_frame_texture_width >= width &&
            g_frame_texture_height >= height) {
        return;
    }
    fs_gl_bind_texture(0);

    if (g_frame_texture) {
        glDeleteTextures(1, &g_frame_texture);
        CHECK_GL_ERROR();
    }
    g_frame_texture_width = 1;
    while (g_frame_texture_width < width) {
        g_frame_texture_width *= 2;
    }
    g_frame_texture_height = 1;
    while (g_frame_texture_height < height) {
        g_frame_texture_height *= 2;
    }
    glGenTextures(1, &g_frame_texture);
    CHECK_GL_ERROR();
    //g_frame_texture.opengl_context_stamp = g_fs_ml_opengl_context_stamp;
    //fs_emu_set_texture(&g_frame_texture);
    fs_gl_bind_texture(g_frame_texture);
    // with high quality borders, there should be no reason to initialize
    // the texture to black
    void *data = NULL;
    //void *data = g_malloc0(g_frame_texture_width * g_frame_texture_height * 4);
#ifndef HAVE_GLES
    fs_gl_unpack_row_length(0);
#endif
    glTexImage2D(GL_TEXTURE_2D, 0, fs_emu_get_texture_format(),
            g_frame_texture_width, g_frame_texture_height, 0,
            fs_emu_get_video_format(), GL_UNSIGNED_BYTE, data);
    CHECK_GL_ERROR();
    if (data) {
        g_free(data);
    }
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    CHECK_GL_ERROR();
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    CHECK_GL_ERROR();
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    CHECK_GL_ERROR();
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    CHECK_GL_ERROR();
}
Ejemplo n.º 3
0
static inline void copy_pixel(unsigned char **dst, unsigned char **src) {
    unsigned char *sp = *src;
    unsigned char *dp = *dst;
    if (fs_emu_get_video_format() == FS_EMU_VIDEO_FORMAT_BGRA) {
        dp[0] = ((int) sp[2]) * sp[3] / 255;
        dp[1] = ((int) sp[1]) * sp[3] / 255;
        dp[2] = ((int) sp[0]) * sp[3] / 255;
    }
    else {
        dp[0] = ((int) sp[0]) * sp[3] / 255;
        dp[1] = ((int) sp[1]) * sp[3] / 255;
        dp[2] = ((int) sp[2]) * sp[3] / 255;
    }
    dp[3] = sp[3];
    *dst = *dst + 4;
    *src = *src + 4;
}
Ejemplo n.º 4
0
int fs_emu_font_render(fs_emu_font *font, const char *text, float x, float y,
        float r, float g, float b, float alpha) {
    if (font->image == NULL) {
        return 0;
    }
    if (text == NULL || *text == '\0') {
        return 0 ;
    }
    if (!g_initialized) {
        initialize();
    }
    /*
    if (g_fs_ml_opengl_context_stamp != g_video_version) {
        GList* list = g_cache;
        while (list) {
            cache_item *item = (cache_item *) list->data;
            g_free(item->text);
            g_free(item);
            list = list->next;
        }
        g_list_free(g_cache);
        g_cache = NULL;
        initialize_cache();
    }
    */
    // find cached text entry, if any
    //sanity_check();
    GList* list = g_cache;
    while (list) {
        cache_item *item = (cache_item *) list->data;
        if (item->font == font && strcmp(item->text, text) == 0) {
            break;
        }
        list = list->next;
    }
    if (list) {
        cache_item *item = (cache_item *) list->data;
        g_cache = g_list_delete_link(g_cache, list);
        sanity_check();
        fs_gl_blending(1);
        fs_gl_texturing(1);
        //fs_emu_ortho();
        //fs_emu_set_texture(NULL);
        fs_gl_bind_texture(g_text_texture);
        //glColor4f(1.0, 1.0, 1.0, alpha);
        //printf("rendering %f %f %f %f...\n", item->x1, item->x2, item->y1, item->y2);
        fs_gl_color4f(r * alpha, g * alpha, b * alpha, alpha);
        //glColor4f(r * alpha, g * alpha, b * alpha, alpha);
        GLfloat tex[] = {
            item->x1, item->y2,
            item->x2, item->y2,
            item->x2, item->y1,
            item->x1, item->y1
        };
        GLfloat vert[] = {
            x, y,
            x + item->width, y,
            x + item->width, y + item->height,
            x, y + item->height
        };

        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);

        glVertexPointer(2, GL_FLOAT, 0, vert);
        glTexCoordPointer(2, GL_FLOAT, 0, tex);
        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

        glDisableClientState(GL_VERTEX_ARRAY);
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);

        g_cache = g_list_prepend(g_cache, item);
        sanity_check();
        return item->width;
    }

    // calculate size of text

    //printf(":: %s\n", text);

    int chars = 0;
    int required_width = 0;
    int required_height = font->h;
    unsigned char *cp = (unsigned char *) text;
    for(; *cp; cp++) {
        unsigned char c = *cp;
        //printf("  %p\n", font);
        //printf("    %d\n", c);
        //printf("    %d\n", font->w[c]);
        if (required_width + font->w[c] > TEXTURE_WIDTH) {
            break;
        }
        required_width += font->w[c];
        chars++;
    }
    //fs_log("width: %d, height: %d\n", required_width, required_height);

    //float tw = font->texture->width;
    //float th = font->texture->height;




    // FIXME: clear g_buffer




    //int length = strlen(text);
    //for (int i = 0; i < length; i++) {
    cp = (unsigned char *) text;
    //glBegin(GL_QUADS);
    //glColor4f(1.0, 1.0, 1.0, 1.0);
    //int x2 = 0;

    int dx = 0;
    int dy = 0;

    for(int i = 0; i < chars; i++) {
        unsigned char c = *cp++;
        //unsigned char = (unsigned char) text[i];
        int sx = font->x[c];
        int sy = font->y[c];
        int sw = font->w[c];
        int sh = font->h;

        //printf("%d %d %d %d\n", sx, sy, sw, sh);

        // draw character

        int *sl = ((int *) font->image->data) + font->image->width * sy + sx;
        int ss = font->image->width; // source stride
        //int *sl = sp;
        int *dl = ((int *) g_buffer) + TEXTURE_WIDTH * dy + dx;
        int ds = TEXTURE_WIDTH; // destination stride
        //int *dl = dp;

        for (int y = 0; y < sh; y++) {
            //printf("%d\n", y);
            int *sp = sl;
            int *dp = dl;
            for (int x = 0; x < sw; x++) {
                //printf("%d %d\n", x, y);
                //*dp++ = 0xff0000ff;
                *dp++ = *sp++;
                //int a = *sp++;
            }
            sl += ss;
            dl += ds;
        }

        dx += sw;

        /*
        //fs_log("%d %d %d %d\n", font->x[c], font->y[c], w, h);
        float s1 = font->x[c] / tw;
        float s2 = (font->x[c] + w) / tw;
        //double t1 = 1.0 - (font->y[c]) / th;
        //double t2 = 1.0 - (font->y[c] + h) / th;
        float t1 = (font->y[c]) / th;
        float t2 = (font->y[c] + h) / th;
        //fs_log("%d %d %d %d\n", x, y, w, h);
        glTexCoord2f(s1, t2);
        //glVertex2f(x, y);
        glVertex2f(x2, 0);
        glTexCoord2f(s2, t2);
        //glVertex2f(x + w, y);
        glVertex2f(x2 + w, 0);
        glTexCoord2f(s2, t1);
        //glVertex2f(x + w, y + h);
        glVertex2f(x2 + w, h);
        glTexCoord2f(s1, t1);
        //glVertex2f(x, y + h);
        glVertex2f(x2, h);
        x2 += w;
        */
    }
    //printf("...\n");
    /*
    glEnd();

    glPopMatrix();
    glMatrixMode(GL_MODELVIEW);
    glPopAttrib();
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
    glPopMatrix();

    glDeleteFramebuffersEXT(1, &frame_buffer);
    //glDeleteRenderbuffersEXT(1, &depth_buffer);

    fs_emu_set_texture(NULL);

    if (mipmapping) {
        fs_gl_bind_texture(render_texture);
        glGenerateMipmapEXT(GL_TEXTURE_2D);
        fs_gl_bind_texture(0);
    }
    */

    GList *last = g_list_last(g_cache);
    cache_item *last_item = (cache_item *) last->data;
    int position = last_item->position;


    fs_gl_bind_texture(g_text_texture);
#ifndef HAVE_GLES
    fs_gl_unpack_row_length(TEXTURE_WIDTH);
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, position * 32, required_width,
            required_height, fs_emu_get_video_format(),
            GL_UNSIGNED_BYTE, g_buffer);
#else
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, required_width, required_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, g_buffer);

    for (int y = 0; y < required_height; y++) {
        char *row = g_buffer + ((y + position * 32)*TEXTURE_WIDTH) * 4;
        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, position * 32, required_width, 1, GL_RGBA, GL_UNSIGNED_BYTE, row);
    }
#endif

    cache_item *item = g_malloc(sizeof(cache_item));
    item->font = font;
    item->text = g_strdup(text);
    item->width = required_width;
    item->height = required_height;
    item->position = position;

    item->x1 = 0;
    item->x2 = required_width / (1.0 * TEXTURE_WIDTH);
    item->y1 = (item->position * 32) / (1.0 * TEXTURE_HEIGHT);
    item->y2 = (item->position * 32 + required_height) /
            (1.0 * TEXTURE_HEIGHT);
    //item->texture = render_texture;
    g_cache = g_list_prepend(g_cache, item);
    sanity_check();

    if (last_item->text) {
        g_free(last_item->text);
    }
    /*
    if (last_item->texture) {
        glDeleteTextures(1, &last_item->texture);
    }
    */
    g_free(last_item);

    g_cache = g_list_delete_link(g_cache, last);
    sanity_check();

    // now the text is in the cache, so call function again
    return fs_emu_font_render(font, text, x, y, r, g, b, alpha);
}
Ejemplo n.º 5
0
static void update_texture() {
    fs_emu_video_buffer *buffer = fs_emu_lock_video_buffer();
    // unlocked in fs_emu_video_after_update

    uint8_t *frame = buffer->data;
    if (frame == NULL) {
    	return;
    }
    int is_new_frame = 1;
    static int last_seq_no = -1;
    if (buffer->seq == last_seq_no + 1) {
        // normal
    }
    else if (buffer->seq == last_seq_no) {
        //fs_log("WARNING: repeated frame %d\n", info->seq_no);
        g_fs_emu_repeated_frames++;
        if (g_fs_emu_repeated_frames > 9999) {
            g_fs_emu_repeated_frames = 9999;
        }
        is_new_frame = 0;
    }
    else {
        int lost_frame_count = buffer->seq - last_seq_no - 1;
        g_fs_emu_lost_frames += lost_frame_count;
        //fs_log("lost %d frame(s)\n", lost_frame_count);
    }
    last_seq_no = buffer->seq;

    int width = buffer->width;
    int height = buffer->height;
    int bpp = buffer->bpp;

    if (g_fs_emu_screenshot) {
        static int count = 1;
        g_fs_emu_screenshot = 0;
        gchar *name, *path;
        time_t t = time(NULL);
        struct tm *tm_struct = localtime(&t);
        char strbuf[20];
        strftime(strbuf, 20, "%Y-%m-%d_%H-%M-%S", tm_struct);
        name = g_strdup_printf("%s_%d.png", strbuf, count);
        count += 1;
        path = g_build_filename(
                g_get_user_special_dir(G_USER_DIRECTORY_DESKTOP),
                name, NULL);
        fs_log("writing screenshot to %s\n", path);
        int len = width * height * bpp;
        uint8_t *out_data = malloc(width * height * 3);
        uint8_t *op = out_data;

        if (fs_emu_get_video_format() == FS_EMU_VIDEO_FORMAT_BGRA) {
            for (int x = 0; x < len; x += 4) {
                *op++ = frame[x + 2];
                *op++ = frame[x + 1];
                *op++ = frame[x + 0];
            }
        }
        else {
            for (int x = 0; x < len; x += 4) {
                *op++ = frame[x + 0];
                *op++ = frame[x + 1];
                *op++ = frame[x + 2];
            }
        }
        int result = fs_image_save_data(path, out_data, width, height, 3);
        if (result) {
            fs_log("saved screenshot\n");
        }
        else {
            fs_log("error saving screenshot\n");
        }
        g_free(name);
        g_free(path);
    }

    int format = 0;
    if (bpp == 3) {
        format = GL_RGB;
    }
    else if (bpp == 4) {
#if 0
        if (fs_emu_get_video_format() == GL_BGRA) {
            format = GL_BGRA;
        }
        else {
            format = GL_RGBA;
        }
#endif
        format = fs_emu_get_video_format();
    }
    else {
        //fs_log("na..\n");
        return;
        //fs_emu_fatal("bpp is neither 3 nor 4\n");
    }
    if (g_fs_emu_video_crop_mode) {
        g_crop = buffer->crop;
        if (g_crop.w == 0) {
            g_crop.w = width;
        }
        if (g_crop.h == 0) {
            g_crop.h = height;
        }
    }
    else {
        g_crop.x = 0;
        g_crop.y = 0;
        g_crop.w = buffer->width;
        g_crop.h = buffer->height;
    }

    int upload_x, upload_y, upload_w, upload_h;
    g_effective_viewport_mode = g_viewport_mode;
    if (buffer->flags & FS_EMU_FORCE_VIEWPORT_CROP_FLAG) {
        g_effective_viewport_mode = FS_EMU_VIEWPORT_MODE_CROP;
    }

    if (g_effective_viewport_mode == FS_EMU_VIEWPORT_MODE_CROP) {
        fix_border(buffer, &upload_x, &upload_y, &upload_w, &upload_h);
    }
    else {
        upload_x = 0;
        upload_y = 0;
        upload_w = buffer->width;
        upload_h = buffer->height;
    }

    if (g_fs_emu_scanlines &&
            (buffer->flags & FS_EMU_NO_SCANLINES_FLAG) == 0) {
        //printf("new frame? %d\n", is_new_frame);
        if (is_new_frame) {
            if (g_scanline_buffer_width != buffer->width ||
                    g_scanline_buffer_height != buffer->height) {
                if (g_scanline_buffer) {
                    free(g_scanline_buffer);
                }
                g_scanline_buffer = malloc(buffer->width * buffer->height * 4);
                g_scanline_buffer_width = buffer->width;
                g_scanline_buffer_height = buffer->height;
            }
            fs_emu_render_scanlines(g_scanline_buffer, buffer,
                    upload_x, upload_y, upload_w, upload_h,
                    g_fs_emu_scanlines_dark, g_fs_emu_scanlines_light);
        }
        if (g_scanline_buffer) {
            frame = g_scanline_buffer;
        }
    }

    //fs_log("%d %d %d %d %d %d %d\n", width, height, bpp,
    //        g_crop.x, g_crop.y, g_crop.w, g_crop.h);
    g_frame_width = width;
    g_frame_height = height;
    g_frame_aspect = buffer->aspect;

    create_texture_if_needed(width, height);
    fs_gl_bind_texture(g_frame_texture);

    uint8_t *data_start = frame + ((upload_y * width) + upload_x) * 4;
#ifndef HAVE_GLES
    fs_gl_unpack_row_length(width);
    glTexSubImage2D(GL_TEXTURE_2D, 0, upload_x, upload_y,
    		upload_w, upload_h, format,
            GL_UNSIGNED_BYTE, data_start);
#else
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, upload_w, upload_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data_start);

    for (int y = 0; y < upload_h; y++) {
        char *row = data_start + ((y + upload_y)*width + upload_x) * 4;
        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, upload_y, upload_w, 1, GL_RGBA, GL_UNSIGNED_BYTE, row);
    }
#endif
    CHECK_GL_ERROR();

#if 1
    int hq_border = 2;
    if (hq_border >= 1) {
        if (upload_y > 0) {
            glTexSubImage2D(GL_TEXTURE_2D, 0, 0, upload_y - 1, width, 1,
                    format, GL_UNSIGNED_BYTE,
                    frame + (upload_y) * width * bpp);
            CHECK_GL_ERROR();
        }

        if (upload_y + upload_h < g_frame_texture_height) {
            glTexSubImage2D(GL_TEXTURE_2D, 0, 0, upload_y + upload_h,
                    width, 1, format, GL_UNSIGNED_BYTE,
                    frame + (upload_y + upload_h - 1) * width * bpp);
            CHECK_GL_ERROR();
        }

        if (upload_x > 0) {
            glTexSubImage2D(GL_TEXTURE_2D, 0, upload_x - 1, upload_y,
                    1, upload_h, format, GL_UNSIGNED_BYTE, frame +
                    ((upload_y) * width + upload_x) * bpp);
            CHECK_GL_ERROR();
        }

        if (upload_x + upload_w < g_frame_texture_width) {
            glTexSubImage2D(GL_TEXTURE_2D, 0, upload_x + upload_w,
                    upload_y, 1, upload_h, format,
                    GL_UNSIGNED_BYTE, frame +
                    ((upload_y) * width + upload_x + upload_w - 1) * bpp);
            CHECK_GL_ERROR();
        }
    }
#if 0
    if (hq_border >= 2) {
        if (upload_y + upload_h < g_frame_texture.height - 1) {
            //printf("1\n");
            glTexSubImage2D(GL_TEXTURE_2D, 0, 0, upload_y + upload_h + 1,
                    width, 1, format, GL_UNSIGNED_BYTE,
                    frame + (upload_y + upload_h - 1) * width * bpp);
                    //frame + (upload_y + upload_h - 2) * width * bpp);
        }

        if (upload_x + upload_w < g_frame_texture.width - 1) {
            glTexSubImage2D(GL_TEXTURE_2D, 0, upload_x + upload_w + 1,
                    upload_y, 1, upload_h, format,
                    GL_UNSIGNED_BYTE, frame +
                    ((upload_y) * width + upload_x + upload_w - 1) * bpp);
        }
    }
#endif
#endif
}
Ejemplo n.º 6
0
int main(int argc, char *argv[])
{
    fs_uae_argc = argc;
    fs_uae_argv = argv;
    fs_set_argv(argc, argv);

#ifdef WITH_CEF
    cef_init(argc, argv);
#endif

    char **arg;
    arg = argv + 1;
    while (arg && *arg) {
        if (strcmp(*arg, "--list-joysticks") == 0) {
            list_joysticks();
            exit(0);
        } else if (strcmp(*arg, "--list-devices") == 0) {
            list_joysticks();
            exit(0);
        } else if (strcmp(*arg, "--version") == 0) {
            printf("%s\n", PACKAGE_VERSION);
            exit(0);
        } else if (strcmp(*arg, "--help") == 0) {
            printf(COPYRIGHT_NOTICE, PACKAGE_VERSION, OS_NAME_2, ARCH_NAME_2);
            printf(EXTRA_HELP_TEXT);
            exit(0);
        }
        arg++;
    }

    fs_init();
    int error = fs_data_init("fs-uae", "fs-uae.dat");
    if (error) {
        printf("WARNING: error (%d) loading fs-uae.dat\n", error);
    }

    fs_set_prgname("fs-uae");
    fs_set_application_name("Amiga Emulator");

    amiga_set_log_function(log_to_libfsemu);

    //result = parse_options(argc, argv);

    printf(COPYRIGHT_NOTICE, PACKAGE_VERSION, OS_NAME_2, ARCH_NAME_2);
    fs_log(COPYRIGHT_NOTICE, PACKAGE_VERSION, OS_NAME_2, ARCH_NAME_2);

    char *current_dir = g_get_current_dir();
    fs_log("current directory is %s\n", current_dir);
    g_free(current_dir);

    amiga_init();

#if 0
    // FIXME: disabling fullscreen spaces must be done before
    // SDL_INIT_VIDEO, but we need to check config to see if this should
    // be done, and we initialize SDL early to check for config file
    // (catch 22)...
    // FIXME: check fullscreen_spaces option
    SDL_SetHint(SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES, "0");
#endif

#ifdef MACOSX
    SDL_Init(SDL_INIT_EVERYTHING);
    SDL_PumpEvents();
    SDL_Event event;
    fs_log("OS X: Check for pending SDL_DROPFILE event\n");
    while (SDL_PollEvent(&event)) {
        fs_log("Got SDL event 0x%x\n", event.type);
        if (event.type == SDL_DROPFILE) {
            if (event.drop.file != NULL) {
                g_fs_uae_config_file_path = strdup(event.drop.file);
            }
            SDL_free(event.drop.file);
        }
    }
#endif

    // skip first entry
    arg = argv + 1;
    if (g_fs_uae_config_file_path == NULL) {
        while (arg && *arg) {
            const gchar *test_path = *arg;
            if (test_path && fs_path_exists(test_path)) {
                if (check_extension(test_path, ".fs-uae")) {
                    g_fs_uae_config_file_path = g_strdup(test_path);
                } else if (check_extension(test_path, ".conf")) {
                    g_fs_uae_config_file_path = g_strdup(test_path);
                } else if (check_extension(test_path, ".adf")) {
                    g_fs_uae_disk_file_path = g_strdup(test_path);
                } else if (check_extension(test_path, ".ipf")) {
                    g_fs_uae_disk_file_path = g_strdup(test_path);
                } else if (check_extension(test_path, ".dms")) {
                    g_fs_uae_disk_file_path = g_strdup(test_path);
                }
            }
            arg++;
        }
    }

    /* Parse options first, in case base_dir, logging  options etc is
     * specified on the command line. */
    fs_config_parse_options(argc - 1, argv + 1);

    fs_log("\n");
    fs_log(LOG_LINE);
    fs_log("libfsemu init\n");
    fs_log(LOG_LINE);
    fs_log("\n");

    fs_emu_path_set_expand_function(fs_uae_expand_path);

    fs_emu_init_overlays(overlay_names);
    fs_emu_init();

    // then load the config file
    load_config_file();

    init_i18n();

    if (g_fs_uae_disk_file_path) {
        fs_config_set_string(OPTION_FLOPPY_DRIVE_0, g_fs_uae_disk_file_path);
        g_warn_about_missing_config_file = 0;
    }

    if (g_warn_about_missing_config_file) {
        fs_emu_warning(_("No configuration file was found"));
    }

    fs_log("\n");
    fs_log(LOG_LINE);
    fs_log("fs-uae init\n");
    fs_log(LOG_LINE);
    fs_log("\n");

    configure_logging(fs_config_get_const_string("log"));
    fs_emu_set_state_check_function(amiga_get_state_checksum);
    fs_emu_set_rand_check_function(amiga_get_rand_checksum);

    // force creation of some recommended default directories
    fs_uae_kickstarts_dir();
    fs_uae_configurations_dir();
    fs_uae_init_path_resolver();

    fs_uae_plugins_init();

    // must be called early, before fs_emu_init -affects video output
    fs_uae_configure_amiga_model();

    // force creation of state directories
    //fs_uae_flash_memory_dir();
    //fs_uae_save_states_dir();
    //fs_uae_floppy_overlays_dir();
    fs_uae_state_dir();

    const char *controllers_dir = fs_uae_controllers_dir();
    if (controllers_dir) {
        fs_emu_set_controllers_dir(controllers_dir);
    }
    const char *logs_dir = fs_uae_logs_dir();
    if (logs_dir) {
        char *log_file;

        log_file = g_build_filename(logs_dir, "FS-UAE.log", NULL);
        if (fs_path_exists(log_file)) {
            g_unlink(log_file);
        }
        g_free(log_file);

        log_file = g_build_filename(logs_dir, "FS-UAE.log.txt", NULL);
        if (fs_path_exists(log_file)) {
            g_unlink(log_file);
        }
        g_free(log_file);

        log_file = g_build_filename(logs_dir, "Emulator.log.txt", NULL);
        if (fs_path_exists(log_file)) {
            g_unlink(log_file);
        }
        g_free(log_file);

        log_file = g_build_filename(logs_dir, "fs-uae.log.txt", NULL);
        fs_config_set_log_file(log_file);
        g_free(log_file);
    }

    fs_config_set_string_if_unset("themes_dir", fs_uae_themes_dir());

    fs_emu_set_pause_function(pause_function);

    //fs_uae_init_input();
    fs_emu_init_2(FS_EMU_INIT_EVERYTHING);

    // we initialize the recording module either it is used or not, so it
    // can delete state-specific recordings (if necessary) when states are
    // saved
    fs_uae_init_recording();

    int deterministic_mode = 0;
    const char* record_file = fs_config_get_const_string("record");
    if (record_file) {
        fs_log("record file specified: %s, forcing deterministic mode\n",
            record_file);
        deterministic_mode = 1;
        fs_uae_enable_recording(record_file);
    } else {
        fs_log("not running in record mode\n");
    }
    if (fs_emu_netplay_enabled() ||
            fs_config_get_boolean(OPTION_DETERMINISTIC) == 1) {
        deterministic_mode = 1;
    }
    if (deterministic_mode) {
        amiga_set_deterministic_mode();
    }

    if (logs_dir) {
        if (fs_emu_netplay_enabled()) {
            char *sync_log_file = g_build_filename(logs_dir,
                    "Synchronization.log", NULL);
            amiga_set_synchronization_log_file(sync_log_file);
            free(sync_log_file);
        }
    }

#ifdef FS_EMU_DRIVERS
    fs_emu_audio_stream_options **options = fs_emu_audio_alloc_stream_options(2);
    options[0]->frequency = fs_emu_audio_output_frequency();
    /* 12 * 2352 is CDDA_BUFFERS * 2352 (blkdev_cdimage.cpp) */
    options[1]->buffer_size = 12 * 2352;
    // begin playing with only one buffer queued
    options[1]->min_buffers = 1;
    fs_emu_audio_configure(options);
    amiga_set_audio_buffer_size(options[0]->buffer_size);
    fs_emu_audio_free_stream_options(options);
#else
    // this stream is for paula output and drive clicks
    // FIXME: could mix drive clicks in its own stream instead, -might
    // give higher quality mixing
    fs_emu_audio_stream_options options;
    options.struct_size = sizeof(fs_emu_audio_stream_options);
    fs_emu_init_audio_stream_options(&options);
    options.frequency = fs_emu_audio_output_frequency();
    fs_emu_init_audio_stream(0, &options);
    amiga_set_audio_buffer_size(options.buffer_size);

    // this stream is for CD audio output (CDTV/CD32)
    fs_emu_init_audio_stream_options(&options);
    // 12 * 2352 is CDDA_BUFFERS * 2352 (blkdev_cdimage.cpp)
    options.buffer_size = 12 * 2352;
    // begin playing with only one buffer queued
    options.min_buffers = 1;
    fs_emu_init_audio_stream(1, &options);
#endif

    amiga_set_audio_callback(audio_callback_function);
    amiga_set_cd_audio_callback(audio_callback_function);
    amiga_set_event_function(event_handler);

    amiga_set_led_function(led_function);
    amiga_on_update_leds(on_update_leds);

    amiga_set_media_function(media_function);
    amiga_set_init_function(on_init);

    if (fs_config_get_boolean(OPTION_JIT_COMPILER) == 1) {
        amiga_init_jit_compiler();
    }

#ifdef WITH_LUA
    amiga_init_lua(fs_emu_acquire_lua, fs_emu_release_lua);
    amiga_init_lua_state(fs_emu_get_lua_state());
    fs_uae_init_lua_state(fs_emu_get_lua_state());
#endif

    if (fs_emu_get_video_format() == FS_EMU_VIDEO_FORMAT_RGBA) {
        amiga_set_video_format(AMIGA_VIDEO_FORMAT_RGBA);
    } else if (fs_emu_get_video_format() == FS_EMU_VIDEO_FORMAT_BGRA) {
        amiga_set_video_format(AMIGA_VIDEO_FORMAT_BGRA);
    } else if (fs_emu_get_video_format() == FS_EMU_VIDEO_FORMAT_R5G6B5) {
        amiga_set_video_format(AMIGA_VIDEO_FORMAT_R5G6B5);
    } else if (fs_emu_get_video_format() == FS_EMU_VIDEO_FORMAT_R5G5B5A1) {
        amiga_set_video_format(AMIGA_VIDEO_FORMAT_R5G5B5A1);
    } else {
        fs_emu_warning("Unsupported video format requested");
    }
    amiga_add_rtg_resolution(672, 540);
    amiga_add_rtg_resolution(960, 540);
    amiga_add_rtg_resolution(672 * 2, 540 * 2);
    amiga_add_rtg_resolution(fs_emu_get_windowed_width(),
            fs_emu_get_windowed_height());
    amiga_add_rtg_resolution(fs_emu_get_fullscreen_width(),
            fs_emu_get_fullscreen_height());
    fs_uae_init_video();

    //fs_uae_init_keyboard();
    fs_uae_init_mouse();
    fs_uae_configure_menu();

    fs_emu_run(main_function);
    fs_log("fs-uae shutting down, fs_emu_run returned\n");
    if (g_rmdir(fs_uae_state_dir()) == 0) {
        fs_log("state dir %s was removed because it was empty\n",
                fs_uae_state_dir());
    }
    else {
        fs_log("state dir %s was not removed (non-empty)\n",
                fs_uae_state_dir());
    }
    fs_log("end of main function\n");
    cleanup_old_files();

#ifdef WITH_CEF
    cef_destroy();
#endif
    return 0;
}
Ejemplo n.º 7
0
int fs_emu_font_render(fs_emu_font *font, const char *text, float x, float y,
        float r, float g, float b, float alpha) {
    if (font == NULL || font->image == NULL) {
        return 0;
    }
    if (text == NULL || *text == '\0') {
        return 0 ;
    }
    if (!g_initialized) {
        initialize();
    }

    // find cached text entry, if any
    GList* list = g_cache;
    while (list) {
        cache_item *item = (cache_item *) list->data;
        if (item->font == font && strcmp(item->text, text) == 0) {
            break;
        }
        list = list->next;
    }
    if (list) {
        cache_item *item = (cache_item *) list->data;
        g_cache = g_list_delete_link(g_cache, list);
        sanity_check();
        fs_gl_blending(1);
        fs_gl_texturing(1);
        //fs_emu_ortho();
        //fs_emu_set_texture(NULL);
        fs_gl_bind_texture(g_text_texture);
        //glColor4f(1.0, 1.0, 1.0, alpha);
        //printf("rendering %f %f %f %f...\n", item->x1, item->x2, item->y1, item->y2);
        fs_gl_color4f(r, g, b, alpha);
        //glColor4f(r * alpha, g * alpha, b * alpha, alpha);

#ifdef USE_GLES
        GLfloat tex[] = {
            item->x1, item->y2,
            item->x2, item->y2,
            item->x2, item->y1,
            item->x1, item->y1
        };
        GLfloat vert[] = {
            x, y,
            x + item->width, y,
            x + item->width, y + item->height,
            x, y + item->height
        };

        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);

        glVertexPointer(2, GL_FLOAT, 0, vert);
        glTexCoordPointer(2, GL_FLOAT, 0, tex);
        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

        glDisableClientState(GL_VERTEX_ARRAY);
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
#else
        glBegin(GL_QUADS);
        glTexCoord2f(item->x1, item->y2);
        glVertex2f(x, y);
        glTexCoord2f(item->x2, item->y2);
        glVertex2f(x + item->width, y);
        glTexCoord2f(item->x2, item->y1);
        glVertex2f(x + item->width, y + item->height);
        glTexCoord2f(item->x1, item->y1);
        glVertex2f(x, y + item->height);
        glEnd();
#endif

        g_cache = g_list_prepend(g_cache, item);
        sanity_check();
        return item->width;
    }

    // calculate size of text

    //printf(":: %s\n", text);

    int num_chars = 0;
    int required_width = 0;
    int required_height = font->h;

    //char *base_text = fs_utf8_strup(text, -1);
    const char *base_text = text;

    unsigned const char *c = (unsigned const char*) base_text;
    int continuations = 0;
    int cp = 0;
    while(*c) {
        //if ((*c & 0b10000000) == 0b00000000) {
        if ((*c & 0x80) == 0x0) {
            continuations = 0;
            //cp = *c & 0b01111111;
            cp = *c & 0x7f;
        }
        //else if ((*c & 0b11000000) == 0b10000000) {
        else if ((*c & 0xc0) == 0x80) {
            continuations--;
            cp = cp << 6;
            //cp = cp | (*c & 0b00111111);
            cp = cp | (*c & 0x3f);
        }
        //else if ((*c & 0b11111110) == 0b11111100) { // 1111110x
        else if ((*c & 0xfe) == 0xfc) { // 1111110x
            continuations = 5;
            //cp = *c & 0b00000001;
            cp = *c & 0x1;
        }
        //else if ((*c & 0b11111100) == 0b11111000) { // 111110xx
        else if ((*c & 0xfc) == 0xf8) { // 111110xx
            continuations = 4;
            //cp = *c & 0b00000011;
            cp = *c & 0x3;
        }
        //else if ((*c & 0b11111000) == 0b11110000) { // 11110xxx
        else if ((*c & 0xf8) == 0xf0) { // 11110xxx
            continuations = 3;
            //cp = *c & 0b00000111;
            cp = *c & 0x7;
        }
        //else if ((*c & 0b11110000) == 0b11100000) { // 1110xxxx
        else if ((*c & 0xf0) == 0xe0) { // 1110xxxx
            continuations = 2;
            //cp = *c & 0b00001111;
            cp = *c & 0xf;
        }
        //else if ((*c & 0b11100000) == 0b11000000) { // 110xxxxx
        else if ((*c & 0xe0) == 0xc0) { // 110xxxxx
            continuations = 1;
            //cp = *c & 0b00011111;
            cp = *c & 0x1f;
        }

        ++c;
        if (continuations) {
            continue;
        }

        cp = fix_char(font, cp);
        //printf("%d\n", cp);
        if (required_width + font->w[cp] > g_texture_width) {
            break;
        }
        required_width += font->w[cp];
        num_chars++;
    }

    int dx = 0;
    int dy = 0;
    c = (unsigned const char*) base_text;
    //printf("base_text: %s\n", c);
    continuations = 0;
    cp = 0;
    int k = 0;
    while(*c) {
        //printf("%d\n", *c);
        //if ((*c & 0b10000000) == 0b00000000) {
        if ((*c & 0x80) == 0x0) {
            continuations = 0;
            //cp = *c & 0b01111111;
            cp = *c & 0x7f;
        }
        //else if ((*c & 0b11000000) == 0b10000000) {
        else if ((*c & 0xc0) == 0x80) {
            continuations--;
            cp = cp << 6;
            //cp = cp | (*c & 0b00111111);
            cp = cp | (*c & 0x3f);
        }
        //else if ((*c & 0b11111110) == 0b11111100) { // 1111110x
        else if ((*c & 0xfe) == 0xfc) { // 1111110x
            continuations = 5;
            //cp = *c & 0b00000001;
            cp = *c & 0x1;
        }
        //else if ((*c & 0b11111100) == 0b11111000) { // 111110xx
        else if ((*c & 0xfc) == 0xf8) { // 111110xx
            continuations = 4;
            //cp = *c & 0b00000011;
            cp = *c & 0x3;
        }
        //else if ((*c & 0b11111000) == 0b11110000) { // 11110xxx
        else if ((*c & 0xf8) == 0xf0) { // 11110xxx
            continuations = 3;
            //cp = *c & 0b00000111;
            cp = *c & 0x7;
        }
        //else if ((*c & 0b11110000) == 0b11100000) { // 1110xxxx
        else if ((*c & 0xf0) == 0xe0) { // 1110xxxx
            continuations = 2;
            //cp = *c & 0b00001111;
            cp = *c & 0xf;
        }
        //else if ((*c & 0b11100000) == 0b11000000) { // 110xxxxx
        else if ((*c & 0xe0) == 0xc0) { // 110xxxxx
            continuations = 1;
            //cp = *c & 0b00011111;
            cp = *c & 0x1f;
        }

        ++c;
        if (continuations) {
            continue;
        }

        if (++k > num_chars) {
            // there may be more chars left in the original string,
            // but there is no room for the next char in the texture
            break;
        }

        cp = fix_char(font, cp);

        int sx = font->x[cp];
        int sy = font->y[cp];
        int sw = font->w[cp];
        int sh = font->h;

        //if (c > 256) {
        //    printf("%d %d %d %d %d\n", c, sx, sy, sw, sh);
        //}

        // draw character
        //printf("-----------> %d\n", cp);

        int *sl = ((int *) font->image->data) + font->image->width * sy + sx;
        int ss = font->image->width; // source stride
        //int *sl = sp;
        int *dl = ((int *) g_buffer) + g_texture_width * dy + dx;
        int ds = g_texture_width; // destination stride
        //int *dl = dp;

        for (int y = 0; y < sh; y++) {
            //printf("%d\n", y);
            int *sp = sl;
            int *dp = dl;
            for (int x = 0; x < sw; x++) {
                //printf("%d %d\n", x, y);
                //*dp++ = 0xff0000ff;
                //*dp++ = *sp++;
                int a = *sp;
                sp++;
                *dp = a;
                dp++;
                //int a = *sp++;
            }
            sl += ss;
            dl += ds;
        }

        dx += sw;
    }
    //free(utext);
    //free(base_text);

    GList *last = g_list_last(g_cache);
    cache_item *last_item = (cache_item *) last->data;
    int position = last_item->position;

    fs_gl_bind_texture(g_text_texture);
    int gl_buffer_format = GL_RGBA;
    if (fs_emu_get_video_format() == FS_EMU_VIDEO_FORMAT_BGRA) {
        gl_buffer_format = GL_BGRA;
    }
#ifdef USE_GLES
    /* GLES does not support unpack padding of buffer. we have to update line-wise (or create a new one) */
    uint8_t *buf = g_buffer;
    for(int y=0;y<required_height;y++) {
        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, position * 32 + y, required_width,
                1, gl_buffer_format, GL_UNSIGNED_BYTE, buf);
        buf += g_texture_width * 4;
    }
#else
    fs_gl_unpack_row_length(g_texture_width);
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, position * 32, required_width,
            required_height, gl_buffer_format, GL_UNSIGNED_BYTE, g_buffer);
#endif

    cache_item *item = malloc(sizeof(cache_item));
    item->font = font;
    item->text = g_strdup(text);
    item->width = required_width;
    item->height = required_height;
    item->position = position;

    item->x1 = 0;
    item->x2 = required_width / (1.0 * g_texture_width);
    item->y1 = (item->position * 32) / (1.0 * g_texture_height);
    item->y2 = (item->position * 32 + required_height) /
            (1.0 * g_texture_height);
    //item->texture = render_texture;
    g_cache = g_list_prepend(g_cache, item);
    sanity_check();

    if (last_item->text) {
        free(last_item->text);
    }
    /*
    if (last_item->texture) {
        glDeleteTextures(1, &last_item->texture);
    }
    */
    free(last_item);

    g_cache = g_list_delete_link(g_cache, last);
    sanity_check();

    // now the text is in the cache, so call function again
    return fs_emu_font_render(font, text, x, y, r, g, b, alpha);
}
Ejemplo n.º 8
0
fs_emu_texture *fs_emu_texture_new_from_file(const char *name) {
    char *full_name;
    char *path;
    if (fs_path_exists(name)) {
        full_name = fs_strdup(name);
        path = fs_strdup(name);
    }
    else {
        full_name = fs_strconcat(name, ".png", NULL);
        path = fs_get_program_data_file(full_name);
        if (path == NULL) {
            fs_emu_warning("Could not find texture %s\n", full_name);
            return NULL;
        }
    }
    fs_image *image = fs_image_new_from_file(path);
    fs_emu_log("loading texture \"%s\"\n", path);
    free(path);
    if (image == NULL) {
        fs_emu_warning("Could not load texture from %s\n", full_name);
        free(full_name);
        return NULL;
    }
    free(full_name);

    if (fs_emu_get_video_format() == FS_EMU_VIDEO_FORMAT_BGRA) {
        // convert to premultiplied alpha
        if (image->format == FS_IMAGE_FORMAT_RGBA) {
            int num_pixels = image->width * image->height;
            unsigned char *pixels = image->data;
            for (int i = 0; i < num_pixels; i++) {
                unsigned char alpha = pixels[3];
                unsigned char temp = pixels[2];
                pixels[2] = ((int) pixels[0]) * alpha / 255;
                pixels[1] = ((int) pixels[1]) * alpha / 255;
                pixels[0] = ((int) temp) * alpha / 255;
                pixels += 4;
            }
        }
        else {
            // FIXME: should swap R and B here...
        }
    }
    else {
        // convert to premultiplied alpha
        if (image->format == FS_IMAGE_FORMAT_RGBA) {
            int num_pixels = image->width * image->height;
            unsigned char *pixels = image->data;
            for (int i = 0; i < num_pixels; i++) {
                unsigned char alpha = pixels[3];
                // should really divide by 255, but 256 is faster...
                //pixels[0] = ((int) pixels[0]) * alpha / 256;
                //pixels[1] = ((int) pixels[1]) * alpha / 256;
                //pixels[2] = ((int) pixels[2]) * alpha / 256;
                pixels[0] = ((int) pixels[0]) * alpha / 255;
                pixels[1] = ((int) pixels[1]) * alpha / 255;
                pixels[2] = ((int) pixels[2]) * alpha / 255;
                //pixels[0] = (unsigned char) ((pixels[0] * alpha + 0.5) / 255.0);
                //pixels[1] = (unsigned char) ((pixels[1] * alpha + 0.5) / 255.0);
                //pixels[2] = (unsigned char) ((pixels[2] * alpha + 0.5) / 255.0);
                pixels += 4;
            }
        }
    }

    fs_emu_texture *texture = fs_new(fs_emu_texture, 1);
    texture->width = image->width;
    texture->height = image->height;
    texture->image = image;
    load_texture(texture);
    fs_emu_set_texture(texture);

    fs_gl_add_context_notification(context_notification_handler, texture);

    return texture;
}