🔒 Locked
Using DDraw
Advertisement
Original Post
Hello,
I am a newbie here, so please be kind. This forum looked the best place to post my question. I have read John De Goes'' book on how to build an engine, and I have about three years of working with C++. But I don''t know where to get started with DDraw. I want to write a software rastarizer before I attempt to write to 3D acceleration. How do I use DDraw?
what do you need help with? blitting, setting up the window, clipper, etc...
I am fairly inexperianced in windows programing. I have written in vb, and I have done plenty of dos. I know how to set up a dos driver, what I want to know is how to do the same in windows. So right from the begining, how to set up the window, how to set up a buffer for bliting. If it is too much writing or whatever just some recomended reading would be apreciated.
Which De Goes book do you have? _3d Game Programming With C++_ by De Goes has some intro stuff in it.
A better book might be _Tricks of the Windows Game Programming Gurus_
Or, if you''d like to save some dough, there are a some good Win32/DirectX intro tutorials here on GameDev. Not too much covering DirectX 7, but once you learn how to setup and use any of the DirectDraw versions, you''ll be set.
Jesse Chounard
A better book might be _Tricks of the Windows Game Programming Gurus_
Or, if you''d like to save some dough, there are a some good Win32/DirectX intro tutorials here on GameDev. Not too much covering DirectX 7, but once you learn how to setup and use any of the DirectDraw versions, you''ll be set.
Jesse Chounard
You're in luck. Microsoft has put the docs up on the web.
They're available here
Jesse Chounard
Edited by - Jesse Chounard on 4/29/00 5:52:02 PM
They're available here
Jesse Chounard
Edited by - Jesse Chounard on 4/29/00 5:52:02 PM
here''s a demo from Tricks of the Windows Game Programming Gururs (or whatever) by Andre Lamoth. You have to instruct the compiler to include ddraw.lib also.
// DEMO7_5.CPP 8-bit page flipping demo
// INCLUDES ///////////////////////////////////////////////
#define WIN32_LEAN_AND_MEAN // just say no to MFC
#define INITGUID
#include // include important windows stuff
#include
#include
#include // include important C/C++ stuff
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include // include directdraw
// DEFINES ////////////////////////////////////////////////
// defines for windows
#define WINDOW_CLASS_NAME "WINCLASS1"
// default screen size
#define SCREEN_WIDTH 640 // size of screen
#define SCREEN_HEIGHT 480
#define SCREEN_BPP 8 // bits per pixel
// TYPES //////////////////////////////////////////////////////
// basic unsigned types
typedef unsigned short USHORT;
typedef unsigned short WORD;
typedef unsigned char UCHAR;
typedef unsigned char BYTE;
// MACROS /////////////////////////////////////////////////
#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEYUP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
// initializes a direct draw struct
#define DDRAW_INIT_STRUCT(ddstruct) { memset(&ddstruct,0,sizeof(ddstruct)); ddstruct.dwSize=sizeof(ddstruct); }
// GLOBALS ////////////////////////////////////////////////
HWND main_window_handle = NULL; // globally track main window
int window_closed = 0; // tracks if window is closed
HINSTANCE hinstance_app = NULL; // globally track hinstance
// directdraw stuff
LPDIRECTDRAW4 lpdd4 = NULL; // dd4 object
LPDIRECTDRAWSURFACE4 lpddsprimary = NULL; // dd primary surface
LPDIRECTDRAWSURFACE4 lpddsback = NULL; // dd back surface
LPDIRECTDRAWPALETTE lpddpal = NULL; // a pointer to the created dd palette
LPDIRECTDRAWCLIPPER lpddclipper = NULL; // dd clipper
PALETTEENTRY palette[256]; // color palette
PALETTEENTRY save_palette[256]; // used to save palettes
DDSURFACEDESC2 ddsd; // a direct draw surface description struct
DDBLTFX ddbltfx; // used to fill
DDSCAPS2 ddscaps; // a direct draw surface capabilities struct
HRESULT ddrval; // result back from dd calls
DWORD start_clock_count = 0; // used for timing
char buffer[80]; // general printing buffer
// FUNCTIONS //////////////////////////////////////////////
LRESULT CALLBACK WindowProc(HWND hwnd,
UINT msg,
WPARAM wparam,
LPARAM lparam)
{
// this is the main message handler of the system
PAINTSTRUCT ps; // used in WM_PAINT
HDC hdc; // handle to a device context
char buffer[80]; // used to print strings
// what is the message
switch(msg)
{
case WM_CREATE:
{
// do initialization stuff here
// return success
return(0);
} break;
case WM_PAINT:
{
// simply validate the window
hdc = BeginPaint(hwnd,&ps);
// end painting
EndPaint(hwnd,&ps);
// return success
return(0);
} break;
case WM_DESTROY:
{
// kill the application, this sends a WM_QUIT message
PostQuitMessage(0);
// return success
return(0);
} break;
default:break;
} // end switch
// process any messages that we didn''t take care of
return (DefWindowProc(hwnd, msg, wparam, lparam));
} // end WinProc
///////////////////////////////////////////////////////////
int Game_Main(void *parms = NULL, int num_parms = 0)
{
// this is the main loop of the game, do all your processing
// here
// make sure this isn''t executed again
if (window_closed)
return(0);
// for now test if user is hitting ESC and send WM_CLOSE
if (KEYDOWN(VK_ESCAPE))
{
PostMessage(main_window_handle,WM_CLOSE,0,0);
window_closed = 1;
} // end if
// lock the back buffer
DDRAW_INIT_STRUCT(ddsd);
lpddsback->Lock(NULL,&ddsd, DDLOCK_SURFACEMEMORYPTR / DDLOCK_WAIT,NULL);
// alias pointer to back buffer surface
UCHAR *back_buffer = (UCHAR *)ddsd.lpSurface;
// now clear the back buffer out
// linear memory?
if (ddsd.lPitch == SCREEN_WIDTH)
memset(back_buffer,0,SCREEN_WIDTH*SCREEN_HEIGHT);
else
{
// non-linear memory
// make copy of video pointer
UCHAR *dest_ptr = back_buffer;
// clear out memory one line at a time
for (int y=0; y {
// clear next line
memset(dest_ptr,0,SCREEN_WIDTH);
// advance pointer to next line
dest_ptr+=ddsd.lPitch;
} // end for y
} // end else
// you would perform game logic...
// draw the next frame into the back buffer, notice that we
// must use the lpitch since it''s a surface and may not be linear
// plot 5000 random pixels
for (int index=0; index < 5000; index++)
{
int x = rand()%SCREEN_WIDTH;
int y = rand()%SCREEN_HEIGHT;
UCHAR col = rand()%256;
back_buffer[x+y*ddsd.lPitch] = col;
} // end for index
// unlock the back buffer
if (FAILED(lpddsback->Unlock(NULL)))
return(0);
// perform the flip
while (FAILED(lpddsprimary->Flip(NULL, DDFLIP_WAIT)));
// wait a sec
Sleep(500);
// return success or failure or your own return code here
return(1);
} // end Game_Main
////////////////////////////////////////////////////////////
int Game_Init(void *parms = NULL, int num_parms = 0)
{
// this is called once after the initial window is created and
// before the main event loop is entered, do all your initialization
// here
LPDIRECTDRAW lpdd_temp;
// first create base IDirectDraw interface
if (FAILED(DirectDrawCreate(NULL, &lpdd_temp, NULL)))
return(0);
// now query for IDirectDraw4
if (FAILED(lpdd_temp->QueryInterface(IID_IDirectDraw4,
(LPVOID *)&lpdd4)))
return(0);
// set cooperation to full screen
if (FAILED(lpdd4->SetCooperativeLevel(main_window_handle,
DDSCL_FULLSCREEN / DDSCL_ALLOWMODEX /
DDSCL_EXCLUSIVE / DDSCL_ALLOWREBOOT)))
return(0);
// set display mode to 640x480x8
if (FAILED(lpdd4->SetDisplayMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,0,0)))
return(0);
// clear ddsd and set size
DDRAW_INIT_STRUCT(ddsd);
// enable valid fields
ddsd.dwFlags = DDSD_CAPS / DDSD_BACKBUFFERCOUNT;
// set the backbuffer count field to 1, use 2 for triple buffering
ddsd.dwBackBufferCount = 1;
// request a complex, flippable
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE / DDSCAPS_COMPLEX / DDSCAPS_FLIP;
// create the primary surface
if (FAILED(lpdd4->CreateSurface(&ddsd, &lpddsprimary, NULL)))
return(0);
// now query for attached surface from the primary surface
// this line is needed by the call
ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
// get the attached back buffer surface
if (FAILED(lpddsprimary->GetAttachedSurface(&ddsd.ddsCaps, &lpddsback)))
return(0);
// build up the palette data array
for (int color=1; color < 255; color++)
{
// fill with random RGB values
palette[color].peRed = rand()%256;
palette[color].peGreen = rand()%256;
palette[color].peBlue = rand()%256;
// set flags field to PC_NOCOLLAPSE
palette[color].peFlags = PC_NOCOLLAPSE;
} // end for color
// now fill in entry 0 and 255 with black and white
palette[0].peRed = 0;
palette[0].peGreen = 0;
palette[0].peBlue = 0;
palette[0].peFlags = PC_NOCOLLAPSE;
palette[255].peRed = 255;
palette[255].peGreen = 255;
palette[255].peBlue = 255;
palette[255].peFlags = PC_NOCOLLAPSE;
// create the palette object
if (FAILED(lpdd4->CreatePalette(DDPCAPS_8BIT / DDPCAPS_ALLOW256 /
DDPCAPS_INITIALIZE,
palette,&lpddpal, NULL)))
return(0);
// finally attach the palette to the primary surface
if (FAILED(lpddsprimary->SetPalette(lpddpal)))
return(0);
// return success or failure or your own return code here
return(1);
} // end Game_Init
/////////////////////////////////////////////////////////////
int Game_Shutdown(void *parms = NULL, int num_parms = 0)
{
// this is called after the game is exited and the main event
// loop while is exited, do all you cleanup and shutdown here
// first the palette
if (lpddpal)
{
lpddpal->Release();
lpddpal = NULL;
} // end if
// now the back buffer surface
if (lpddsback)
{
lpddsback->Release();
lpddsback = NULL;
} // end if
// now the primary surface
if (lpddsprimary)
{
lpddsprimary->Release();
lpddsprimary = NULL;
} // end if
// now blow away the IDirectDraw4 interface
if (lpdd4)
{
lpdd4->Release();
lpdd4 = NULL;
} // end if
// return success or failure or your own return code here
return(1);
} // end Game_Shutdown
// WINMAIN ////////////////////////////////////////////////
int WINAPI WinMain( HINSTANCE hinstance,
HINSTANCE hprevinstance,
LPSTR lpcmdline,
int ncmdshow)
{
WNDCLASSEX winclass; // this will hold the class we create
HWND hwnd; // generic window handle
MSG msg; // generic message
HDC hdc; // graphics device context
// first fill in the window class stucture
winclass.cbSize = sizeof(WNDCLASSEX);
winclass.style = CS_DBLCLKS / CS_OWNDC /
CS_HREDRAW / CS_VREDRAW;
winclass.lpfnWndProc = WindowProc;
winclass.cbClsExtra = 0;
winclass.cbWndExtra = 0;
winclass.hInstance = hinstance;
winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
winclass.hCursor = LoadCursor(NULL, IDC_ARROW);
winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
winclass.lpszMenuName = NULL;
winclass.lpszClassName = WINDOW_CLASS_NAME;
winclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
// save hinstance in global
hinstance_app = hinstance;
// register the window class
if (!RegisterClassEx(&winclass))
return(0);
// create the window
if (!(hwnd = CreateWindowEx(NULL, // extended style
WINDOW_CLASS_NAME, // class
"DirectDraw Page Flipping Demo", // title
WS_POPUP / WS_VISIBLE,
0,0, // initial x,y
SCREEN_WIDTH,SCREEN_HEIGHT, // initial width, height
NULL, // handle to parent
NULL, // handle to menu
hinstance,// instance of this application
NULL))) // extra creation parms
return(0);
// save main window handle
main_window_handle = hwnd;
// initialize game here
Game_Init();
// enter main event loop
while(TRUE)
{
// test if there is a message in queue, if so get it
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
// test if this is a quit
if (msg.message == WM_QUIT)
break;
// translate any accelerator keys
TranslateMessage(&msg);
// send the message to the window proc
DispatchMessage(&msg);
} // end if
// main game processing goes here
Game_Main();
} // end while
// closedown game here
Game_Shutdown();
// return to Windows like this
return(msg.wParam);
} // end WinMain
///////////////////////////////////////////////////////////
// DEMO7_5.CPP 8-bit page flipping demo
// INCLUDES ///////////////////////////////////////////////
#define WIN32_LEAN_AND_MEAN // just say no to MFC
#define INITGUID
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
// DEFINES ////////////////////////////////////////////////
// defines for windows
#define WINDOW_CLASS_NAME "WINCLASS1"
// default screen size
#define SCREEN_WIDTH 640 // size of screen
#define SCREEN_HEIGHT 480
#define SCREEN_BPP 8 // bits per pixel
// TYPES //////////////////////////////////////////////////////
// basic unsigned types
typedef unsigned short USHORT;
typedef unsigned short WORD;
typedef unsigned char UCHAR;
typedef unsigned char BYTE;
// MACROS /////////////////////////////////////////////////
#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEYUP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
// initializes a direct draw struct
#define DDRAW_INIT_STRUCT(ddstruct) { memset(&ddstruct,0,sizeof(ddstruct)); ddstruct.dwSize=sizeof(ddstruct); }
// GLOBALS ////////////////////////////////////////////////
HWND main_window_handle = NULL; // globally track main window
int window_closed = 0; // tracks if window is closed
HINSTANCE hinstance_app = NULL; // globally track hinstance
// directdraw stuff
LPDIRECTDRAW4 lpdd4 = NULL; // dd4 object
LPDIRECTDRAWSURFACE4 lpddsprimary = NULL; // dd primary surface
LPDIRECTDRAWSURFACE4 lpddsback = NULL; // dd back surface
LPDIRECTDRAWPALETTE lpddpal = NULL; // a pointer to the created dd palette
LPDIRECTDRAWCLIPPER lpddclipper = NULL; // dd clipper
PALETTEENTRY palette[256]; // color palette
PALETTEENTRY save_palette[256]; // used to save palettes
DDSURFACEDESC2 ddsd; // a direct draw surface description struct
DDBLTFX ddbltfx; // used to fill
DDSCAPS2 ddscaps; // a direct draw surface capabilities struct
HRESULT ddrval; // result back from dd calls
DWORD start_clock_count = 0; // used for timing
char buffer[80]; // general printing buffer
// FUNCTIONS //////////////////////////////////////////////
LRESULT CALLBACK WindowProc(HWND hwnd,
UINT msg,
WPARAM wparam,
LPARAM lparam)
{
// this is the main message handler of the system
PAINTSTRUCT ps; // used in WM_PAINT
HDC hdc; // handle to a device context
char buffer[80]; // used to print strings
// what is the message
switch(msg)
{
case WM_CREATE:
{
// do initialization stuff here
// return success
return(0);
} break;
case WM_PAINT:
{
// simply validate the window
hdc = BeginPaint(hwnd,&ps);
// end painting
EndPaint(hwnd,&ps);
// return success
return(0);
} break;
case WM_DESTROY:
{
// kill the application, this sends a WM_QUIT message
PostQuitMessage(0);
// return success
return(0);
} break;
default:break;
} // end switch
// process any messages that we didn''t take care of
return (DefWindowProc(hwnd, msg, wparam, lparam));
} // end WinProc
///////////////////////////////////////////////////////////
int Game_Main(void *parms = NULL, int num_parms = 0)
{
// this is the main loop of the game, do all your processing
// here
// make sure this isn''t executed again
if (window_closed)
return(0);
// for now test if user is hitting ESC and send WM_CLOSE
if (KEYDOWN(VK_ESCAPE))
{
PostMessage(main_window_handle,WM_CLOSE,0,0);
window_closed = 1;
} // end if
// lock the back buffer
DDRAW_INIT_STRUCT(ddsd);
lpddsback->Lock(NULL,&ddsd, DDLOCK_SURFACEMEMORYPTR / DDLOCK_WAIT,NULL);
// alias pointer to back buffer surface
UCHAR *back_buffer = (UCHAR *)ddsd.lpSurface;
// now clear the back buffer out
// linear memory?
if (ddsd.lPitch == SCREEN_WIDTH)
memset(back_buffer,0,SCREEN_WIDTH*SCREEN_HEIGHT);
else
{
// non-linear memory
// make copy of video pointer
UCHAR *dest_ptr = back_buffer;
// clear out memory one line at a time
for (int y=0; y
// clear next line
memset(dest_ptr,0,SCREEN_WIDTH);
// advance pointer to next line
dest_ptr+=ddsd.lPitch;
} // end for y
} // end else
// you would perform game logic...
// draw the next frame into the back buffer, notice that we
// must use the lpitch since it''s a surface and may not be linear
// plot 5000 random pixels
for (int index=0; index < 5000; index++)
{
int x = rand()%SCREEN_WIDTH;
int y = rand()%SCREEN_HEIGHT;
UCHAR col = rand()%256;
back_buffer[x+y*ddsd.lPitch] = col;
} // end for index
// unlock the back buffer
if (FAILED(lpddsback->Unlock(NULL)))
return(0);
// perform the flip
while (FAILED(lpddsprimary->Flip(NULL, DDFLIP_WAIT)));
// wait a sec
Sleep(500);
// return success or failure or your own return code here
return(1);
} // end Game_Main
////////////////////////////////////////////////////////////
int Game_Init(void *parms = NULL, int num_parms = 0)
{
// this is called once after the initial window is created and
// before the main event loop is entered, do all your initialization
// here
LPDIRECTDRAW lpdd_temp;
// first create base IDirectDraw interface
if (FAILED(DirectDrawCreate(NULL, &lpdd_temp, NULL)))
return(0);
// now query for IDirectDraw4
if (FAILED(lpdd_temp->QueryInterface(IID_IDirectDraw4,
(LPVOID *)&lpdd4)))
return(0);
// set cooperation to full screen
if (FAILED(lpdd4->SetCooperativeLevel(main_window_handle,
DDSCL_FULLSCREEN / DDSCL_ALLOWMODEX /
DDSCL_EXCLUSIVE / DDSCL_ALLOWREBOOT)))
return(0);
// set display mode to 640x480x8
if (FAILED(lpdd4->SetDisplayMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,0,0)))
return(0);
// clear ddsd and set size
DDRAW_INIT_STRUCT(ddsd);
// enable valid fields
ddsd.dwFlags = DDSD_CAPS / DDSD_BACKBUFFERCOUNT;
// set the backbuffer count field to 1, use 2 for triple buffering
ddsd.dwBackBufferCount = 1;
// request a complex, flippable
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE / DDSCAPS_COMPLEX / DDSCAPS_FLIP;
// create the primary surface
if (FAILED(lpdd4->CreateSurface(&ddsd, &lpddsprimary, NULL)))
return(0);
// now query for attached surface from the primary surface
// this line is needed by the call
ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
// get the attached back buffer surface
if (FAILED(lpddsprimary->GetAttachedSurface(&ddsd.ddsCaps, &lpddsback)))
return(0);
// build up the palette data array
for (int color=1; color < 255; color++)
{
// fill with random RGB values
palette[color].peRed = rand()%256;
palette[color].peGreen = rand()%256;
palette[color].peBlue = rand()%256;
// set flags field to PC_NOCOLLAPSE
palette[color].peFlags = PC_NOCOLLAPSE;
} // end for color
// now fill in entry 0 and 255 with black and white
palette[0].peRed = 0;
palette[0].peGreen = 0;
palette[0].peBlue = 0;
palette[0].peFlags = PC_NOCOLLAPSE;
palette[255].peRed = 255;
palette[255].peGreen = 255;
palette[255].peBlue = 255;
palette[255].peFlags = PC_NOCOLLAPSE;
// create the palette object
if (FAILED(lpdd4->CreatePalette(DDPCAPS_8BIT / DDPCAPS_ALLOW256 /
DDPCAPS_INITIALIZE,
palette,&lpddpal, NULL)))
return(0);
// finally attach the palette to the primary surface
if (FAILED(lpddsprimary->SetPalette(lpddpal)))
return(0);
// return success or failure or your own return code here
return(1);
} // end Game_Init
/////////////////////////////////////////////////////////////
int Game_Shutdown(void *parms = NULL, int num_parms = 0)
{
// this is called after the game is exited and the main event
// loop while is exited, do all you cleanup and shutdown here
// first the palette
if (lpddpal)
{
lpddpal->Release();
lpddpal = NULL;
} // end if
// now the back buffer surface
if (lpddsback)
{
lpddsback->Release();
lpddsback = NULL;
} // end if
// now the primary surface
if (lpddsprimary)
{
lpddsprimary->Release();
lpddsprimary = NULL;
} // end if
// now blow away the IDirectDraw4 interface
if (lpdd4)
{
lpdd4->Release();
lpdd4 = NULL;
} // end if
// return success or failure or your own return code here
return(1);
} // end Game_Shutdown
// WINMAIN ////////////////////////////////////////////////
int WINAPI WinMain( HINSTANCE hinstance,
HINSTANCE hprevinstance,
LPSTR lpcmdline,
int ncmdshow)
{
WNDCLASSEX winclass; // this will hold the class we create
HWND hwnd; // generic window handle
MSG msg; // generic message
HDC hdc; // graphics device context
// first fill in the window class stucture
winclass.cbSize = sizeof(WNDCLASSEX);
winclass.style = CS_DBLCLKS / CS_OWNDC /
CS_HREDRAW / CS_VREDRAW;
winclass.lpfnWndProc = WindowProc;
winclass.cbClsExtra = 0;
winclass.cbWndExtra = 0;
winclass.hInstance = hinstance;
winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
winclass.hCursor = LoadCursor(NULL, IDC_ARROW);
winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
winclass.lpszMenuName = NULL;
winclass.lpszClassName = WINDOW_CLASS_NAME;
winclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
// save hinstance in global
hinstance_app = hinstance;
// register the window class
if (!RegisterClassEx(&winclass))
return(0);
// create the window
if (!(hwnd = CreateWindowEx(NULL, // extended style
WINDOW_CLASS_NAME, // class
"DirectDraw Page Flipping Demo", // title
WS_POPUP / WS_VISIBLE,
0,0, // initial x,y
SCREEN_WIDTH,SCREEN_HEIGHT, // initial width, height
NULL, // handle to parent
NULL, // handle to menu
hinstance,// instance of this application
NULL))) // extra creation parms
return(0);
// save main window handle
main_window_handle = hwnd;
// initialize game here
Game_Init();
// enter main event loop
while(TRUE)
{
// test if there is a message in queue, if so get it
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
// test if this is a quit
if (msg.message == WM_QUIT)
break;
// translate any accelerator keys
TranslateMessage(&msg);
// send the message to the window proc
DispatchMessage(&msg);
} // end if
// main game processing goes here
Game_Main();
} // end while
// closedown game here
Game_Shutdown();
// return to Windows like this
return(msg.wParam);
} // end WinMain
///////////////////////////////////////////////////////////
Includes didn''t come out, you might wanna redo them with inverted brackets, ie ><.
Oh yeah, isn''t that copyright infringement?
The_Minister
Oh yeah, isn''t that copyright infringement?
The_Minister
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement