在带有C的DOSBOX中没有可用于malloc的内存

时间:2015-12-27 01:47:21

标签: c dos vga

我正在开发一个程序来使用BORLAND 3.1在DOSBOX上使用C创建一个基本的图像编辑器(如paint)。现在我正在尝试实现一个简单的撤消按钮。为此,我创建了一个双数组来存储绘图区域的10倍(即288 * 180)。但是,当添加数组初始化的行时,我无法为我在程序的其他功能中使用的双缓冲区分配内存。

有没有什么方法可以在DOSBOX中获得更多内存或者其他没有给我这个问题的实现?

我按照这样编译我的程序:

bcc -mh paint.c

这是我的代码:

byte huge undo[51840][10];  // This is the array that is giving me problems
void welcome_screen(){
    BITMAP fondo_inicio,normal_ptr_image,boton_inicio,boton_salir;
    MOUSE  mouse_welcome;
    unsigned long int  h;
    int a[2];
    byte *double_buffer;
    sword new_x, new_y;
    word redraw,press,release;
    sword dx,dy=0;
    MOUSEBITMAP *normal_pointer=NULL;
    MOUSEBITMAP *mouse_new=NULL;
    word last_time;

    int i,done = 0;

    filled=-1;

    /* allocate memory for double buffer and background image SCREEN_SIZE = 320*200 */
    if ((double_buffer = (byte *) malloc(SCREEN_SIZE)) == NULL)
    {
        printf("Not enough memory for double buffer.\n"); // ---> This is the error I get when adding the above line
        exit(1);
    }

2 个答案:

答案 0 :(得分:4)

如果你想使用640K以上的内存,你想要做的是使用DPMI,使用DOS扩展器(如CWSDMPI)进行编译,并通过它来分配内存。 DJGPP是GCC的DOS端口,是DOS上最现代的编译器,目前仍在开发中。 (编辑:根据Ross Ridge的说法,DJGPP会自动使用扩展内存和标准库调用。)另一个选项,就是当时大多数商业软件使用的是带有DOS4G / W的Watcom C.今天它可以作为OpenWatcom和DOS / 32扩展器使用。您还需要配置DOSBOX以使XMS可用; 16MiB在1995年是一笔沉重的金额。

答案 1 :(得分:2)

为什么不保留一个屏幕以及随后的10个后续操作,而不是将撤消缓冲区保留为10个全屏位图的数组?然后撤消只是恢复屏幕缓冲区,然后应用随后的9个记忆操作。

那是......

byte undo[288*180]; // one screen of memory representing what the screen looked like 10 operations ago

struct Operation undo_ops[10]; // the last 10 operations since the undo buffer was formed
int undo_ops_count; // number of elements in above array

其中"操作"是这样的:

struct Operation
{
    int x1;
    int y1;
    int x2;
    int y2;
    int size;
    int extra;
    int color;
    enum OpCode code; // Circle, Rectangle, Line, Fill, whatever...
};

然后是一些伪代码,用于"撤消"实际上

void Undo()
{
    if (undo_ops_count > 0)
    {
        undo_ops_count--;  // forget the last operation

        // restore the screen
        memcpy(g_screen_buffer, undo, sizeof(undo));

        // apply the last operations before the last user operation
        for (int x = 0; x < undo_ops_count; x++)
        {
            ApplyOperation(g_screen_buffer, &undo_ops[x]); // re-draw what the user did on top of the restored screen buffer
        }
        RepaintScreen(g_screen_buffer);
    }
}

绘制新内容的每个用户操作都会附加到undo_ops数组中。如果用完undo_ops的数组空间不足,则只需重新绘制新的屏幕缓冲区并删除最旧的操作。我会把它作为锻炼给你。看到它如何释放更多的内存,我敢打赌,你可以记住超过10次操作而不会耗尽内存。