1
0
mirror of https://github.com/ksherlock/x65.git synced 2024-12-27 13:29:18 +00:00

INCDIR, -D, -i, sublime

More stuff for 6502 fun time
This commit is contained in:
Carl-Henrik Skårstedt 2015-10-05 22:45:42 -07:00
parent 00b149a23d
commit a4598a5c43
4 changed files with 148 additions and 540 deletions

473
README.md

File diff suppressed because one or more lines are too long

View File

@ -173,6 +173,7 @@ enum AssemblerDirective {
AD_ENDIF, // #ENDIF: End a block of #IF/#IFDEF
AD_STRUCT, // STRUCT: Declare a set of labels offset from a base address
AD_REPT, // REPT: Repeat the assembly of the bracketed code a number of times
AD_INCDIR, // INCDIR: Add a folder to search for include files
};
// Operators are either instructions or directives
@ -288,44 +289,6 @@ static const strref str_const("const");
static const strref struct_byte("byte");
static const strref struct_word("word");
// Read in text data (main source, include, etc.)
char* LoadText(strref filename, size_t &size) {
strown<512> file(filename);
if (FILE *f = fopen(file.c_str(), "r")) {
fseek(f, 0, SEEK_END);
size_t _size = ftell(f);
fseek(f, 0, SEEK_SET);
if (char *buf = (char*)calloc(_size, 1)) {
fread(buf, 1, _size, f);
fclose(f);
size = _size;
return buf;
}
fclose(f);
}
size = 0;
return nullptr;
}
// Read in binary data (incbin)
char* LoadBinary(strref filename, size_t &size) {
strown<512> file(filename);
if (FILE *f = fopen(file.c_str(), "rb")) {
fseek(f, 0, SEEK_END);
size_t _size = ftell(f);
fseek(f, 0, SEEK_SET);
if (char *buf = (char*)malloc(_size)) {
fread(buf, _size, 1, f);
fclose(f);
size = _size;
return buf;
}
fclose(f);
}
size = 0;
return nullptr;
}
// Binary search over an array of unsigned integers, may contain multiple instances of same key
unsigned int FindLabelIndex(unsigned int hash, unsigned int *table, unsigned int count)
{
@ -553,6 +516,7 @@ public:
std::vector<LocalLabelRecord> localLabels;
std::vector<char*> loadedData; // free when assembler is completed
std::vector<MemberOffset> structMembers; // labelStructs refer to sets of structMembers
std::vector<strref> includePaths;
strovl symbols; // for building a symbol output file
// context for macros / include files
@ -644,6 +608,11 @@ public:
// Conditional statement evaluation (A==B? A?)
StatusCode EvalStatement(strref line, bool &result);
// Add include folder
void AddIncludeFolder(strref path);
char* LoadText(strref filename, size_t &size);
char* LoadBinary(strref filename, size_t &size);
// constructor
Asm() : output(nullptr) {
@ -683,6 +652,65 @@ void Asm::Cleanup() {
errorEncountered = false;
}
// Read in text data (main source, include, etc.)
char* Asm::LoadText(strref filename, size_t &size) {
strown<512> file(filename);
std::vector<strref>::iterator i = includePaths.begin();
for(;;) {
if (FILE *f = fopen(file.c_str(), "r")) {
fseek(f, 0, SEEK_END);
size_t _size = ftell(f);
fseek(f, 0, SEEK_SET);
if (char *buf = (char*)calloc(_size, 1)) {
fread(buf, 1, _size, f);
fclose(f);
size = _size;
return buf;
}
fclose(f);
}
if (i==includePaths.end())
break;
file.copy(*i);
if (file.get_last()!='/' && file.get_last()!='\\')
file.append('/');
file.append(filename);
++i;
}
size = 0;
return nullptr;
}
// Read in binary data (incbin)
char* Asm::LoadBinary(strref filename, size_t &size) {
strown<512> file(filename);
std::vector<strref>::iterator i = includePaths.begin();
for(;;) {
if (FILE *f = fopen(file.c_str(), "rb")) {
fseek(f, 0, SEEK_END);
size_t _size = ftell(f);
fseek(f, 0, SEEK_SET);
if (char *buf = (char*)malloc(_size)) {
fread(buf, _size, 1, f);
fclose(f);
size = _size;
return buf;
}
fclose(f);
}
if (i==includePaths.end())
break;
file.copy(*i);
if (file.get_last()!='/' && file.get_last()!='\\')
file.append('/');
file.append(filename);
++i;
}
size = 0;
return nullptr;
}
// Make sure there is room to assemble in
void Asm::CheckOutputCapacity(unsigned int addSize) {
size_t currSize = curr - output;
@ -1682,8 +1710,19 @@ StatusCode Asm::EvalStatement(strref line, bool &result)
return STATUS_OK;
}
// Add a folder for including files
void Asm::AddIncludeFolder(strref path)
{
if (!path)
return;
for (std::vector<strref>::const_iterator i=includePaths.begin(); i!=includePaths.end(); ++i) {
if (path.same_str(*i))
return;
}
if (includePaths.size()==includePaths.capacity())
includePaths.reserve(includePaths.size() + 16);
includePaths.push_back(path);
}
// unique key binary search
int LookupOpCodeIndex(unsigned int hash, OP_ID *lookup, int count)
@ -1734,6 +1773,7 @@ DirectiveName aDirectiveNames[] {
{ "#ENDIF", AD_ENDIF },
{ "STRUCT", AD_STRUCT },
{ "REPT", AD_REPT },
{ "INCDIR", AD_INCDIR },
};
static const int nDirectiveNames = sizeof(aDirectiveNames) / sizeof(aDirectiveNames[0]);
@ -2057,6 +2097,9 @@ StatusCode Asm::ApplyDirective(AssemblerDirective dir, strref line, strref sourc
}
break;
}
case AD_INCDIR:
AddIncludeFolder(line.between('"', '"'));
break;
}
return error;
}
@ -2539,21 +2582,36 @@ void Asm::Assemble(strref source, strref filename)
}
}
int main(int argc, char **argv)
{
int return_value = 0;
bool c64 = true;
Asm assembler;
const char* source_filename=nullptr, *binary_out_name=nullptr;
const char* sym_file=nullptr;
const char *source_filename=nullptr, *binary_out_name=nullptr;
const char *sym_file=nullptr, *vs_file=nullptr;
for (int a=1; a<argc; a++) {
strref arg(argv[a]);
if (arg.same_str("-c64"))
c64 = true;
else if (arg.same_str("-bin"))
c64 = false;
else if (arg.same_str("-sym") && (a+1)<argc)
sym_file = argv[++a];
if (arg.get_first()=='-') {
++arg;
if (arg.get_first()=='i')
assembler.AddIncludeFolder(arg+1);
else if (arg.get_first()=='D' || arg.get_first()=='d') {
++arg;
if (arg.find('=')>0)
assembler.AssignLabel(arg.before('='), arg.after('='));
else
assembler.AssignLabel(arg, "1");
} else if (arg.same_str("c64"))
c64 = true;
else if (arg.same_str("bin"))
c64 = false;
else if (arg.same_str("sym") && (a + 1) < argc)
sym_file = argv[++a];
else if (arg.same_str("vice") && (a + 1) < argc)
vs_file = argv[++a];
}
else if (!source_filename)
source_filename = arg.get();
else if (!binary_out_name)
@ -2561,37 +2619,57 @@ int main(int argc, char **argv)
}
if (!source_filename) {
puts("Usage:\nAsm6502 <-c64 / -bin> filename.s code.prg <-sym code.sym> \n"
"* -c64: Include load address\n * -bin: Raw binary\n * -sym: vice/kick asm symbol file\n");
puts("Usage:\nAsm6502 [options] filename.s code.prg\n"
" * -i<path>: Add include path\n * -D<label>[=<value>]: Define a label with an optional value (otherwise 1)\n"
" * -c64: Include load address\n * -bin: Raw binary\n * -sym <file.sym>: vice/kick asm symbol file\n"
" * -vice <file.vs>: export a vice symbol file\nhttps://github.com/sakrac/Asm6502\n");
return 0;
}
// Load source
if (source_filename) {
size_t size = 0;
if (char *buffer = LoadText(source_filename, size)) {
Asm assembler;
if (char *buffer = assembler.LoadText(source_filename, size)) {
assembler.symbol_export = sym_file!=nullptr;
assembler.Assemble(strref(buffer, strl_t(size)), strref(argv[1]));
if (binary_out_name && assembler.curr > assembler.output) {
if (FILE *f = fopen(binary_out_name, "wb")) {
if (c64) {
char addr[2] = { (char)assembler.load_address, (char)(assembler.load_address>>8) };
fwrite(addr, 2, 1, f);
}
fwrite(assembler.output, assembler.curr-assembler.output, 1, f);
fclose(f);
}
}
if (sym_file && assembler.symbols.get_len()) {
if (FILE *f = fopen(sym_file, "w")) {
fwrite(assembler.symbols.get(), assembler.symbols.get_len(), 1, f);
fclose(f);
}
}
if (assembler.errorEncountered)
return_value = 1;
else {
if (binary_out_name && assembler.curr > assembler.output) {
if (FILE *f = fopen(binary_out_name, "wb")) {
if (c64) {
char addr[2] = { (char)assembler.load_address, (char)(assembler.load_address >> 8) };
fwrite(addr, 2, 1, f);
}
fwrite(assembler.output, assembler.curr - assembler.output, 1, f);
fclose(f);
}
}
if (sym_file && assembler.symbols.get_len()) {
if (FILE *f = fopen(sym_file, "w")) {
fwrite(assembler.symbols.get(), assembler.symbols.get_len(), 1, f);
fclose(f);
}
}
if (vs_file && assembler.symbols.get_len()) {
if (FILE *f = fopen(vs_file, "w")) {
strref syms = assembler.symbols.get_strref();
while (strref label = syms.line()) {
if (label.has_prefix(".label")) {
label.next_word_ws();
strref name = label.split_token_trim('=');
if (label[0] == '$')
++label;
fprintf(f, "al " STRREF_FMT " " STRREF_FMT"\n", STRREF_ARG(label), STRREF_ARG(name));
}
}
fclose(f);
}
}
}
// free some memory
assembler.Cleanup();
}

Binary file not shown.

1
sublime/README.md Normal file
View File

@ -0,0 +1 @@
# Asm6502 - Sublime Text Package [Sublime Text 3](http://www.sublimetext.com/3) is a great text editor that supports custom languages and build scripts, Asm6502.sublime-package is a single file collection of config files that enable Asm6502 language syntax, Asm6502 Build and an Asm6502 color theme that's got some c64 colors in it as well. Copy Asm6502.sublime-package from this folder to: Windows: ``` %USERPROFILE%\AppData\Roaming\Sublime Text 3\Installed Packages\ ``` OSX: ``` ~/Library/Application Support/Sublime Text 3/Installed Packages/ ``` Compile a 64 or 32 bit release build of Asm6502 and put it into c:\c64\asm6502\asm6502.exe Download the Vice C64 Emulator into c:\vice or c:\c64\vice Within Sublime Text set the Build System to Asm6502 with a 6502 .s or .asm source file loaded and press Ctrl+B to build, or Ctrl+6 to build and launch Vice with the built prg file. With sincere apologies to the author of the Sublime Text package for Kick Assembler without which I would have spent countless hours to figure this out, check out the kick assembler Sublime package here: http://goatpower.org/projects-releases/sublime-package-kick-assembler-c64/ Feel free to modify this package as desired. To open up the individual files add a '.zip' extension to Asm6502.sublime-package and unzip it and paste the files to ``` %USERPROFILE%\AppData\Roaming\Sublime Text 3\Packages\Asm6502 ```