540 lines
23 KiB
C++
540 lines
23 KiB
C++
#include <cmath>
|
|
|
|
#include "memory.h"
|
|
#include "cpu.h"
|
|
#include "loader.h"
|
|
#include "expression.h"
|
|
#include "assembler.h"
|
|
#include "compiler.h"
|
|
#include "pragmas.h"
|
|
|
|
|
|
namespace Pragmas
|
|
{
|
|
std::map<std::string, Pragma> _pragmas;
|
|
|
|
|
|
std::map<std::string, Pragma>& getPragmas(void) {return _pragmas;}
|
|
|
|
|
|
bool initialise(void)
|
|
{
|
|
// Pragmas
|
|
_pragmas["_codeRomType_"] = {"_codeRomType_", CODEROMTYPE };
|
|
_pragmas["_runtimePath_"] = {"_runtimePath_", RUNTIMEPATH };
|
|
_pragmas["_runtimeStart_"] = {"_runtimeStart_", RUNTIMESTART };
|
|
_pragmas["_userCodeStart_"] = {"_userCodeStart_", USERCODESTART };
|
|
_pragmas["_arraysStart_"] = {"_arraysStart_", ARRAYSSTART };
|
|
_pragmas["_stringsStart_"] = {"_stringsStart_", STRINGSSTART };
|
|
_pragmas["_stringWorkArea_"] = {"_stringWorkArea_", STRINGWORKAREA };
|
|
_pragmas["_tempVarSize_"] = {"_tempVarSize_", TEMPVARSIZE };
|
|
_pragmas["_codeOptimiseType_"] = {"_codeOptimiseType_", CODEOPTIMISETYPE };
|
|
_pragmas["_arrayIndiciesOne_"] = {"_arrayIndiciesOne_", ARRAYINDICIESONE };
|
|
_pragmas["_maxNumSprites_"] = {"_maxNumSprites_", MAXNUMSPRITES };
|
|
_pragmas["_spriteStripeChunks_"] = {"_spriteStripeChunks_", SPRITESTRIPECHUNKS};
|
|
_pragmas["_enable6BitAudioEmu_"] = {"_enable6BitAudioEmu_", ENABLE6BITAUDIOEMU};
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool findPragma(std::string code, const std::string& pragma, size_t& foundPos)
|
|
{
|
|
foundPos = code.find(pragma);
|
|
if(foundPos != std::string::npos)
|
|
{
|
|
foundPos += pragma.size();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
PragmaResult handlePragmas(std::string& input, int codeLineIndex)
|
|
{
|
|
std::vector<std::string> tokens = Expression::tokenise(input, ' ', false);
|
|
if(tokens.size() >= 1)
|
|
{
|
|
std::string token = tokens[0];
|
|
Expression::stripNonStringWhitespace(token);
|
|
|
|
if(_pragmas.find(token) == _pragmas.end()) return PragmaNotFound;
|
|
|
|
// Handle pragma in input
|
|
size_t foundPos;
|
|
if(findPragma(token, _pragmas[token]._name, foundPos) && _pragmas[token]._func)
|
|
{
|
|
bool success = _pragmas[token]._func(input, codeLineIndex, foundPos);
|
|
if(success) return PragmaFound;
|
|
|
|
return PragmaError;
|
|
}
|
|
}
|
|
|
|
return PragmaNotFound;
|
|
}
|
|
|
|
|
|
// ********************************************************************************************
|
|
// Pragmas
|
|
// ********************************************************************************************
|
|
bool CODEROMTYPE(const std::string& input, int codeLineIndex, size_t foundPos)
|
|
{
|
|
// Get rom type
|
|
std::string pragma = input.substr(foundPos);
|
|
Expression::stripNonStringWhitespace(pragma);
|
|
Expression::strToUpper(pragma);
|
|
if(Cpu::getRomTypeMap().find(pragma) == Cpu::getRomTypeMap().end())
|
|
{
|
|
fprintf(stderr, "Pragmas::CODEROMTYPE() : 'Main:%d' : syntax error, use _codeRomType_ <\"ROM TYPE\"> : %s\n", codeLineIndex + 1, input.c_str());
|
|
return false;
|
|
}
|
|
|
|
Compiler::setCodeRomType(Cpu::getRomTypeMap()[pragma]);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool RUNTIMEPATH(const std::string& input, int codeLineIndex, size_t foundPos)
|
|
{
|
|
std::string pragma = input.substr(foundPos);
|
|
Expression::stripNonStringWhitespace(pragma);
|
|
if(pragma.size() < 3 || !Expression::isStringValid(pragma))
|
|
{
|
|
fprintf(stderr, "Pragmas::RUNTIMEPATH() : 'Main:%d' : syntax error, use _runtimePath_ <\"Path to runtime\"> : %s\n", codeLineIndex + 1, input.c_str());
|
|
return false;
|
|
}
|
|
|
|
// Strip quotes
|
|
std::string runtimePath = pragma;
|
|
runtimePath.erase(0, 1);
|
|
runtimePath.erase(runtimePath.size() - 1, 1);
|
|
|
|
// Set build path
|
|
Compiler::setBuildPath(runtimePath, Loader::getFilePath());
|
|
|
|
return true;
|
|
}
|
|
|
|
bool RUNTIMESTART(const std::string& input, int codeLineIndex, size_t foundPos)
|
|
{
|
|
std::string pragma = input.substr(foundPos);
|
|
Expression::stripNonStringWhitespace(pragma);
|
|
std::vector<std::string> tokens = Expression::tokenise(pragma, ',', false);
|
|
if(tokens.size() != 1)
|
|
{
|
|
fprintf(stderr, "Pragmas::RUNTIMESTART() : 'Main:%d' : syntax error, use _runtimeStart_ <address> : %s\n", codeLineIndex + 1, input.c_str());
|
|
return false;
|
|
}
|
|
|
|
Expression::Numeric addrNumeric;
|
|
std::string addrOperand;
|
|
if(Compiler::parseStaticExpression(codeLineIndex, tokens[0], addrOperand, addrNumeric) == Compiler::OperandInvalid)
|
|
{
|
|
fprintf(stderr, "Pragmas::RUNTIMESTART() : 'Main:%d' : syntax error in address field %s : %s\n", codeLineIndex + 1, tokens[0].c_str(), input.c_str());
|
|
return false;
|
|
}
|
|
uint16_t address = uint16_t(std::lround(addrNumeric._value));
|
|
if(address < DEFAULT_EXEC_ADDRESS)
|
|
{
|
|
fprintf(stderr, "Pragmas::RUNTIMESTART() : 'Main:%d' : address field must be above &h%04x, found %s : %s\n", codeLineIndex + 1, DEFAULT_EXEC_ADDRESS, tokens[0].c_str(), input.c_str());
|
|
return false;
|
|
}
|
|
|
|
Compiler::setRuntimeStart(address);
|
|
|
|
// Re-initialise memory manager for 64K
|
|
if(address >= RAM_UPPER_START && Memory::getSizeRAM() != RAM_SIZE_HI)
|
|
{
|
|
Memory::setSizeRAM(RAM_SIZE_HI);
|
|
}
|
|
|
|
// String work area needs to be updated, (return old work areas and get new ones)
|
|
for(int i=0; i<NUM_STR_WORK_AREAS; i++)
|
|
{
|
|
uint16_t strWorkArea;
|
|
Memory::giveFreeRAM(Compiler::getStrWorkArea(i), USER_STR_SIZE + 2);
|
|
if(!Memory::getFreeRAM(Memory::FitDescending, USER_STR_SIZE + 2, USER_CODE_START, address, strWorkArea))
|
|
{
|
|
fprintf(stderr, "Pragmas::RUNTIMESTART() : 'Main:%d' : setting new String Work Area failed : %s\n", codeLineIndex + 1, input.c_str());
|
|
return false;
|
|
}
|
|
Compiler::setStrWorkArea(strWorkArea, i);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool USERCODESTART(const std::string& input, int codeLineIndex, size_t foundPos)
|
|
{
|
|
std::string pragma = input.substr(foundPos);
|
|
Expression::stripNonStringWhitespace(pragma);
|
|
std::vector<std::string> tokens = Expression::tokenise(pragma, ',', false);
|
|
if(tokens.size() != 1)
|
|
{
|
|
fprintf(stderr, "Pragmas::USERCODESTART() : 'Main:%d' : syntax error, use _userCodeStart_ <address> : %s\n", codeLineIndex + 1, input.c_str());
|
|
return false;
|
|
}
|
|
|
|
Expression::Numeric addrNumeric;
|
|
std::string addrOperand;
|
|
if(Compiler::parseStaticExpression(codeLineIndex, tokens[0], addrOperand, addrNumeric) == Compiler::OperandInvalid)
|
|
{
|
|
fprintf(stderr, "Pragmas::USERCODESTART() : 'Main:%d' : syntax error in address field %s : %s\n", codeLineIndex + 1, tokens[0].c_str(), input.c_str());
|
|
return false;
|
|
}
|
|
uint16_t address = uint16_t(std::lround(addrNumeric._value));
|
|
if(address < DEFAULT_EXEC_ADDRESS)
|
|
{
|
|
fprintf(stderr, "Pragmas::USERCODESTART() : 'Main:%d' : address field must be above &h%04x, found %s : %s\n", codeLineIndex + 1, DEFAULT_EXEC_ADDRESS, tokens[0].c_str(), input.c_str());
|
|
return false;
|
|
}
|
|
|
|
// Programmer wants to use video memory as code space
|
|
if(address >= 0x0800 && address < 0x7FA0 && (address & 0x00FF) < 0x00A0) Memory::invertFreeRAM();
|
|
|
|
Compiler::setUserCodeStart(address);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ARRAYSSTART(const std::string& input, int codeLineIndex, size_t foundPos)
|
|
{
|
|
std::string pragma = input.substr(foundPos);
|
|
Expression::stripNonStringWhitespace(pragma);
|
|
std::vector<std::string> tokens = Expression::tokenise(pragma, ',', false);
|
|
if(tokens.size() != 1)
|
|
{
|
|
fprintf(stderr, "Pragmas::ARRAYSSTART() : 'Main:%d' : syntax error, use _arraysStart_ <address> : %s\n", codeLineIndex + 1, input.c_str());
|
|
return false;
|
|
}
|
|
|
|
Expression::Numeric addrNumeric;
|
|
std::string addrOperand;
|
|
if(Compiler::parseStaticExpression(codeLineIndex, tokens[0], addrOperand, addrNumeric) == Compiler::OperandInvalid)
|
|
{
|
|
fprintf(stderr, "Pragmas::ARRAYSSTART() : 'Main:%d' : syntax error in address field %s : %s\n", codeLineIndex + 1, tokens[0].c_str(), input.c_str());
|
|
return false;
|
|
}
|
|
uint16_t address = uint16_t(std::lround(addrNumeric._value));
|
|
if(address < DEFAULT_EXEC_ADDRESS)
|
|
{
|
|
fprintf(stderr, "Pragmas::ARRAYSSTART() : 'Main:%d' : address field must be above &h%04x, found %s : %s\n", codeLineIndex + 1, DEFAULT_EXEC_ADDRESS, tokens[0].c_str(), input.c_str());
|
|
return false;
|
|
}
|
|
|
|
Compiler::setArraysStart(address);
|
|
|
|
// Re-initialise memory manager for 64K
|
|
if(address >= RAM_UPPER_START && Memory::getSizeRAM() != RAM_SIZE_HI)
|
|
{
|
|
Memory::setSizeRAM(RAM_SIZE_HI);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool STRINGSSTART(const std::string& input, int codeLineIndex, size_t foundPos)
|
|
{
|
|
std::string pragma = input.substr(foundPos);
|
|
Expression::stripNonStringWhitespace(pragma);
|
|
std::vector<std::string> tokens = Expression::tokenise(pragma, ',', false);
|
|
if(tokens.size() != 1)
|
|
{
|
|
fprintf(stderr, "Pragmas::STRINGSSTART() : 'Main:%d' : syntax error, use _stringsStart_ <address> : %s\n", codeLineIndex + 1, input.c_str());
|
|
return false;
|
|
}
|
|
|
|
Expression::Numeric addrNumeric;
|
|
std::string addrOperand;
|
|
if(Compiler::parseStaticExpression(codeLineIndex, tokens[0], addrOperand, addrNumeric) == Compiler::OperandInvalid)
|
|
{
|
|
fprintf(stderr, "Pragmas::STRINGSSTART() : 'Main:%d' : syntax error in address field %s : %s\n", codeLineIndex + 1, tokens[0].c_str(), input.c_str());
|
|
return false;
|
|
}
|
|
uint16_t address = uint16_t(std::lround(addrNumeric._value));
|
|
if(address < DEFAULT_EXEC_ADDRESS)
|
|
{
|
|
fprintf(stderr, "Pragmas::STRINGSSTART() : 'Main:%d' : address field must be above &h%04x, found %s : %s\n", codeLineIndex + 1, DEFAULT_EXEC_ADDRESS, tokens[0].c_str(), input.c_str());
|
|
return false;
|
|
}
|
|
|
|
Compiler::setStringsStart(address);
|
|
|
|
// Re-initialise memory manager for 64K
|
|
if(address >= RAM_UPPER_START && Memory::getSizeRAM() != RAM_SIZE_HI)
|
|
{
|
|
Memory::setSizeRAM(RAM_SIZE_HI);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool STRINGWORKAREA(const std::string& input, int codeLineIndex, size_t foundPos)
|
|
{
|
|
std::string pragma = input.substr(foundPos);
|
|
Expression::stripNonStringWhitespace(pragma);
|
|
std::vector<std::string> tokens = Expression::tokenise(pragma, ',', false);
|
|
if(tokens.size() != 1)
|
|
{
|
|
fprintf(stderr, "Pragmas::STRINGWORKAREA() : 'Main:%d' : syntax error, use _stringWorkArea_ <address> : %s\n", codeLineIndex + 1, input.c_str());
|
|
return false;
|
|
}
|
|
|
|
Expression::Numeric addrNumeric;
|
|
std::string addrOperand;
|
|
if(Compiler::parseStaticExpression(codeLineIndex, tokens[0], addrOperand, addrNumeric) == Compiler::OperandInvalid)
|
|
{
|
|
fprintf(stderr, "Pragmas::STRINGWORKAREA() : 'Main:%d' : syntax error in address field %s : %s\n", codeLineIndex + 1, tokens[0].c_str(), input.c_str());
|
|
return false;
|
|
}
|
|
uint16_t strWorkArea = uint16_t(std::lround(addrNumeric._value));
|
|
if(strWorkArea < DEFAULT_EXEC_ADDRESS)
|
|
{
|
|
fprintf(stderr, "Pragmas::STRINGWORKAREA() : 'Main:%d' : address field must be above &h%04x, found %s : %s\n", codeLineIndex + 1, DEFAULT_EXEC_ADDRESS, tokens[0].c_str(), input.c_str());
|
|
return false;
|
|
}
|
|
|
|
// String work area needs to be updated, (return old work areas and get new ones)
|
|
Memory::giveFreeRAM(Compiler::getStrWorkArea(0), USER_STR_SIZE + 2);
|
|
if(!Memory::takeFreeRAM(strWorkArea, USER_STR_SIZE + 2))
|
|
{
|
|
fprintf(stderr, "Pragmas::STRINGWORKAREA() : 'Main:%d' : setting new string work area failed : %s\n", codeLineIndex + 1, input.c_str());
|
|
return false;
|
|
}
|
|
Compiler::setStrWorkArea(strWorkArea, 0);
|
|
Memory::giveFreeRAM(Compiler::getStrWorkArea(1), USER_STR_SIZE + 2);
|
|
if(!Memory::getFreeRAM(Memory::FitDescending, USER_STR_SIZE + 2, USER_CODE_START, strWorkArea, strWorkArea))
|
|
{
|
|
fprintf(stderr, "Pragmas::STRINGWORKAREA() : 'Main:%d' : setting new string work area failed : %s\n", codeLineIndex + 1, input.c_str());
|
|
return false;
|
|
}
|
|
Compiler::setStrWorkArea(strWorkArea, 1);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool TEMPVARSIZE(const std::string& input, int codeLineIndex, size_t foundPos)
|
|
{
|
|
std::string pragma = input.substr(foundPos);
|
|
Expression::stripNonStringWhitespace(pragma);
|
|
std::vector<std::string> tokens = Expression::tokenise(pragma, ',', false);
|
|
if(tokens.size() != 1)
|
|
{
|
|
fprintf(stderr, "Pragmas::TEMPVARSIZE() : 'Main:%d' : syntax error, use '_tempVarSize_ <size>' : %s\n", codeLineIndex + 1, input.c_str());
|
|
return false;
|
|
}
|
|
|
|
Expression::Numeric sizeNumeric;
|
|
std::string sizeOperand;
|
|
if(Compiler::parseStaticExpression(codeLineIndex, tokens[0], sizeOperand, sizeNumeric) == Compiler::OperandInvalid)
|
|
{
|
|
fprintf(stderr, "Pragmas::TEMPVARSIZE() : 'Main:%d' : syntax error in size field %s : %s\n", codeLineIndex + 1, tokens[0].c_str(), input.c_str());
|
|
return false;
|
|
}
|
|
uint8_t size = uint8_t(std::lround(sizeNumeric._value));
|
|
if(size < 2 || size > 16)
|
|
{
|
|
fprintf(stderr, "Pragmas::TEMPVARSIZE() : 'Main:%d' : size field must be in the range 2 to 16, found %s : %s\n", codeLineIndex + 1, tokens[0].c_str(), input.c_str());
|
|
return false;
|
|
}
|
|
|
|
Compiler::setTempVarSize(size);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CODEOPTIMISETYPE(const std::string& input, int codeLineIndex, size_t foundPos)
|
|
{
|
|
std::string pragma = input.substr(foundPos);
|
|
Expression::stripNonStringWhitespace(pragma);
|
|
std::vector<std::string> tokens = Expression::tokenise(pragma, ',', false);
|
|
if(tokens.size() != 1)
|
|
{
|
|
fprintf(stderr, "Pragmas::CODEOPTIMISETYPE() : 'Main:%d' : syntax error, use _codeOptimiseType_ <size/speed> : %s\n", codeLineIndex + 1, input.c_str());
|
|
return false;
|
|
}
|
|
|
|
if(tokens[0] == "SIZE")
|
|
{
|
|
Compiler::setCodeOptimiseType(Compiler::CodeSize);
|
|
return true;
|
|
}
|
|
else if(tokens[0] == "SPEED")
|
|
{
|
|
Compiler::setCodeOptimiseType(Compiler::CodeSpeed);
|
|
return true;
|
|
}
|
|
|
|
fprintf(stderr, "Pragmas::CODEOPTIMISETYPE() : 'Main:%d' : syntax error, _use codeOptimiseType_ <'size'/'speed'> : %s\n", codeLineIndex + 1, input.c_str());
|
|
|
|
return false;
|
|
}
|
|
|
|
bool ARRAYINDICIESONE(const std::string& input, int codeLineIndex, size_t foundPos)
|
|
{
|
|
UNREFERENCED_PARAM(input);
|
|
UNREFERENCED_PARAM(foundPos);
|
|
UNREFERENCED_PARAM(codeLineIndex);
|
|
|
|
Compiler::setArrayIndiciesOne(true);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool MAXNUMSPRITES(const std::string& input, int codeLineIndex, size_t foundPos)
|
|
{
|
|
std::string pragma = input.substr(foundPos);
|
|
Expression::stripNonStringWhitespace(pragma);
|
|
std::vector<std::string> tokens = Expression::tokenise(pragma, ',', false, true);
|
|
if(tokens.size() != 1)
|
|
{
|
|
fprintf(stderr, "Pragmas::MAXNUMSPRITES() : 'Main:%d' : syntax error, use _maxNumSprites_ <max num sprites> : %s\n", codeLineIndex + 1, input.c_str());
|
|
return false;
|
|
}
|
|
|
|
// Max num sprites
|
|
Expression::Numeric maxNumNumeric;
|
|
std::string maxNumOperand;
|
|
if(Compiler::parseStaticExpression(codeLineIndex, tokens[0], maxNumOperand, maxNumNumeric) == Compiler::OperandInvalid)
|
|
{
|
|
fprintf(stderr, "Pragmas::MAXNUMSPRITES() : 'Main:%d' : syntax error in max num field %s : %s\n", codeLineIndex + 1, tokens[0].c_str(), input.c_str());
|
|
return false;
|
|
}
|
|
uint16_t maxNumSprites = uint16_t(std::lround(maxNumNumeric._value));
|
|
if(Compiler::getRuntimeStart() < RAM_UPPER_START && maxNumSprites > MAX_NUM_SPRITES_LO)
|
|
{
|
|
fprintf(stderr, "Pragmas::MAXNUMSPRITES() : 'Main:%d' : maximum number of sprites for 32K RAM is limited to %d, found %s : %s\n", codeLineIndex + 1, MAX_NUM_SPRITES_LO, tokens[0].c_str(), input.c_str());
|
|
return false;
|
|
}
|
|
|
|
if(Compiler::getRuntimeStart() >= RAM_UPPER_START && maxNumSprites > MAX_NUM_SPRITES_HI)
|
|
{
|
|
fprintf(stderr, "Pragmas::MAXNUMSPRITES() : 'Main:%d' : maximum number of sprites for 64K RAM is limited to %d, found %s : %s\n", codeLineIndex + 1, MAX_NUM_SPRITES_HI, tokens[0].c_str(), input.c_str());
|
|
return false;
|
|
}
|
|
|
|
// Allocate RAM for sprite's LUT now, otherwise more than 48 sprites in a 32K RAM system can fail
|
|
uint16_t lutAddress;
|
|
int lutSize = int(maxNumSprites) * 2;
|
|
if(!Memory::getFreeRAM(Memory::FitDescending, lutSize, USER_CODE_START, Compiler::getRuntimeStart(), lutAddress))
|
|
{
|
|
fprintf(stderr, "Pragmas::MAXNUMSPRITES() : 'Main:%d' : not enough RAM for sprites LUT of size %d : %s\n", codeLineIndex + 1, lutSize, input.c_str());
|
|
return false;
|
|
}
|
|
Compiler::setSpritesAddrLutAddress(lutAddress);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool SPRITESTRIPECHUNKS(const std::string& input, int codeLineIndex, size_t foundPos)
|
|
{
|
|
std::string pragma = input.substr(foundPos);
|
|
Expression::stripNonStringWhitespace(pragma);
|
|
std::vector<std::string> tokens = Expression::tokenise(pragma, ',', false, true);
|
|
if(tokens.size() < 1 || tokens.size() > 3)
|
|
{
|
|
fprintf(stderr, "Pragmas::SPRITESTRIPECHUNKS() : 'Main:%d' : syntax error, use _spriteStripeChunks_ <num chunks>, <optional minimum address>, <optional ascending/descending> : %s\n", codeLineIndex + 1, input.c_str());
|
|
return false;
|
|
}
|
|
|
|
// Number of chunks
|
|
Expression::Numeric chunksNumeric;
|
|
std::string chunksOperand;
|
|
if(Compiler::parseStaticExpression(codeLineIndex, tokens[0], chunksOperand, chunksNumeric) == Compiler::OperandInvalid)
|
|
{
|
|
fprintf(stderr, "Pragmas::SPRITESTRIPECHUNKS() : 'Main:%d' : syntax error in num chunks field %s : %s\n", codeLineIndex + 1, tokens[0].c_str(), input.c_str());
|
|
return false;
|
|
}
|
|
uint16_t spriteStripeChunks = uint16_t(std::lround(chunksNumeric._value));
|
|
if(spriteStripeChunks > SPRITE_STRIPE_CHUNKS_HI)
|
|
{
|
|
fprintf(stderr, "Pragmas::SPRITESTRIPECHUNKS() : 'Main:%d' : num chunks field can not be larger than %d, found %s : %s\n", codeLineIndex + 1, SPRITE_STRIPE_CHUNKS_HI, tokens[0].c_str(), input.c_str());
|
|
return false;
|
|
}
|
|
|
|
Compiler::setSpriteStripeChunks(spriteStripeChunks);
|
|
|
|
// RAM minimum address
|
|
if(tokens.size() >= 2)
|
|
{
|
|
Expression::Numeric addrNumeric;
|
|
std::string addrOperand;
|
|
if(Compiler::parseStaticExpression(codeLineIndex, tokens[1], addrOperand, addrNumeric) == Compiler::OperandInvalid)
|
|
{
|
|
fprintf(stderr, "Pragmas::SPRITESTRIPECHUNKS() : 'Main:%d' : syntax error in address field %s : %s\n", codeLineIndex + 1, tokens[0].c_str(), input.c_str());
|
|
return false;
|
|
}
|
|
uint16_t minAddress = uint16_t(std::lround(addrNumeric._value));
|
|
if(minAddress < DEFAULT_EXEC_ADDRESS)
|
|
{
|
|
fprintf(stderr, "Pragmas::SPRITESTRIPECHUNKS() : 'Main:%d' : address field must be above &h%04x, found %s : %s\n", codeLineIndex + 1, DEFAULT_EXEC_ADDRESS, tokens[1].c_str(), input.c_str());
|
|
return false;
|
|
}
|
|
|
|
Compiler::setSpriteStripeMinAddress(minAddress);
|
|
}
|
|
|
|
// RAM fit type
|
|
if(tokens.size() == 3)
|
|
{
|
|
if(tokens[2] == "ASCENDING")
|
|
{
|
|
Compiler::setSpriteStripeFitType(Memory::FitAscending);
|
|
return true;
|
|
}
|
|
else if(tokens[2] == "DESCENDING")
|
|
{
|
|
Compiler::setSpriteStripeFitType(Memory::FitDescending);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, "Pragmas::SPRITESTRIPECHUNKS() : 'Main:%d' : search direction field must be 'ascending or descending', found '%s' : %s\n", codeLineIndex + 1, tokens[2].c_str(), input.c_str());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ENABLE6BITAUDIOEMU(const std::string& input, int codeLineIndex, size_t foundPos)
|
|
{
|
|
#ifdef STAND_ALONE
|
|
UNREFERENCED_PARAM(foundPos);
|
|
#endif
|
|
|
|
if(Compiler::getCodeRomType() < Cpu::ROMv5a)
|
|
{
|
|
fprintf(stderr, "Pragmas::ENABLE6BITAUDIOEMU() : 'Main:%d' : version error, '_enable6BitAudioEmu_ <ON/OFF>' only works with ROMv5a or greater; use '_codeRomType_ ROMv5a' : %s\n", codeLineIndex + 1, input.c_str());
|
|
return false;
|
|
}
|
|
|
|
#ifndef STAND_ALONE
|
|
std::string pragma = input.substr(foundPos);
|
|
Expression::stripNonStringWhitespace(pragma);
|
|
std::vector<std::string> tokens = Expression::tokenise(pragma, ',', false, true);
|
|
if(tokens.size() != 1)
|
|
{
|
|
fprintf(stderr, "Pragmas::ENABLE6BITAUDIOEMU() : 'Main:%d' : syntax error, use '_enable6BitAudioEmu_ <ON/OFF>' : %s\n", codeLineIndex + 1, input.c_str());
|
|
return false;
|
|
}
|
|
|
|
// ON/OFF
|
|
bool enable = false;
|
|
Expression::strToUpper(tokens[0]);
|
|
if(tokens[0] == "ON") enable = true;
|
|
else if(tokens[0] == "OFF") enable = false;
|
|
else
|
|
{
|
|
fprintf(stderr, "Pragmas::ENABLE6BITAUDIOEMU() : 'Main:%d' : syntax error, use '_enable6BitAudioEmu_ <ON/OFF>' : %s\n", codeLineIndex + 1, input.c_str());
|
|
return false;
|
|
}
|
|
|
|
Cpu::enable6BitSound(Cpu::ROMv5a, enable);
|
|
return true;
|
|
#else
|
|
fprintf(stderr, "Pragmas::ENABLE6BITAUDIOEMU() : 'Main:%d' : syntax error, '_enable6BitAudioEmu_ <ON/OFF>', only works in emulation mode : %s\n", codeLineIndex + 1, input.c_str());
|
|
return false;
|
|
#endif
|
|
}
|
|
} |