存档在 2009年11月5日

C++常见错误之一   new[]与delete[]

2009年11月5日

int *data;

data=new int[100];

delete data;

以上程序在Visual C++ 6.0中是正确的,然而在最新的ANSI/ISO C++标准中,它却是错误的。

在以往的日子里,我也一直这么写。昨日在使用CodeGuard除错,发现在delete data一行时报告资源类型不匹配。一查CodeGuard报告,提示使用new []形式创建的资源要使用delete []释放。所以正确的程序应该如下:

int *data;

data=new int[100];

delete[] data;

以上的程序在 Borland C++ Builder 6 中测试通过,CodeGuard对未修改的错误程序报告如下:

Error 00019. 0x350010 (Thread 0x04F4):
Resource type mismatch: a(n) object was expected.
delete(0x00CF5244)

Call Tree:
0x004011C0(=NDTest.exe:0x01:0001C0) D:\Program Files\Borland\CBuilder6\Projects\NDTest\MainUnit.cpp#15
0x3266FFB3(=CC3260.DLL:0x01:06EFB3)

The object array (0x00CF5244) [size: 400 bytes] was created with new[]
Call Tree:
0x004011B4(=NDTest.exe:0x01:0001B4) D:\Program Files\Borland\CBuilder6\Projects\NDTest\MainUnit.cpp#13
0x3266FFB3(=CC3260.DLL:0x01:06EFB3)

——————————————
Functions called:
delete (25 times)
realloc (1 times)
memcpy (1 times)
delete[] (2 times)
free (15 times)
new[] (15 times)
new (29 times)
calloc (5 times)
malloc (9 times)
Resource types used:
object array (15 allocs, 14 max)
object (29 allocs, 17 max)
memory block (15 allocs, 10 max)
Modules used:
00400000 05/13/2003 10:56:46 D:\Program
Files\Borland\CBuilder6\Projects\NDTest\NDTest.exe
0CD00000 01/30/2002 17:38:38 D:\PROGRA~1\Borland\CBUILD~1\Bin\CG32.DLL
32600000 01/30/2003 06:04:00 D:\PROGRA~1\Borland\CBUILD~1\Bin\CC3260.DLL
65D20000 07/22/2002 12:05:04 C:\WINNT\System32\USP10.dll
6C330000 07/22/2002 12:05:04 C:\WINNT\System32\LPK.DLL
75E00000 07/22/2002 12:05:04 C:\WINNT\System32\IMM32.DLL
77D90000 11/11/2002 15:33:44 C:\WINNT\system32\ADVAPI32.DLL
77DF0000 11/04/2002 10:58:50 C:\WINNT\system32\USER32.DLL
77E60000 11/04/2002 10:58:54 C:\WINNT\system32\KERNEL32.DLL
77F40000 07/23/2002 16:34:08 C:\WINNT\system32\GDI32.dll
77F80000 04/04/2003 15:47:22 C:\WINNT\system32\ntdll.dll
786F0000 11/20/2002 16:53:24 C:\WINNT\system32\RPCRT4.dll
==========================================

Win32多线程C程序示例

2009年11月5日

// Win32 多线程示例
// 网址: http://www.hyzgame.com
//————————————————————————————————–
#include <windows.h>
#include <iostream.h>
//————————————————————————————————–
DWORD WINAPI Print123(void *)
{
int i;

for(i=0;i<10;i++)
cout<<“123″<<endl;

return(0);
}

//————————————————————————————————–
DWORD WINAPI PrintABC(void *)
{
int i;

for(i=0;i<10;i++)
cout<<“ABC”<<endl;

return(0);
}
//————————————————————————————————–
DWORD WINAPI Printabc(void *)
{
int i;

for(i=0;i<10;i++)
cout<<“abc”<<endl;

return(0);
}
//————————————————————————————————–
int main(int argc,char **argv)
{
HANDLE handles[3];
DWORD  ids[3];

handles[0]=CreateThread(NULL,0,Print123,NULL,NULL,&ids[0]);
handles[1]=CreateThread(NULL,0,PrintABC,NULL,NULL,&ids[1]);
handles[2]=CreateThread(NULL,0,Printabc,NULL,NULL,&ids[2]);

WaitForMultipleObjects(3,handles,true,INFINITE);

CloseHandle(handles[0]);
CloseHandle(handles[1]);
CloseHandle(handles[2]);

return(0);
}

堆排序算法C源程序

2009年11月5日

#include<stdio.h>
#include<stdlib.h>

void isift(int *p,int i,int n)
{
int j,t;

t=p[i];
j=2*(i+1)-1;

while(j<=n)
{
if((j<n)&&(p[j]<p[j+1]))j++;

if(t<p[j])
{
p[i]=p[j];
i=j;
j=2*(i+1)-1;
}
else j=n+1;
}

p[i]=t;
return;
}

void pihap(int *p,int n)
{
int i,mm,t;

mm=n/2;
for(i=mm-1;i>=0;i–)
isift(p,i,n-1);

for(i=n-1;i>=1;i–)
{
t=p[0];
p[0]=p[i];
p[i]=t;

isift(p,0,i-1);
}

return;
}

void main(int argc,char *argv[])
{
int i;
int data[32];

printf(“未排序:”);
for(i=0;i<32;i++)
printf(“%d,”,data[i]=rand()%100);

pihap(data,32);

printf(“\n已排序:”);
for(i=0;i<32;i++)
printf(“%d,”,data[i]);
}

如何安装Turbo C++ 3.0 for DOS

2009年11月5日

一、运行安装盘下的Install.EXE,运行后界面如下:

Image1

二、按Enter键继续

Image2

三、此时安装程序会要求你输入安装盘的盘符,输入后按回车

Image3

四、此时输入安装文件的路径,一般直接按回车

Image4

五、此页是安装选项,第一项是选择安装后的路径,第二项不用管它,最后选择第三项按回车

如何使用“Dev-C++ 5.0 (4.9.6.0)”

2009年11月5日

Dev-C++ 5.0是Bloodshed软件公司于2002年9月26日推出的一个基于MingW(即GNU C/C++的Win32版)的微型C/C++开发工具。

由于使用了GNU C/C+内核,所以在做软件移植时非常的方便,你可以方便的将一个程序移植到任意一个有GNU C/C++的平台。而 且由于基于GNU C/C++的开放源代码软件很多,所以使用Dev-C++是一个很好的选择。但由于它的调试不便,帮助不全等问题,也使得它在推广上举步艰难,远比不上 Borland C/C++、OpenWatcom C/C++这两个同是免费的编译器。

一、下载

你可以从官方网站下载。由于它是个GNU软件,所以在它的使用上,您需要遵守GPL协议。

官方网站

二、安装

运行安装程序后,界面如下:

Image1

这页是GPL协议,如果您同意的话,点“I Agree”按钮可以继续安装,按“Cancel”放弃安装。

Image2

在这一界面上要以选择需要安装的文件,由于这个软件仅33MB,所以我们可以直接点击“Next >”继续安装。

Image3

在这一界面上选择安装目录,选好后按“Install”开始安装。

三、选择界面语种

运行Dev-C++ 5.0后,界面如下:

Image4

在Tools菜单选择“Enviroment Options”,在出现的对话框的“Interface”页内,在“Language”处选择“Chinese”。如下图。

Image6

点击“OK”后界面将变为中文,如下图:

四、建立项目

下面我们就可以建立一个项目了,在“文件”菜单中选“新建”,再选“项目”,然后的选择见下图:

Image7

点击“确定”,然后选择保存目录。完成后按Ctrl+F10就行了。

如何使用“OpenWatcom C/C++ 1.0(0.85)”

2009年11月5日

说到OpenWatcom,我们不得不提一下Watcom。

Watcom系统编译器是加拿大Watcom公司开发的Intel x86体系16/32位编译器,其最新版是11.0c。

Watcom C/C++的集成开发环境极差,不像Borland C/C++和Visual C/C++那样有漂亮的界面,编译连结不过轻轻一点。Watcom C/C++的大部分使用者都在命令行下编译程序。想想吧!一个需要在命令行下编译程序的编译器,怎么匹敌Borland C/C++和Visual C/C++,甚至是C++ Builder呢?

当然,编译器的好坏并不能单单从使用方便使用上来比较,专业的程序员最关心的是目标程序的质量。Watcom系列编译器相比Borland编译器和Microsoft编译器有一个最大的优势,那便是速度:用Watcom C/C++编译出来的程序在速度上远远超越(记住,不是一点儿,是超越了许多)了Borland C/C++和Microsoft Visual C/C++编译出来的程序。这样一来,即使是没有集成开发环境,程序员们也认了。这也是不少游戏程序员亲昧于这个编译器的原因。

现在我们所用到的OpenWatcom C/C++ 1.0便是Watcom C/C++ 11.0c开放后的版本,它是免费、而且开放源码的。

一、下载与安装

在下载前,请选阅读它的授权协议。

官方网站

下载后直接解压到某个盘的根目录即可,推荐解压后目录为“C:\OpenWatcom”。

二、配置

由于OpenWatcom C/C++支持的平台相当多,所以针对不同的平台有不同的配置。主要在于系统变置的不同,这里主要讲一下针对32位DOS和Windows的配置:

32位DOS平台配置

WATCOM=C:\OpenWatcom
PATH=C:\OpenWatcom\Binw
INCLUDE=C:\OpenWatcom\H
LIBPATH=C:\OpenWatcom\LIB386
EDPATH=C:\OpenWatcom\EDDAT

●32位Windows配置

WATCOM=C:\OpenWatcom
PATH=C:\OpenWatcom\Binnt
INCLUDE=C:\OpenWatcom\H;C:\OpenWatcom\H\NT
LIBPATH=C:\OpenWatcom\LIB386;C:\OpenWatcom\LIB386\NT
EDPATH=C:\OpenWatcom\EDDAT

三、编译程序

OpenWatcom C/C++编译程序方法和Watcom C/C++ 11.0一致。

编译一个基于DOS/4GW的程序:wcl386 -l=dos4g hello.c

编译一个基于WindowsNT字符模式的程序:wcl386 -l=nt hello.c

编译一个基于WindowsNT窗口模式的程序:wcl386 -l=nt_win hello.c

编译一个基于Windows95的程序:wcl386 -l=win95 hello.c

如何使用“Borland C/C++ 5.5.1 for Win32”

2009年11月5日

“Borland C/C++ 5.5.1 for Win32”是Borland公司在2000年免费放出的一个C/C++编译器,其功能完整、包含多种SDK,且容量极小,安装版本大小仅8MB。 Borland公司现在的旗舰级产品“C++ Builder 5”内置的就是这一编译器,最新的“C++ Builder 6”内置的为“Borland C/C++ 5.6”。

它的免费仅适用于非盈利性软件的开发,以及教学使用。

由于没有集成开发环境,所以对某些开发者来说使用可能比较困难,在这里,我特地向这些开发者讲叙它的使用。

一、下载

下载地址

二、安装

运行安装程序,界面如下:

Image1

点击“下一步(N) >”按钮,出现以下界面:

Image2

在这一界面内选择安装路径,一般使用默认路径,点击“完成”完成安装。

三、建立配置文件

这里所说的配置文件是可建可不建的,但建议建立较好。

在C:\Borland\BCC55\bin目录内建立文本文件,并更名为bcc32.cfg,使用编辑工具打开这个文件,并输入以下内容:

-I”C:\Borland\BCC55\include”
-L”C:\Borland\BCC55\lib”

在同一目录内建立ilink32.cfg,并输入以下内容:

-L”C:\Borland\BCC55\lib”

四、使用

命令行下的程序编译可能大多数人不习惯,但也只能这样用。例如编译程序hello.cpp

BCC32 hello.cpp

FinalBurnAlpha中NEO-GEO游戏驱动程序的编写

2009年11月5日

作者:胡颖卓


二年前我写了《FinalBurn AlphaCPS-2游戏驱动程序的编写》一文,现由于模拟器界的三年原则惯例,所以很久都没有新的CPS-2游戏XOR表出现了。而现今由于SNK的复活,NEO-GEO游戏又慢慢的多了几个出来,所以我特地再为大家撰写这篇文章。

FinalBurn Alpha中,NEO-GEO驱动相比CPS-2驱动写起来较为简易,下面我以SNK PLAYMORE的大作《侍魂 零》为例,告诉各位如何编写它的驱动程序。

打开src\burn\neogeo\d_neogeo.cpp文件。

首先是书写游戏的ROM描述表:

static struct BurnRomInfo samsho5RomDesc[] =
{//    文件名        长度      CRC校验码   类型

{“270-p1.bin”, 0x800000, 0x611A6687, 0x10}, // 0 68K 代码

{“270-s1.bin”, 0x020000, 0x33227D62, 1},    // 1 文字层图片数据

{“270-c1.bin”, 0x800000, 0x4E7BDEA1, 1},    // 2 图片数据
{“270-c2.bin”, 0x800000, 0x7B444985, 1},    // 3
{“270-c3.bin”, 0x800000, 0x8C709A9B, 1},    // 4
{“270-c4.bin”, 0x800000, 0xCFD53F5C, 1},    // 5
{“270-c5.bin”, 0x800000, 0xC026D318, 1},    // 6
{“270-c6.bin”, 0x800000, 0xB3D9D204, 1},    // 7
{“270-c7.bin”, 0x800000, 0xFE03A025, 1},    // 8
{“270-c8.bin”, 0x800000, 0x89DB2D34, 1},    // 9

{“270-m1.bin”, 0x020000, 0x18114FB1, 0x10}, // 10 Z80 代码

{“270-v1.bin”, 0x400000, 0x6849136C, 2},    // 11 声音数据
{“270-v2.bin”, 0x400000, 0x222E1774, 2},    // 12
{“270-v3.bin”, 0x400000, 0xCD9E7ADC, 2},    // 13
{“270-v4.bin”, 0x400000, 0x8B305CAC, 2},    // 14

};

接下来是驱动的描述:

STDROMPICKEXT(samsho5, samsho5, neogeo);
STD_ROM_FN(samsho5);

struct BurnDriver BurnDrvSamSho5 =
{

{

“samsho5”,                //ROM文件名称
“Samurai Shodown V”,      //游戏名称
“”,                       //其它信息
“SNK Playmore”,           //游戏开发商
“Neo Geo”,                //游戏机型说明
“2003”,                   //游戏发行年代
NULL,                     //游戏主ROM名称
“neogeo”                  //游戏BIOS

},

BDF_GAME_WORKING,
2,                             //游戏人数
HARDWARE_SNK_NEOGEO | HARDWARE_SNK_SWAPP | HARDWARE_SNK_SWAPC | HARDWARE_SNK_SRAM,
NULL,
samsho5RomInfo,                //ROM信息
samsho5RomName,                //ROM名称
neogeoInputInfo,
neogeoDIPInfo,
NeoInit,
NeoExit,
NeoFrame,
NeoRender,
NeoScan,
&NeoRecalcPalette,
nNeoScreenWidth,
224,
4,3

};

最后我们只需要在src\generated\driverlist.h中加入相应的项就可以了,祝大家玩的愉快!


FinalBurn Alpha 0.2.9x 中CPS2游戏驱动程序的编写

2009年11月5日

作者:胡颖卓


FinalBurn Alpha是当今最好的CPS1/2模拟器之一,更可贵的是它是完全开放源码的。从FinalBurn Alpha 2.93开始,FinalBurn Alpha小组(以后简称FBA小组)便转向了多功能、多机种的支持,而不是像其它模拟器那样,出一个新游戏的破解就出一个新版,或是有一点儿改进就出一个新版。这样做利了开发者,而玩家却是觉得有些不便。

起初,我为大家写一些新版本的FBA,但这样会和FBA小组的版本对应不上。更是近来,我需要将主要精力放在网络游戏上,所以也没有太多的时间为大家写这些驱动。在这里,我针对FinalBurn Alpha 2.93CPS2游戏19xx驱动为例,给大家做一下讲解,以便大家能自己写出新的驱动。

首先,要包含驱动头文件cps.h,语句如下:

#include”cps.h”

再者,是输入设备定义,也不用讲解,照例子抄就行了:

static struct BurnInputInfo DrvInputList[] =
{
{“P1 Coin”  , 0, CpsInp020+4, “p1 coin”  },
{“P1 Start” , 0, CpsInp020+0, “p1 start” },
{“P1 Up”    , 0, CpsInp001+3, “p1 up”    },
{“P1 Down”  , 0, CpsInp001+2, “p1 down”  },
{“P1 Left”  , 0, CpsInp001+1, “p1 left”  },
{“P1 Right” , 0, CpsInp001+0, “p1 right” },
{“P1 Shot”  , 0, CpsInp001+4, “p1 fire 1”},
{“P1 Bomb”  , 0, CpsInp001+5, “p1 fire 2”},
//19xx是两键游戏,如果是3键游戏,只需要按顺序加上就行了,例如
//{“P1 AutoFire”, 0, CpsInp001+6, “p1 auto fire”},


{“P2 Coin”  , 0, CpsInp020+5, “p2 coin”  },
{“P2 Start” , 0, CpsInp020+1, “p2 start” },
{“P2 Up”    , 0, CpsInp000+3, “p2 up”    },
{“P2 Down”  , 0, CpsInp000+2, “p2 down”  },
{“P2 Left”  , 0, CpsInp000+1, “p2 left”  },
{“P2 Right” , 0, CpsInp000+0, “p2 right” },
{“P2 Shot”  , 0, CpsInp000+4, “p2 fire 1”},
{“P2 Bomb”  , 0, CpsInp000+5, “p2 fire 2”},

{“Reset”      , 0, &CpsReset  , “reset”   },
{“Diagnostic” , 0, CpsInp021+1, “diag”    },
{“Service”    , 0, CpsInp021+2, “service” },
};

STDINPUTINFO(Drv);

也有一种特殊情况,由于CPS2下格斗游戏非常多,而且使用的按键定义方法也一样,比如《少年街霸3》,我们就可以使用以下方法来定义:

STDINPUTINFOSPEC(Drv, CpsFsi);

ROM表的写法我们来看看19XX的写法:

static struct BurnRomInfo NinexxRomDesc[]=
{
//文件名     ,文件长度,CRC校验码 ,类型
{“19xux.03” ,0x80000,0x239a08ae, 0x10}, //  0  XOR 表
{“19xux.04” ,0x80000,0xc13a1072, 0x10}, //  1
{“19xux.05” ,0x80000,0x8c066ec3, 0x10}, //  2
{“19xux.06” ,0x80000,0x4b1caeb9, 0x10}, //  3

{“19xu.03” ,0x80000,0x05955268, 0x10},  //  4  68000 代码 需要上面的进行解密
{“19xu.04” ,0x80000,0x3111ab7f, 0x10},  //  5
{“19xu.05” ,0x80000,0x38df4a63, 0x10},  //  6
{“19xu.06” ,0x80000,0x5c7e60d3, 0x10},  //  7
{“19x.07”  ,0x80000,0x61c0296c, 0x10},  //  8

{“19x.13” ,0x080000,0x427aeb18, 1},     //  9  图像数据,此处要按3,5,7,9,4,6,8,0此类顺序排列
{“19x.15” ,0x080000,0x63bdbf54, 1},     //  10
{“19x.17” ,0x080000,0x2dfe18b5, 1},     //  11
{“19x.19” ,0x080000,0xcbef9579, 1},     //  12
{“19x.14” ,0x200000,0xe916967c, 1},     //  13
{“19x.16” ,0x200000,0x6e75f3db, 1},     //  14
{“19x.18” ,0x200000,0x2213e798, 1},     //  15
{“19x.20” ,0x200000,0xab9d5b96, 1},     //  16

{“19x.01” ,0x020000,0xef55195e, 2},     //  17 QSound数据 z80声音数据

{“19x.11” ,0x200000,0xd38beef3, 2},     //  18 QSound声音采样
{“19x.12” ,0x200000,0xd47c96e2, 2},     //  19
};

STD_ROM_PICK(Ninexx) STD_ROM_FN(Ninexx)

这里面Ninexx是我们自己可以定义的名称,改成_19xx也是可以的。

之后是驱动信息结构,19XX的写法如下:

游戏ROM文件名称,为19xx的话,那对应19xx.zip
游戏名称
注释或其它信息
生产商
机型
出品年代
主ROM名称,例如19xx的西班牙版就需要在这里打上”19xx”
主板BIOS,不使用的话定义为NULL

运行标志,如果为纵版需要加上BDF_ROTATE_GRAPHICS_CCW
最大玩家数量
硬件类型
取zip名称特殊函数
Rom信息结构
Rom名称结构
输入配置信息表
DIP配置表

驱动初始化函数
驱动关闭函数
游戏帧处理函数
游戏刷新函数
游戏剪裁处理函数
游戏调色板空间
游戏画面宽度
游戏画面高度
游戏画面纵横比

struct BurnDriver BurnDrvCps19xx=
{
{“19xx”,
“19XX: The War Against Destiny (US 951207)”,
“”,
“Capcom”,
“CPS2”,
“1995”,
NULL,
NULL},
BDF_GAME_WORKING | BDF_ROTATE_GRAPHICS_CCW,
2,
HARDWARE_CAPCOM_CPS2,
NULL,
NinexxRomInfo,
NinexxRomName,
DrvInputInfo,
NULL,

DrvInit,
DrvExit,
Cps2Frame,
CpsRedraw,
CpsAreaScan,
&CpsRecalcPal,
224,
384,
3,4
};

DrvExit函数我们不用去管它,直接照抄一个就行了,关键在于DrvInit函数。下面我们来看一下19XXDrvInit函数,并为大家做详细的讲解:

static int DrvInit()
{
int nRet=0;
int i=0;
unsigned char *pqs=NULL;

Cps=2;                   //CPS1型游戏为1,CPS2型游戏为2

nCpsRomLen = 5*0x080000; //程序数据长度          对应文件3-10
nCpsCodeLen= 4*0x080000; //需要XOR表解密的长度   对应文件3-10
nCpsGfxLen =  0x1000000; //图象数据长度          对应文件13-20
nCpsZRomLen= 1*0x020000; //QSoundDataZ80数据长度 对应文件1-2
nCpsQSamLen= 2*0x200000; //QSoundSample长度     对应文件11-12

nRet=CpsInit();
if(nRet!=0)return(1);

// 装载程序ROM,这里5为程序ROM数量,4为XOR表ROM数量
for(i=0;i<5;i++)
{nRet=BurnLoadRom(CpsRom+0x080000*i,4+i,1); if (nRet!=0) return 1; }

// 解密程序ROM,这里4为XOR表ROM数量
memcpy(CpsCode,CpsRom,nCpsCodeLen);
for (i=0;i<4;i++)
{ nRet=BurnXorRom(CpsCode+0x080000*i,0+i,1); if (nRet!=0) return 1; }

// 装载图像ROM
nRet=Cps2LoadTiles(CpsGfx          , 9); //每次可以装载4个,后面的数字是ROM的起始编号
nRet=Cps2LoadTiles(CpsGfx+0x0800000,13); //0x0800000为前面4个ROM的总容量

// 装载Z80 ROM
nRet=BurnLoadRom(CpsZRom,17,1); //同上面的,17为起始编号,1为ROM数量,一次只能装载1个

// 装载QSound Samples ROM
pqs=(unsigned char *)CpsQSam;
nRet=BurnLoadRom(pqs         ,18,1); //18为编号,ROM数量仅为1
nRet=BurnLoadRom(pqs+0x200000,19,1); //
BurnByteswap(pqs,nCpsQSamLen);

nRet=CpsRunInit(); if (nRet!=0) return 1;
return 0;
}

至此,以上的讲解已足够大家为新的游戏写出一个驱动了,希望下次Razoola放出新的CPS2游戏XOR表时,大家能够不至于等待谁写出新的驱动,而可以自己解决。

名花十二客

2009年11月5日

宋代张敏叔以十二花为十二客,各赋诗一首。从此以后,十二客即成为画家画题。

    • 牡丹──赏客
    • 梅花──清客
    • 菊花──寿客
    • 瑞香──佳客
    • 丁香──素客
    • 兰花──幽客
    • 莲花──静客
    • 茶花──雅客
    • 桂花──仙客
    • 蔷薇──野客
    • 茉莉──远客
    • 芍药──近客
      鄂ICP备09027626号