modified sn76489 cut-off frequency, modified Video synchronization

This commit is contained in:
ekeeke31 2009-01-06 17:15:28 +00:00
parent 0e86a15c09
commit 414a53ca1f
8 changed files with 412 additions and 371 deletions

View File

@ -125,33 +125,33 @@ bool fat_enabled = 0;
int main (int argc, char *argv[]) int main (int argc, char *argv[])
{ {
long long now, prev;
int RenderedFrameCount = 0;
int FrameCount = 0;
#ifdef HW_RVL #ifdef HW_RVL
/* initialize Wii DVD interface first */ /* initialize Wii DVD interface first */
DI_Close(); DI_Close();
DI_Init(); DI_Init();
#endif #endif
long long now, prev; /* initialize OGC subsystems */
int RenderedFrameCount = 0;
int FrameCount = 0;
/* Initialize OGC subsystems */
ogc_video__init(); ogc_video__init();
ogc_input__init(); ogc_input__init();
ogc_audio__init(); ogc_audio__init();
#ifdef HW_DOL #ifdef HW_DOL
/* Initialize GC DVD interface */ /* initialize GC DVD interface */
DVD_Init (); DVD_Init ();
dvd_drive_detect(); dvd_drive_detect();
#endif #endif
#ifdef HW_RVL #ifdef HW_RVL
/* Power Button callback */ /* Power button callback */
SYS_SetPowerCallback(Power_Off); SYS_SetPowerCallback(Power_Off);
#endif #endif
/* Initialize FAT Interface */ /* initialize FAT Interface */
if (fatInitDefault() == true) if (fatInitDefault() == true)
{ {
fat_enabled = 1; fat_enabled = 1;
@ -164,33 +164,49 @@ int main (int argc, char *argv[])
#endif #endif
} }
/* Default Config */ /* default Config */
legal(); legal();
set_config_defaults(); set_config_defaults();
config_load(); config_load();
/* Restore Recent Files list */ /* restore recent Files list */
set_history_defaults(); set_history_defaults();
history_load(); history_load();
/* Initialize Virtual Machine */ /* initialize VM */
init_machine (); init_machine ();
/* Load any injected rom */ /* load any injected rom */
if (genromsize) if (genromsize)
{ {
ARAMFetch((char *)cart_rom, (void *)0x8000, genromsize); ARAMFetch((char *)cart_rom, (void *)0x8000, genromsize);
reloadrom (); reloadrom ();
} }
/* Show Menu */ /* show Menu first */
MainMenu(); ConfigRequested = 1;
ConfigRequested = 0;
/* Emulation Loop */ /* main emulation loop */
while (1) while (1)
{ {
/* Check for Menu request */
if (ConfigRequested)
{
/* stop Audio */
ogc_audio__stop();
/* go to Menu */
MainMenu ();
ConfigRequested = 0;
/* reset frame sync */
frameticker = 0;
FrameCount = 0;
RenderedFrameCount = 0;
/* restart sound loop */
ogc_audio__start(); ogc_audio__start();
}
if (gc_pal < 0) if (gc_pal < 0)
{ {
@ -204,28 +220,31 @@ int main (int argc, char *argv[])
{ {
if (frameticker > 1) if (frameticker > 1)
{ {
/* frameskipping */ /* skip one frame */
frameticker--; frameticker--;
system_frame (1); system_frame (1);
/* update audio only */
ogc_audio__update();
} }
else else
{ {
/* frame sync */ /* frame sync */
while (!frameticker) usleep(1); while (frameticker < 1) usleep(1);
/* frame rendering */ /* render one frame */
system_frame (0); system_frame (0);
RenderedFrameCount++; RenderedFrameCount++;
/* update audio & video */
ogc_audio__update();
ogc_video__update();
} }
frameticker--; frameticker--;
} }
/* update video & audio */ /* check rendered frame count (FPS) */
ogc_audio__update();
ogc_video__update();
/* check rendered frames (FPS) */
FrameCount++; FrameCount++;
if (FrameCount == vdp_rate) if (FrameCount == vdp_rate)
{ {
@ -233,23 +252,7 @@ int main (int argc, char *argv[])
RenderedFrameCount = 0; RenderedFrameCount = 0;
FrameCount = 0; FrameCount = 0;
} }
/* Check for Menu request */
if (ConfigRequested)
{
/* stop Audio */
ogc_audio__stop();
/* go to menu */
MainMenu ();
ConfigRequested = 0;
/* reset frame sync */
frameticker = 0;
FrameCount = 0;
RenderedFrameCount = 0;
}
} }
return 0; return 0;
} }

View File

@ -35,9 +35,6 @@ u8 soundbuffer[2][3840] ATTRIBUTE_ALIGN(32);
/* Current work soundbuffer */ /* Current work soundbuffer */
int mixbuffer; int mixbuffer;
/* Current DMA status (1: DMA in progress, 0: DMA stopped) */
static int IsPlaying = 0;
/* Current DMA length (required to be a factor of 32-bytes) /* Current DMA length (required to be a factor of 32-bytes)
length is calculated regarding current emulation timings: length is calculated regarding current emulation timings:
PAL timings : 50 frames/sec, 48000 samples/sec = 960 samples per frame = 3840 bytes (16 bits stereo samples) PAL timings : 50 frames/sec, 48000 samples/sec = 960 samples per frame = 3840 bytes (16 bits stereo samples)
@ -99,27 +96,22 @@ void ogc_audio__update(void)
***/ ***/
void ogc_audio__start(void) void ogc_audio__start(void)
{ {
if (!IsPlaying)
{
dma_len = vdp_pal ? 3840 : 3200; dma_len = vdp_pal ? 3840 : 3200;
memset(soundbuffer[0], 0, dma_len); memset(soundbuffer[0], 0, dma_len);
AUDIO_InitDMA((u32) soundbuffer[0], dma_len); AUDIO_InitDMA((u32) soundbuffer[0], dma_len);
DCFlushRange(soundbuffer[0], dma_len); DCFlushRange(soundbuffer[0], dma_len);
AUDIO_StartDMA(); AUDIO_StartDMA();
IsPlaying = 1;
mixbuffer = 1; mixbuffer = 1;
}
} }
/*** /***
ogc_audio__stop ogc_audio__stop
This function reset current Audio DMA process and clear soundbuffers This function reset current Audio DMA process
This is called when going back to Main Menu This is called when going back to Main Menu
DMA need to be restarted when going back to the game (see above) DMA need to be restarted when going back to the game (see above)
***/ ***/
void ogc_audio__stop(void) void ogc_audio__stop(void)
{ {
AUDIO_StopDMA (); AUDIO_StopDMA ();
IsPlaying = 0;
} }

View File

@ -53,20 +53,22 @@ u8 *texturemem; /*** Texture Data ***/
static u8 gp_fifo[DEFAULT_FIFO_SIZE] ATTRIBUTE_ALIGN (32); static u8 gp_fifo[DEFAULT_FIFO_SIZE] ATTRIBUTE_ALIGN (32);
static GXTexObj texobj; static GXTexObj texobj;
static u8 do_copy = GX_FALSE;
static Mtx view; static Mtx view;
static u32 vwidth, vheight; static u32 vwidth, vheight;
/*** custom Video modes (used to emulate original console video modes) ***/ /*** custom Video modes ***/
/* 288 lines progressive (PAL 50Hz) */ /* 288 lines progressive (PAL 50Hz) */
GXRModeObj TV50hz_288p = GXRModeObj TV50hz_288p =
{ {
VI_TVMODE_PAL_DS,// viDisplayMode VI_TVMODE_PAL_DS, // viDisplayMode
640, // fbWidth 640, // fbWidth
286, // efbHeight 286, // efbHeight
286, // xfbHeight 286, // xfbHeight
(VI_MAX_WIDTH_PAL - 720)/2, // viXOrigin 0, // viXOrigin
(VI_MAX_HEIGHT_PAL/2 - 572/2)/2,// viYOrigin (VI_MAX_HEIGHT_PAL - 572)/2, // viYOrigin
720, // viWidth VI_MAX_WIDTH_PAL, // viWidth
572, // viHeight 572, // viHeight
VI_XFBMODE_SF, // xFBmode VI_XFBMODE_SF, // xFBmode
GX_FALSE, // field_rendering GX_FALSE, // field_rendering
@ -95,13 +97,13 @@ GXRModeObj TV50hz_288p =
/* 288 lines interlaced (PAL 50Hz) */ /* 288 lines interlaced (PAL 50Hz) */
GXRModeObj TV50hz_288i = GXRModeObj TV50hz_288i =
{ {
VI_TVMODE_PAL_INT,// viDisplayMode VI_TVMODE_PAL_INT, // viDisplayMode
640, // fbWidth 640, // fbWidth
286, // efbHeight 286, // efbHeight
286, // xfbHeight 286, // xfbHeight
(VI_MAX_WIDTH_PAL - 720)/2, // viXOrigin 0, // viXOrigin
(VI_MAX_HEIGHT_PAL/2 - 572/2)/2,// viYOrigin (VI_MAX_HEIGHT_PAL - 572)/2, // viYOrigin
720, // viWidth VI_MAX_WIDTH_PAL, // viWidth
572, // viHeight 572, // viHeight
VI_XFBMODE_SF, // xFBmode VI_XFBMODE_SF, // xFBmode
GX_TRUE, // field_rendering GX_TRUE, // field_rendering
@ -130,14 +132,14 @@ GXRModeObj TV50hz_288i =
/* 576 lines interlaced (PAL 50Hz, scaled) */ /* 576 lines interlaced (PAL 50Hz, scaled) */
GXRModeObj TV50hz_576i = GXRModeObj TV50hz_576i =
{ {
VI_TVMODE_PAL_INT,// viDisplayMode VI_TVMODE_PAL_INT, // viDisplayMode
640, // fbWidth 640, // fbWidth
480, // efbHeight 480, // efbHeight
574, // xfbHeight VI_MAX_HEIGHT_PAL, // xfbHeight
(VI_MAX_WIDTH_PAL - 720)/2, // viXOrigin 0, // viXOrigin
(VI_MAX_HEIGHT_PAL - 574)/2,// viYOrigin 0, // viYOrigin
720, // viWidth VI_MAX_WIDTH_PAL, // viWidth
574, // viHeight VI_MAX_HEIGHT_PAL, // viHeight
VI_XFBMODE_DF, // xFBmode VI_XFBMODE_DF, // xFBmode
GX_FALSE, // field_rendering GX_FALSE, // field_rendering
GX_FALSE, // aa GX_FALSE, // aa
@ -165,14 +167,14 @@ GXRModeObj TV50hz_576i =
/* 240 lines progressive (NTSC or PAL 60Hz) */ /* 240 lines progressive (NTSC or PAL 60Hz) */
GXRModeObj TV60hz_240p = GXRModeObj TV60hz_240p =
{ {
VI_TVMODE_EURGB60_DS,// viDisplayMode VI_TVMODE_EURGB60_DS, // viDisplayMode
640, // fbWidth 640, // fbWidth
240, // efbHeight VI_MAX_HEIGHT_NTSC/2, // efbHeight
240, // xfbHeight VI_MAX_HEIGHT_NTSC/2, // xfbHeight
(VI_MAX_WIDTH_NTSC - 720)/2, // viXOrigin 0, // viXOrigin
(VI_MAX_HEIGHT_NTSC/2 - 480/2)/2, // viYOrigin 0, // viYOrigin
720, // viWidth VI_MAX_WIDTH_NTSC, // viWidth
480, // viHeight VI_MAX_HEIGHT_NTSC, // viHeight
VI_XFBMODE_SF, // xFBmode VI_XFBMODE_SF, // xFBmode
GX_FALSE, // field_rendering GX_FALSE, // field_rendering
GX_FALSE, // aa GX_FALSE, // aa
@ -200,14 +202,14 @@ GXRModeObj TV60hz_240p =
/* 240 lines interlaced (NTSC or PAL 60Hz) */ /* 240 lines interlaced (NTSC or PAL 60Hz) */
GXRModeObj TV60hz_240i = GXRModeObj TV60hz_240i =
{ {
VI_TVMODE_EURGB60_INT,// viDisplayMode VI_TVMODE_EURGB60_INT, // viDisplayMode
640, // fbWidth 640, // fbWidth
240, // efbHeight VI_MAX_HEIGHT_NTSC/2, // efbHeight
240, // xfbHeight VI_MAX_HEIGHT_NTSC/2, // xfbHeight
(VI_MAX_WIDTH_NTSC - 720)/2, // viXOrigin 0, // viXOrigin
(VI_MAX_HEIGHT_NTSC/2 - 480/2)/2, // viYOrigin 0, // viYOrigin
720, // viWidth VI_MAX_WIDTH_NTSC, // viWidth
480, // viHeight VI_MAX_HEIGHT_NTSC, // viHeight
VI_XFBMODE_SF, // xFBmode VI_XFBMODE_SF, // xFBmode
GX_TRUE, // field_rendering GX_TRUE, // field_rendering
GX_FALSE, // aa GX_FALSE, // aa
@ -237,12 +239,12 @@ GXRModeObj TV60hz_480i =
{ {
VI_TVMODE_EURGB60_INT,// viDisplayMode VI_TVMODE_EURGB60_INT,// viDisplayMode
640, // fbWidth 640, // fbWidth
480, // efbHeight VI_MAX_HEIGHT_NTSC, // efbHeight
480, // xfbHeight VI_MAX_HEIGHT_NTSC, // xfbHeight
(VI_MAX_WIDTH_NTSC - 720)/2, // viXOrigin 0, // viXOrigin
(VI_MAX_HEIGHT_NTSC - 480)/2, // viYOrigin 0, // viYOrigin
720, // viWidth VI_MAX_WIDTH_NTSC, // viWidth
480, // viHeight VI_MAX_HEIGHT_NTSC, // viHeight
VI_XFBMODE_DF, // xFBmode VI_XFBMODE_DF, // xFBmode
GX_FALSE, // field_rendering GX_FALSE, // field_rendering
GX_FALSE, // aa GX_FALSE, // aa
@ -489,6 +491,7 @@ static void gxScale(GXRModeObj *rmode)
square[4] = square[1] = yscale + yshift; square[4] = square[1] = yscale + yshift;
square[7] = square[10] = -yscale + yshift; square[7] = square[10] = -yscale + yshift;
/* flush data from cache */
DCFlushRange (square, 32); DCFlushRange (square, 32);
GX_InvVtxCache (); GX_InvVtxCache ();
} }
@ -618,14 +621,37 @@ void ogc_video__update()
draw_square (); draw_square ();
GX_DrawDone (); GX_DrawDone ();
/* switch external framebuffers then copy EFB to XFB */ /* postpound XFB update */
do_copy = GX_TRUE;
}
/* Pre-Retrace handler
synchronize XFB switch with VSYNC
*/
void xfb_switch(u32 cnt)
{
if (!ConfigRequested)
{
/* switch external framebuffers */
whichfb ^= 1; whichfb ^= 1;
GX_CopyDisp (xfb[whichfb], GX_TRUE);
GX_Flush ();
/* set next XFB */ /* set next XFB */
VIDEO_SetNextFramebuffer (xfb[whichfb]); VIDEO_SetNextFramebuffer (xfb[whichfb]);
VIDEO_Flush (); VIDEO_Flush ();
}
}
/* Post-Retrace handler
synchronize XFB copy with VSYNC */
void xfb_copy(u32 cnt)
{
if (do_copy)
{
/* copy EFB to XFB */
GX_CopyDisp (xfb[whichfb], GX_TRUE);
GX_Flush ();
do_copy = GX_FALSE;
}
} }
/* Initialize VIDEO subsystem */ /* Initialize VIDEO subsystem */
@ -720,6 +746,9 @@ void ogc_video__init(void)
/* Set the framebuffer to be displayed at next VBlank */ /* Set the framebuffer to be displayed at next VBlank */
VIDEO_SetNextFramebuffer (xfb[0]); VIDEO_SetNextFramebuffer (xfb[0]);
VIDEO_SetPreRetraceCallback(xfb_switch);
VIDEO_SetPostRetraceCallback(xfb_copy);
/* Enable Video Interface */ /* Enable Video Interface */
VIDEO_SetBlack (FALSE); VIDEO_SetBlack (FALSE);

View File

@ -23,6 +23,9 @@
Modified for use with GenesisPlus Gamecube's port: Modified for use with GenesisPlus Gamecube's port:
- made SN76489_Update outputs 16bits mono samples - made SN76489_Update outputs 16bits mono samples
- replaced volume table with VGM plugin's one - replaced volume table with VGM plugin's one
05/01/2009 Eke-Eke
Modified Cut-Off frequency (according to Steve Snake: http://www.smspower.org/forums/viewtopic.php?t=1746)
*/ */
#include "shared.h" #include "shared.h"
@ -31,7 +34,7 @@
#include <string.h> // for memcpy #include <string.h> // for memcpy
#define NoiseInitialState 0x8000 /* Initial state of shift register */ #define NoiseInitialState 0x8000 /* Initial state of shift register */
#define PSG_CUTOFF 0x6 /* Value below which PSG does not output */ #define PSG_CUTOFF 0x1 /* Value below which PSG does not output */
static const int PSGVolumeValues[2][16] = { static const int PSGVolumeValues[2][16] = {
/* These values are taken from a real SMS2's output */ /* These values are taken from a real SMS2's output */
@ -84,7 +87,6 @@ void SN76489_Reset(int which)
/* Zero clock */ /* Zero clock */
p->Clock=0; p->Clock=0;
} }
void SN76489_Shutdown(void) void SN76489_Shutdown(void)
@ -126,29 +128,36 @@ void SN76489_Write(int which, int data)
{ {
SN76489_Context *p = &SN76489[which]; SN76489_Context *p = &SN76489[which];
if (data&0x80) { if (data&0x80)
{
/* Latch/data byte %1 cc t dddd */ /* Latch/data byte %1 cc t dddd */
p->LatchedRegister=((data>>4)&0x07); p->LatchedRegister=((data>>4)&0x07);
p->Registers[p->LatchedRegister]= p->Registers[p->LatchedRegister] =
(p->Registers[p->LatchedRegister] & 0x3f0) /* zero low 4 bits */ (p->Registers[p->LatchedRegister] & 0x3f0) | /* zero low 4 bits */
| (data&0xf); /* and replace with data */ (data&0xf); /* and replace with data */
} else { }
else
{
/* Data byte %0 - dddddd */ /* Data byte %0 - dddddd */
if (!(p->LatchedRegister%2)&&(p->LatchedRegister<5)) if (!(p->LatchedRegister%2)&&(p->LatchedRegister<5))
/* Tone register */ /* Tone register */
p->Registers[p->LatchedRegister]= p->Registers[p->LatchedRegister]=
(p->Registers[p->LatchedRegister] & 0x00f) /* zero high 6 bits */ (p->Registers[p->LatchedRegister] & 0x00f) | /* zero high 6 bits */
| ((data&0x3f)<<4); /* and replace with data */ ((data&0x3f)<<4); /* and replace with data */
else else
/* Other register */ /* Other register */
p->Registers[p->LatchedRegister]=data&0x0f; /* Replace with data */ p->Registers[p->LatchedRegister]=data&0x0f; /* Replace with data */
} }
switch (p->LatchedRegister) {
switch (p->LatchedRegister)
{
case 0: case 0:
case 2: case 2:
case 4: /* Tone channels */ case 4: /* Tone channels */
if (p->Registers[p->LatchedRegister]==0) p->Registers[p->LatchedRegister]=1; /* Zero frequency changed to 1 to avoid div/0 */ /* Zero frequency changed to 1 to avoid div/0 */
if (p->Registers[p->LatchedRegister]==0) p->Registers[p->LatchedRegister]=1;
break; break;
case 6: /* Noise */ case 6: /* Noise */
p->NoiseShiftRegister=NoiseInitialState; /* reset shift register */ p->NoiseShiftRegister=NoiseInitialState; /* reset shift register */
p->NoiseFreq=0x10<<(p->Registers[6]&0x3); /* set noise signal generator frequency */ p->NoiseFreq=0x10<<(p->Registers[6]&0x3); /* set noise signal generator frequency */
@ -169,6 +178,7 @@ void SN76489_Update(int which, INT16 *buffer, int length)
for(j = 0; j < length; j++) for(j = 0; j < length; j++)
{ {
/* update output */
for (i=0;i<=2;++i) for (i=0;i<=2;++i)
if (p->IntermediatePos[i]!=FLT_MIN) if (p->IntermediatePos[i]!=FLT_MIN)
p->Channels[i]=(short)((p->Mute >> i & 0x1)*PSGVolumeValues[p->VolumeArray][p->Registers[2*i+1]]*p->IntermediatePos[i]); p->Channels[i]=(short)((p->Mute >> i & 0x1)*PSGVolumeValues[p->VolumeArray][p->Registers[2*i+1]]*p->IntermediatePos[i]);
@ -178,10 +188,10 @@ void SN76489_Update(int which, INT16 *buffer, int length)
p->Channels[3]=(short)((p->Mute >> 3 & 0x1)*PSGVolumeValues[p->VolumeArray][p->Registers[7]]*(p->NoiseShiftRegister & 0x1)); p->Channels[3]=(short)((p->Mute >> 3 & 0x1)*PSGVolumeValues[p->VolumeArray][p->Registers[7]]*(p->NoiseShiftRegister & 0x1));
if (p->BoostNoise) p->Channels[3]<<=1; /* double noise volume */ if (p->BoostNoise) p->Channels[3]<<=1; /* double noise volume */
buffer[j] =0; buffer[j] =0;
for (i=0;i<=3;++i) buffer[j] += p->Channels[i]; for (i=0;i<=3;++i) buffer[j] += p->Channels[i];
/* update tone */
p->Clock+=p->dClock; p->Clock+=p->dClock;
p->NumClocksForSample=(int)p->Clock; /* truncates */ p->NumClocksForSample=(int)p->Clock; /* truncates */
p->Clock-=p->NumClocksForSample; /* remove integer part */ p->Clock-=p->NumClocksForSample; /* remove integer part */
@ -218,7 +228,7 @@ void SN76489_Update(int which, INT16 *buffer, int length)
/* Noise channel */ /* Noise channel */
if (p->ToneFreqVals[3]<=0) { /* If it gets below 0... */ if (p->ToneFreqVals[3]<=0) { /* If it gets below 0... */
p->ToneFreqPos[3]=-p->ToneFreqPos[3]; /* Flip the flip-flop */ p->ToneFreqPos[3]=-p->ToneFreqPos[3]; /* Flip the flip-flop */
if (p->NoiseFreq!=0x80) /* If not matching tone2, decrement counter */ if (p->NoiseFreq!=0x80) /* If not matching tone2, reset counter */
p->ToneFreqVals[3]+=p->NoiseFreq*(p->NumClocksForSample/p->NoiseFreq+1); p->ToneFreqVals[3]+=p->NoiseFreq*(p->NumClocksForSample/p->NoiseFreq+1);
if (p->ToneFreqPos[3]==1) { /* Only once per cycle... */ if (p->ToneFreqPos[3]==1) { /* Only once per cycle... */
int Feedback; int Feedback;

View File

@ -28,7 +28,7 @@
#ifndef _SN76489_H_ #ifndef _SN76489_H_
#define _SN76489_H_ #define _SN76489_H_
#define MAX_SN76489 4 #define MAX_SN76489 1
/* /*
More testing is needed to find and confirm feedback patterns for More testing is needed to find and confirm feedback patterns for

View File

@ -12,7 +12,7 @@
CC = gcc CC = gcc
AS = nasm -f coff AS = nasm -f coff
LDFLAGS = LDFLAGS =
FLAGS = -I. -I.. -I../z80 -I../m68k -I../dos -I../sound -I../sound/SRC -I../cart_hw -I../cart_hw/svp \ FLAGS = -I. -I.. -I../z80 -I../m68k -I../dos -I../sound -I../sound/SRC -I../cart_hw -I../cart_hw/svp -I../ntsc \
-Wall -g \ -Wall -g \
-O6 -march=i686 -fomit-frame-pointer \ -O6 -march=i686 -fomit-frame-pointer \
-DLSB_FIRST -DX86_ASM -DDOS -DLSB_FIRST -DX86_ASM -DDOS
@ -61,6 +61,9 @@ OBJ += obj/dos.o \
obj/fileio.o \ obj/fileio.o \
obj/loadrom.o obj/loadrom.o
OBJ += obj/sms_ntsc.o \
obj/md_ntsc.o
EXE = ../gen.exe EXE = ../gen.exe
all : $(EXE) all : $(EXE)
@ -102,6 +105,10 @@ obj/%.o : ../m68k/%.c ../m68k/%.h
obj/%.o : ./%.c ./%.h obj/%.o : ./%.c ./%.h
$(CC) -c $< -o $@ $(FLAGS) $(CC) -c $< -o $@ $(FLAGS)
obj/%.o : ../ntsc/%.c ../ntsc/%.h
$(CC) -c $(CFLAGS) $(INCLUDES) $(DEFINES) $< -o $@
pack : pack :
strip $(EXE) strip $(EXE)
upx -1 $(EXE) upx -1 $(EXE)