home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Large Pack of OldSkool DOS MOD Trackers
/
goattracker_2.73.zip
/
src
/
gt2reloc.c
< prev
next >
Wrap
C/C++ Source or Header
|
2014-07-23
|
12KB
|
441 lines
//
// GOATTRACKER v2.73 - gt2reloc (commandline relocator/packer)
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
#define GOATTRK2_C
#ifdef __WIN32__
#include <windows.h>
#endif
#include "goattrk2.h"
#include "bme.h"
int menu = 0;
int editmode = EDIT_PATTERN;
int recordmode = 1;
int followplay = 0;
int hexnybble = -1;
int stepsize = 4;
int autoadvance = 0;
int defaultpatternlength = 64;
int cursorflash = 0;
int cursorcolortable[] = {1,2,7,2};
int exitprogram = 0;
int eacolumn = 0;
int eamode = 0;
unsigned keypreset = KEY_TRACKER;
unsigned playerversion = 0;
int fileformat = FORMAT_PRG;
int zeropageadr = 0xfc;
int playeradr = 0x1000;
unsigned sidmodel = 0;
unsigned multiplier = 1;
unsigned adparam = 0x0f00;
unsigned ntsc = 0;
unsigned patternhex = 0;
unsigned sidaddress = 0xd400;
unsigned finevibrato = 1;
unsigned optimizepulse = 1;
unsigned optimizerealtime = 1;
unsigned customclockrate = 0;
unsigned usefinevib = 0;
unsigned b = DEFAULTBUF;
unsigned mr = DEFAULTMIXRATE;
unsigned writer = 0;
unsigned hardsid = 0;
unsigned catweasel = 0;
unsigned interpolate = 0;
unsigned residdelay = 0;
unsigned hardsidbufinteractive = 20;
unsigned hardsidbufplayback = 400;
float basepitch = 0.0f;
char configbuf[MAX_PATHNAME];
char loadedsongfilename[MAX_FILENAME];
char songfilename[MAX_FILENAME];
char songfilter[MAX_FILENAME];
char songpath[MAX_PATHNAME];
char instrfilename[MAX_FILENAME];
char instrfilter[MAX_FILENAME];
char instrpath[MAX_PATHNAME];
char packedpath[MAX_PATHNAME];
char packedsongname[MAX_PATHNAME];
char *programname = "$VER: GoatTracker v2.73";
char textbuffer[MAX_PATHNAME];
extern unsigned char datafile[];
#ifdef __WIN32__
FILE *STDOUT, *STDERR;
#else
#define STDOUT stdout
#define STDERR stderr
#endif
void usage(void)
{
fprintf(STDOUT, "Usage: GT2RELOC <songname> <outfile> [options]\n");
fprintf(STDOUT, "Options:\n");
fprintf(STDOUT, "-Axx Set ADSR parameter for hardrestart in hex. DEFAULT=0F00\n");
fprintf(STDOUT, "-Bx enable/disable buffered SID writes. DEFAULT=disabled\n");
fprintf(STDOUT, "-Cx enable/disable zeropage ghost registers. DEFAULT=disabled\n");
fprintf(STDOUT, "-Dx enable/disable sound effect support. DEFAULT=disabled\n");
fprintf(STDOUT, "-Ex enable/disable volume change support. DEFAULT=disabled\n");
fprintf(STDOUT, "-Fxx Set custom SID clock cycles per second (0 = use PAL/NTSC default)\n");
fprintf(STDOUT, "-Gxx Set pitch of A-4 in Hz (0 = use default frequencytable, close to 440Hz)\n");
fprintf(STDOUT, "-Hx enable/disable storing of author info. DEFAULT=disabled\n");
fprintf(STDOUT, "-Ix enable/disable optimizations. DEFAULT=enabled\n");
fprintf(STDOUT, "-Jx enable/disable full buffering. DEFAULT=disabled\n");
fprintf(STDOUT, "-Lxx SID memory location in hex. DEFAULT=D400\n");
fprintf(STDOUT, "-N Use NTSC timing\n");
fprintf(STDOUT, "-Oxx Set pulseoptimization/skipping (0 = off, 1 = on) DEFAULT=on\n");
fprintf(STDOUT, "-P Use PAL timing (DEFAULT)\n");
fprintf(STDOUT, "-Rxx Set realtime-effect optimization/skipping (0 = off, 1 = on) DEFAULT=on\n");
fprintf(STDOUT, "-Sxx Set speed multiplier (0 for 25Hz, 1 for 1x, 2 for 2x etc.) DEFAULT=1\n");
fprintf(STDOUT, "-Vxx Set finevibrato conversion (0 = off, 1 = on) DEFAULT=on\n");
fprintf(STDOUT, "-Wxx player memory location highbyte in hex. DEFAULT=1000\n");
fprintf(STDOUT, "-Zxx zeropage memory location in hex. DEFAULT=FC\n");
fprintf(STDOUT, "-? Show options\n");
}
int main(int argc, char **argv)
{
int c;
#ifdef __WIN32__
/*
SDL_Init() reroutes stdout and stderr, either to stdout.txt and stderr.txt
or to nirwana. simply reopening these handles does, other than suggested on
some web pages, not work reliably - opening new files on CON using different
handles however does.
*/
STDOUT = fopen("CON", "w");
STDERR = fopen("CON", "w");
#endif
programname += sizeof "$VER:";
// Open datafile
io_openlinkeddatafile(datafile);
// Reset channels/song
initchannels();
clearsong(1,1,1,1,1);
// get input- and output file names
if (argc >= 3) {
strcpy(songfilename, argv[1]);
strcpy(packedsongname, argv[2]);
} else {
usage();
exit(-1);
}
// Load song
if (strlen(songfilename)) {
loadsong();
} else {
fprintf(STDERR, "error: no song filename given.\n");
exit (-1);
}
c = strlen(packedsongname);
if (strlen(packedsongname) <= 0) {
fprintf(STDERR, "error: no output filename given.\n");
exit (-1);
}
// determine output format from file extension of the output filename
c--;
while ((c > 0) && (packedsongname[c] != '.')) c--;
if (packedsongname[c] == '.') c++;
if (!strcmp(&packedsongname[c], "sid")) {
fileformat = FORMAT_SID;
} else if (!strcmp(&packedsongname[c], "prg")) {
fileformat = FORMAT_PRG;
} else if (!strcmp(&packedsongname[c], "bin")) {
fileformat = FORMAT_BIN;
} else {
fileformat = FORMAT_PRG;
}
fprintf(STDOUT, "%s Packer/Relocator\n", programname);
fprintf(STDOUT, "song file: %s\n", loadedsongfilename);
fprintf(STDOUT, "output file: %s\n", packedsongname);
fprintf(STDOUT, "output format: ");
if (fileformat == FORMAT_SID) {
fprintf(STDOUT, "sid\n");
} else if (fileformat == FORMAT_BIN) {
fprintf(STDOUT, "bin\n");
} else {
fprintf(STDOUT, "prg\n");
}
// Scan command line
for (c = 3; c < argc; c++)
{
#ifdef __WIN32__
if ((argv[c][0] == '-') || (argv[c][0] == '/'))
#else
if (argv[c][0] == '-')
#endif
{
switch(toupper(argv[c][1]))
{
case '?':
return 0;
case 'A':
sscanf(&argv[c][2], "%x", &adparam);
break;
case 'G':
sscanf(&argv[c][2], "%f", &basepitch);
break;
case 'L':
sscanf(&argv[c][2], "%x", &sidaddress);
break;
case 'O':
sscanf(&argv[c][2], "%u", &optimizepulse);
break;
case 'R':
sscanf(&argv[c][2], "%u", &optimizerealtime);
break;
case 'V':
sscanf(&argv[c][2], "%u", &finevibrato);
break;
case 'S':
sscanf(&argv[c][2], "%u", &multiplier);
break;
// NTSC timing
case 'N':
ntsc = 1;
customclockrate = 0;
break;
// PAL timing
case 'P':
ntsc = 0;
customclockrate = 0;
break;
// custom clock rate
case 'F':
sscanf(&argv[c][2], "%u", &customclockrate);
break;
// player options (first menu)
// 0: Buffered SID-writes
case 'B':
if (argv[c][2] == '1') {
playerversion |= PLAYER_BUFFERED;
} else {
playerversion &= ~PLAYER_BUFFERED;
}
break;
// 1: Sound effect support
case 'D':
if (argv[c][2] == '1') {
playerversion |= PLAYER_SOUNDEFFECTS;
} else {
playerversion &= ~PLAYER_SOUNDEFFECTS;
}
break;
// 2: Volume change support
case 'E':
if (argv[c][2] == '1') {
playerversion |= PLAYER_VOLUME;
} else {
playerversion &= ~PLAYER_VOLUME;
}
break;
// 3: Store author-info
case 'H':
if (argv[c][2] == '1') {
playerversion |= PLAYER_AUTHORINFO;
} else {
playerversion &= ~PLAYER_AUTHORINFO;
}
break;
// 4: Use zeropage ghostregs
case 'C':
if (argv[c][2] == '1') {
playerversion |= PLAYER_ZPGHOSTREGS;
} else {
playerversion &= ~PLAYER_ZPGHOSTREGS;
}
break;
// 5: Disable optimization
case 'I':
if (argv[c][2] == '1') {
playerversion &= ~PLAYER_NOOPTIMIZATION;
} else {
playerversion |= PLAYER_NOOPTIMIZATION;
}
// 6: Full buffering
case 'J':
if (argv[c][2] == '1') {
playerversion &= ~PLAYER_FULLBUFFERED;
} else {
playerversion |= PLAYER_FULLBUFFERED;
}
break;
// start address (second menu)
case 'W':
sscanf(&argv[c][2], "%x", &playeradr);
playeradr<<=8;
break;
// zeropage address (third menu)
case 'Z':
sscanf(&argv[c][2], "%x", &zeropageadr);
break;
}
}
else
{
fprintf(STDERR, "error: unknown option\n");
usage();
exit(-1);
}
}
// Validate parameters
sidmodel &= 1;
adparam &= 0xffff;
zeropageadr &= 0xff;
playeradr &= 0xff00;
sidaddress &= 0xffff;
if (multiplier > 16) multiplier = 16;
if ((finevibrato == 1) && (multiplier < 2)) usefinevib = 1;
if (finevibrato > 1) usefinevib = 1;
if (optimizepulse > 1) optimizepulse = 1;
if (optimizerealtime > 1) optimizerealtime = 1;
if (customclockrate < 100) customclockrate = 0;
// Calculate frequencytable if necessary
if (basepitch < 0.0f)
basepitch = 0.0f;
if (basepitch > 0.0f)
calculatefreqtable();
// perform relocation
relocator();
// Exit
return 0;
}
void waitkeymousenoupdate(void)
{
}
void getparam(FILE *handle, unsigned *value)
{
char *configptr;
for (;;)
{
if (feof(handle)) return;
fgets(configbuf, MAX_PATHNAME, handle);
if ((configbuf[0]) && (configbuf[0] != ';') && (configbuf[0] != ' ') && (configbuf[0] != 13) && (configbuf[0] != 10)) break;
}
configptr = configbuf;
if (*configptr == '$')
{
*value = 0;
configptr++;
for (;;)
{
char c = tolower(*configptr++);
int h = -1;
if ((c >= 'a') && (c <= 'f')) h = c - 'a' + 10;
if ((c >= '0') && (c <= '9')) h = c - '0';
if (h >= 0)
{
*value *= 16;
*value += h;
}
else break;
}
}
else
{
*value = 0;
for (;;)
{
char c = tolower(*configptr++);
int d = -1;
if ((c >= '0') && (c <= '9')) d = c - '0';
if (d >= 0)
{
*value *= 10;
*value += d;
}
else break;
}
}
}
void getfloatparam(FILE *handle, float *value)
{
char *configptr;
for (;;)
{
if (feof(handle)) return;
fgets(configbuf, MAX_PATHNAME, handle);
if ((configbuf[0]) && (configbuf[0] != ';') && (configbuf[0] != ' ') && (configbuf[0] != 13) && (configbuf[0] != 10)) break;
}
configptr = configbuf;
*value = 0.0f;
sscanf(configptr, "%f", value);
}
void calculatefreqtable()
{
double basefreq = (double)basepitch * (16777216.0 / 985248.0) * pow(2.0, 0.25) / 32.0;
int c;
for (c = 0; c < 8*12 ; c++)
{
double note = c;
double freq = basefreq * pow(2.0, note/12.0);
int intfreq = freq + 0.5;
if (intfreq > 0xffff)
intfreq = 0xffff;
freqtbllo[c] = intfreq & 0xff;
freqtblhi[c] = intfreq >> 8;
}
}