static cell AMX_NATIVE_CALL amx_fpga_load(AMX *amx, const cell *params) { set_port_directions(0); // All as inputs char *fname; amx_StrParam(amx, params[1], fname); uint8_t *buffer; if (amx_Allot(amx, 1024/sizeof(cell), (cell**)&buffer) != 0) return false; bool status = false; if (!fname[0]) { have_custom_image = false; status = fpga_configure(NULL, buffer); set_port_directions(default_pins); } else { have_custom_image = true; FIL file; if (f_open(&file, fname, FA_READ) != FR_OK) return false; status = fpga_configure(&file, buffer); f_close(&file); } amx_Release(amx, (cell*)buffer); return status; }
int call(std::vector<int> const& v) { if (amx && fn) { int rezult; std::vector<cell> cells(v.size() + 1); //precall cells[0] = v.size() * sizeof(cell); for (std::size_t param_id = 0, len = v.size(); param_id < len; ++param_id) { cell* phys_addr; amx_Allot(amx, 1, &cells[param_id + 1], &phys_addr); *phys_addr = v[param_id]; } //call rezult = fn(amx, &cells[0]); //postcall for (std::size_t param_id = 0, len = v.size(); param_id < len; ++param_id) { amx_Release(amx, cells[param_id + 1]); } return rezult; } else { assert(false && "error call null amx"); return -1; } }
int amxinit_fpga(AMX *amx) { static const AMX_NATIVE_INFO funcs[] = { {"fpga_load", amx_fpga_load}, {"fpga_config_outputs", amx_fpga_config_outputs}, {"fpga_read_pins", amx_fpga_read_pins}, {"fpga_write_pins", amx_fpga_write_pins}, {"fpga_read", amx_fpga_read}, {"fpga_write", amx_fpga_write}, {0, 0} }; if (have_custom_image) { uint8_t *buffer; if (amx_Allot(amx, 1024/sizeof(cell), (cell**)&buffer) != 0) return false; have_custom_image = false; fpga_configure(NULL, buffer); // Restore original FPGA image amx_Release(amx, (cell*)buffer); } set_port_directions(default_pins); return amx_Register(amx, funcs, -1); }
int main(int argc,char *argv[]) { extern int amx_ConsoleInit(AMX *amx); extern int amx_ConsoleCleanup(AMX *amx); extern int amx_CoreInit(AMX *amx); extern int amx_CoredCleanp(AMX *amx); size_t memsize; void *program; AMX amx; int index, err; cell amx_addr, *phys_addr; char output[128]; if (argc != 4) PrintUsage(argv[0]); if ((memsize = aux_ProgramSize(argv[1])) == 0) PrintUsage(argv[0]); program = malloc(memsize); if (program == NULL) ErrorExit(NULL, AMX_ERR_MEMORY); err = aux_LoadProgram(&amx, argv[1], program); if (err) ErrorExit(&amx, err); amx_ConsoleInit(amx); err = amx_CoreInit(amx); if (err) ErrorExit(&amx, err); err = amx_FindPublic(&amx, argv[2], &index); if (err) ErrorExit(&amx, err); err = amx_Allot(&amx, strlen(argv[3]) + 1, &amx_addr, &phys_addr); if (err) ErrorExit(&amx, err); amx_SetString(phys_addr, argv[3], 0); err = amx_Exec(&amx, NULL, index, 1, amx_addr); if (err) ErrorExit(&amx, err); amx_GetString(output, phys_addr); amx_Release(&amx, amx_addr); printf("%s returns %s\n", argv[1], output); amx_ConsoleCleanup(&amx); amx_CoreCleanup(&amx); amx_Cleanup(&amx); free(program); return 0; }
uint32_t CScriptTimers::NewEx(char* _scriptName, uint32_t _interval, uint32_t _repeat, cell* _params, AMX* pAMX) { timerCount++; timerData* _timer = new timerData; strncpy(_timer->funcName, _scriptName, 255); _timer->totalTime = _interval; _timer->remainingTime = _interval; _timer->timerRepeat = _repeat; _timer->timerKilled = 0; _timer->timerAMX = pAMX; cell amx_addr[256]; char* szParamList; amx_StrParam(pAMX, _params[4], szParamList); int j, numstr, iOff = 5; if (szParamList == NULL) j = 0; else j = strlen(szParamList); numstr = 0; while (j) { j--; cell *paddr = NULL; if (*(szParamList + j) == 'a') { int numcells = *get_amxaddr(pAMX, _params[j + iOff + 1]); if (amx_Allot(pAMX, numcells, &amx_addr[numstr], &paddr) == AMX_ERR_NONE) { memcpy(paddr, get_amxaddr(pAMX, _params[j + iOff]), numcells * sizeof (cell)); numstr++; } } else if (*(szParamList + j) == 's') { char* szParamText; amx_StrParam(pAMX, _params[j + iOff], szParamText); if (szParamText != NULL && strlen(szParamText) > 0) { int numcells = strlen(szParamText) + 1; if (amx_Allot(pAMX, numcells, &amx_addr[numstr], &paddr) == AMX_ERR_NONE) { amx_SetString(paddr, szParamText, 0, 0, UNLIMITED); numstr++; } } else { *szParamText = 1; *(szParamText + 1) = 0; if (amx_Allot(pAMX, 1, &amx_addr[numstr], &paddr) == AMX_ERR_NONE) { amx_SetString(paddr, szParamText, 0, 0, UNLIMITED); numstr++; } } } else { amx_addr[numstr] = *get_amxaddr(pAMX, _params[j + iOff]); numstr++; } } void* mem = NULL; if (numstr) { mem = malloc(numstr * sizeof (cell)); memcpy(mem, &amx_addr, numstr * sizeof (cell)); _timer->timerParams = mem; } else { _timer->timerParams = NULL; } _timer->paramCount = numstr; timersMap.insert(std::pair<uint32_t, timerData*>(timerCount, _timer)); return timerCount; }
// native ArraySortEx(Array:array, const comparefunc[], data[]="", data_size=0); static cell AMX_NATIVE_CALL ArraySortEx(AMX* amx, cell* params) { CellArray* vec = ArrayHandles.lookup(params[1]); if (!vec) { LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]); return 0; } int len; char* funcName = get_amxstring(amx, params[2], 0, len); int func = registerSPForwardByName(amx, funcName, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_DONE); if (!func) { LogError(amx, AMX_ERR_NATIVE, "The public function \"%s\" was not found.", funcName); return 0; } size_t arraysize = vec->size(); size_t blocksize = vec->blocksize(); cell *array = vec->base(); cell amx_addr1 = 0, amx_addr2 = 0, *phys_addr = NULL; if (blocksize > 1) { int err; if ((err = amx_Allot(amx, blocksize, &amx_addr1, &phys_addr)) != AMX_ERR_NONE || ( err = amx_Allot(amx, blocksize, &amx_addr2, &phys_addr)) != AMX_ERR_NONE) { LogError(amx, err, "Ran out of memory"); return 0; } } ArraySort_s oldinfo = SortInfo; SortInfo.func = func; SortInfo.array_base = array; SortInfo.array_bsize = static_cast<cell>(blocksize); SortInfo.array_hndl = params[1]; SortInfo.data = params[3]; SortInfo.size = params[4]; SortInfo.amx = amx; SortInfo.addr1 = amx_addr1; SortInfo.addr2 = amx_addr2; qsort(array, arraysize, blocksize * sizeof(cell), blocksize > 1 ? SortArrayListExArray : SortArrayListExCell); SortInfo = oldinfo; if (blocksize > 1) { amx_Release(amx, amx_addr1); amx_Release(amx, amx_addr2); } unregisterSPForward(func); return 1; }
int Invoke::callNative(const PAWN::Native * native, ...) { if (amx_list.empty() || amx_map.find(native->name) == amx_map.end()) { return 0; } unsigned int amx_addr = amx_map[native->name], count = strlen(native->data), variables = 0; cell * params = new cell[count + 1], * physAddr[6]; params[0] = count * sizeof(cell); va_list input; va_start(input, native); for (unsigned int i = 0; i < count; ++i) { switch (native->data[i]) { case 'd': case 'i': { params[i + 1] = va_arg(input, int); } break; case 'f': { float value = (float)va_arg(input, double); params[i + 1] = amx_ftoc(value); } break; case 's': { char * string = va_arg(input, char *); amx_Allot(amx_list.front(), strlen(string) + 1, ¶ms[i + 1], &physAddr[variables++]); amx_SetString(physAddr[variables - 1], string, 0, 0, strlen(string) + 1); } break; case 'v': { va_arg(input, void *); amx_Allot(amx_list.front(), 1, ¶ms[i + 1], &physAddr[variables++]); } break; case 'p': { va_arg(input, void *); int size = va_arg(input, int); amx_Allot(amx_list.front(), size, ¶ms[++i], &physAddr[variables++]); params[i + 1] = size; } break; } } va_end(input); amx_Function_t amx_Function = (amx_Function_t)amx_addr; int value = amx_Function(amx_list.front(), params); if (variables) { variables = 0; va_start(input, native); for (unsigned int i = 0; i < count; ++i) { switch (native->data[i]) { case 's': { amx_Release(amx_list.front(), params[i + 1]); } break; case 'v': { unsigned int * value = va_arg(input, unsigned int *), * returnValue = (unsigned int *)physAddr[variables++]; * value = * returnValue; amx_Release(amx_list.front(), params[i + 1]); } break; case 'p': { char * text = va_arg(input, char *); int size = va_arg(input, int); amx_GetString(text, physAddr[variables++], 0, size); amx_Release(amx_list.front(), params[++i]); } break; default: { va_arg(input, void *); } break; } } va_end(input); } delete [] params; return value; }
cell CForward::execute(cell *params, ForwardPreparedArray *preparedArrays) { cell realParams[FORWARD_MAX_PARAMS]; cell *physAddrs[FORWARD_MAX_PARAMS]; const int STRINGEX_MAXLENGTH = 128; cell globRetVal = 0; AMXForwardList::iterator iter; for (iter = m_Funcs.begin(); iter != m_Funcs.end(); iter++) { if (iter->pPlugin->isExecutable(iter->func)) { // Get debug info AMX *amx = (*iter).pPlugin->getAMX(); Debugger *pDebugger = (Debugger *)amx->userdata[UD_DEBUGGER]; if (pDebugger) pDebugger->BeginExec(); // handle strings & arrays int i; for (i = 0; i < m_NumParams; ++i) { if (m_ParamTypes[i] == FP_STRING || m_ParamTypes[i] == FP_STRINGEX) { const char *str = reinterpret_cast<const char*>(params[i]); cell *tmp; if (!str) str = ""; amx_Allot(iter->pPlugin->getAMX(), (m_ParamTypes[i] == FP_STRING) ? strlen(str) + 1 : STRINGEX_MAXLENGTH, &realParams[i], &tmp); amx_SetStringOld(tmp, str, 0, 0); physAddrs[i] = tmp; } else if (m_ParamTypes[i] == FP_ARRAY) { cell *tmp; amx_Allot(amx, preparedArrays[params[i]].size, &realParams[i], &tmp); physAddrs[i] = tmp; if (preparedArrays[params[i]].type == Type_Cell) { memcpy(tmp, preparedArrays[params[i]].ptr, preparedArrays[params[i]].size * sizeof(cell)); } else { char *data = (char*)preparedArrays[params[i]].ptr; for (unsigned int j = 0; j < preparedArrays[params[i]].size; ++j) *tmp++ = (static_cast<cell>(*data++)) & 0xFF; } } else { realParams[i] = params[i]; } } //Push the parameters in reverse order. Weird, unfriendly part of Small 3.0! for (i = m_NumParams-1; i >= 0; i--) { amx_Push(amx, realParams[i]); } // exec cell retVal = 0; #if defined BINLOG_ENABLED g_BinLog.WriteOp(BinLog_CallPubFunc, (*iter).pPlugin->getId(), iter->func); #endif int err = amx_Exec(amx, &retVal, iter->func); // log runtime error, if any if (err != AMX_ERR_NONE) { //Did something else set an error? if (pDebugger && pDebugger->ErrorExists()) { //we don't care, something else logged the error. } else if (err != -1) { //nothing logged the error so spit it out anyway LogError(amx, err, NULL); } } amx->error = AMX_ERR_NONE; if (pDebugger) pDebugger->EndExec(); // cleanup strings & arrays for (i = 0; i < m_NumParams; ++i) { if (m_ParamTypes[i] == FP_STRING) { amx_Release(iter->pPlugin->getAMX(), realParams[i]); } else if (m_ParamTypes[i] == FP_STRINGEX) { // copy back amx_GetStringOld(reinterpret_cast<char*>(params[i]), physAddrs[i], 0); amx_Release(iter->pPlugin->getAMX(), realParams[i]); } else if (m_ParamTypes[i] == FP_ARRAY) { // copy back if (preparedArrays[params[i]].copyBack) { cell *tmp = physAddrs[i]; if (preparedArrays[params[i]].type == Type_Cell) { memcpy(preparedArrays[params[i]].ptr, tmp, preparedArrays[params[i]].size * sizeof(cell)); } else { char *data = (char*)preparedArrays[params[i]].ptr; for (unsigned int j = 0; j < preparedArrays[params[i]].size; ++j) *data++ = static_cast<char>(*tmp++ & 0xFF); } } amx_Release(iter->pPlugin->getAMX(), realParams[i]); } } // decide what to do (based on exectype and retval) switch (m_ExecType) { case ET_IGNORE: break; case ET_STOP: if (retVal > 0) return retVal; case ET_STOP2: if (retVal == 1) return 1; else if (retVal > globRetVal) globRetVal = retVal; break; case ET_CONTINUE: if (retVal > globRetVal) globRetVal = retVal; break; } } } return globRetVal; }
cell CSPForward::execute(cell *params, ForwardPreparedArray *preparedArrays) { if (isFree) return 0; const int STRINGEX_MAXLENGTH = 128; cell realParams[FORWARD_MAX_PARAMS]; cell *physAddrs[FORWARD_MAX_PARAMS]; if (!m_HasFunc || m_ToDelete) return 0; CPluginMngr::CPlugin *pPlugin = g_plugins.findPluginFast(m_Amx); if (!pPlugin->isExecutable(m_Func)) return 0; m_InExec = true; Debugger *pDebugger = (Debugger *)m_Amx->userdata[UD_DEBUGGER]; if (pDebugger) pDebugger->BeginExec(); // handle strings & arrays int i; for (i = 0; i < m_NumParams; ++i) { if (m_ParamTypes[i] == FP_STRING || m_ParamTypes[i] == FP_STRINGEX) { const char *str = reinterpret_cast<const char*>(params[i]); if (!str) str = ""; cell *tmp; amx_Allot(m_Amx, (m_ParamTypes[i] == FP_STRING) ? strlen(str) + 1 : STRINGEX_MAXLENGTH, &realParams[i], &tmp); amx_SetStringOld(tmp, str, 0, 0); physAddrs[i] = tmp; } else if (m_ParamTypes[i] == FP_ARRAY) { cell *tmp; amx_Allot(m_Amx, preparedArrays[params[i]].size, &realParams[i], &tmp); physAddrs[i] = tmp; if (preparedArrays[params[i]].type == Type_Cell) { memcpy(tmp, preparedArrays[params[i]].ptr, preparedArrays[params[i]].size * sizeof(cell)); } else { char *data = (char*)preparedArrays[params[i]].ptr; for (unsigned int j = 0; j < preparedArrays[params[i]].size; ++j) *tmp++ = (static_cast<cell>(*data++)) & 0xFF; } } else { realParams[i] = params[i]; } } for (i = m_NumParams - 1; i >= 0; i--) amx_Push(m_Amx, realParams[i]); // exec cell retVal; #if defined BINLOG_ENABLED g_BinLog.WriteOp(BinLog_CallPubFunc, pPlugin->getId(), m_Func); #endif int err = amx_Exec(m_Amx, &retVal, m_Func); if (err != AMX_ERR_NONE) { //Did something else set an error? if (pDebugger && pDebugger->ErrorExists()) { //we don't care, something else logged the error. } else if (err != -1) { //nothing logged the error so spit it out anyway LogError(m_Amx, err, NULL); } } if (pDebugger) pDebugger->EndExec(); m_Amx->error = AMX_ERR_NONE; // cleanup strings & arrays for (i = 0; i < m_NumParams; ++i) { if (m_ParamTypes[i] == FP_STRING) { amx_Release(m_Amx, realParams[i]); } else if (m_ParamTypes[i] == FP_STRINGEX) { // copy back amx_GetStringOld(reinterpret_cast<char*>(params[i]), physAddrs[i], 0); amx_Release(m_Amx, realParams[i]); } else if (m_ParamTypes[i] == FP_ARRAY) { // copy back if (preparedArrays[params[i]].copyBack) { cell *tmp = physAddrs[i]; if (preparedArrays[params[i]].type == Type_Cell) { memcpy(preparedArrays[params[i]].ptr, tmp, preparedArrays[params[i]].size * sizeof(cell)); } else { char *data = (char*)preparedArrays[params[i]].ptr; for (unsigned int j = 0; j < preparedArrays[params[i]].size; ++j) *data++ = static_cast<char>(*tmp++ & 0xFF); } } amx_Release(m_Amx, realParams[i]); } } m_InExec = false; return retVal; }