В том-то и дело, что всё работает замечательно, если только в VAR положить правильное количество SHORTCHAR'ов. SDL_FillRect с NIL'ом закрашивает весь экран, как он и должен.
SDL_FillRect принимает вторым параметром указатель на SDL_Rect. SDL_Rect - это struct, внутри которого 4 INTEGER'а. Всё предельно просто и всё равно что-то работает не так.
Вот оригинальный код SDL_FillRect'а (файл «src/video/SDL_fillrect.c»):
Код:
/*
* This function performs a fast fill of the given rectangle with 'color'
*/
int
SDL_FillRect(SDL_Surface * dst, const SDL_Rect * rect, Uint32 color)
{
SDL_Rect clipped;
Uint8 *pixels;
if (!dst) {
return SDL_SetError("Passed NULL destination surface");
}
/* This function doesn't work on surfaces < 8 bpp */
if (dst->format->BitsPerPixel < 8) {
return SDL_SetError("SDL_FillRect(): Unsupported surface format");
}
/* If 'rect' == NULL, then fill the whole surface */
if (rect) {
/* Perform clipping */
if (!SDL_IntersectRect(rect, &dst->clip_rect, &clipped)) {
return 0;
}
rect = &clipped;
} else {
rect = &dst->clip_rect;
/* Don't attempt to fill if the surface's clip_rect is empty */
if (SDL_RectEmpty(rect)) {
return 0;
}
}
/* Perform software fill */
if (!dst->pixels) {
return SDL_SetError("SDL_FillRect(): You must lock the surface");
}
pixels = (Uint8 *) dst->pixels + rect->y * dst->pitch +
rect->x * dst->format->BytesPerPixel;
switch (dst->format->BytesPerPixel) {
case 1:
{
color |= (color << 8);
color |= (color << 16);
#ifdef __SSE__
if (SDL_HasSSE()) {
SDL_FillRect1SSE(pixels, dst->pitch, color, rect->w, rect->h);
break;
}
#endif
SDL_FillRect1(pixels, dst->pitch, color, rect->w, rect->h);
break;
}
case 2:
{
color |= (color << 16);
#ifdef __SSE__
if (SDL_HasSSE()) {
SDL_FillRect2SSE(pixels, dst->pitch, color, rect->w, rect->h);
break;
}
#endif
SDL_FillRect2(pixels, dst->pitch, color, rect->w, rect->h);
break;
}
case 3:
/* 24-bit RGB is a slow path, at least for now. */
{
SDL_FillRect3(pixels, dst->pitch, color, rect->w, rect->h);
break;
}
case 4:
{
#ifdef __SSE__
if (SDL_HasSSE()) {
SDL_FillRect4SSE(pixels, dst->pitch, color, rect->w, rect->h);
break;
}
#endif
SDL_FillRect4(pixels, dst->pitch, color, rect->w, rect->h);
break;
}
}
/* We're done! */
return 0;
}
Вот объявление этой процедуры на экспорт в файле «include/SDL_surface.h»:
Код:
extern DECLSPEC int SDLCALL SDL_FillRect
(SDL_Surface * dst, const SDL_Rect * rect, Uint32 color);
Вот моё определение процедуры в Блэкбоксе (файл «Graph/Mod/GraphSdl.odc») и за одно определния Surface и Rect:
Код:
PROCEDURE [ccall] FillRect* ["SDL_FillRect"] (dst: Surface; VAR [nil] rect: Rect; color: INTEGER): INTEGER;
Surface* = POINTER [untagged] TO SurfaceDesc;
SurfaceDesc* = RECORD [untagged]
flags: INTEGER;
format*: PixelFormat; (* Это указатель *)
(* и т. д. *)
END;
Rect* = RECORD [untagged]
x*, y*, w*, h*: INTEGER
END;
Оригинальный SDL_Rect из файла «include/SDL_rect.h»:
Код:
typedef struct SDL_Rect
{
int x, y;
int w, h;
} SDL_Rect;
То есть оно принимает NIL и рисует всё правильно. И если дать ему не NIL, а Rect, то оно тоже всё принимает и всё рисует правильно. Но только если в VAR правильное количество байтов. Причём, в случае с процедурой Draw оно должно равняться (36 + 4 * n) байтам (где n = 0, 1, 2...). Вот сейчас у меня там i, x, y, color: INTEGER (16 байтов), затем ARRAY [untagged] 16 OF SHORTCHAR (ещё 16 байтов), потом Q1, Q2, Q3, Q4, Q5: INTEGER; (ещё 20 байтов). Итого: 52 и всё работает. Если уберу Q2, Q3, Q4, Q5, оставив Q1, то тоже будет всё работать. Но если уберу и Q1 или оставлю ещё и Q2, то выскакивает трап. 36 ведь не кратно 4... И как это вообще влияет?