PLUGIN_EXPORT int PLUGIN_CALL AmxLoad(AMX * amx) { int num, idx; // Operate on the raw AMX file, don't use the amx_ functions to avoid issues // with the fact that we've not actually finished initialisation yet. Based // VERY heavilly on code from "amx.c" in the PAWN runtime library. AMX_HEADER * hdr = (AMX_HEADER *)amx->base; AMX_FUNCSTUB * func; num = NUMENTRIES(hdr, natives, libraries); for (idx = 0; idx != num; ++idx) { func = GETENTRY(hdr, natives, idx); if (!strcmp("SetPlayerName", GETENTRYNAME(hdr, func))) { // Intercept the call! SetPlayerName = (AMX_NATIVE)func->address; func->address = (ucell)n_SSCANF_SetPlayerName; break; } } return amx_Register(amx, sscanfNatives, -1); }
void Redirect(AMX * amx, char const * const from, ucell to, AMX_NATIVE * store) { int num, idx; // Operate on the raw AMX file, don't use the amx_ functions to avoid issues // with the fact that we've not actually finished initialisation yet. Based // VERY heavilly on code from "amx.c" in the PAWN runtime library. AMX_HEADER * hdr = (AMX_HEADER *)amx->base; AMX_FUNCSTUB * func; num = NUMENTRIES(hdr, natives, libraries); //logprintf("Redirect 1"); for (idx = 0; idx != num; ++idx) { func = GETENTRY(hdr, natives, idx); //logprintf("Redirect 2 \"%s\" \"%s\"", from, GETENTRYNAME(hdr, func)); if (!strcmp(from, GETENTRYNAME(hdr, func))) { //logprintf("Redirect 3"); // Intercept the call! if (store) { *store = (AMX_NATIVE)func->address; } func->address = to; break; } } }
int loadprogram(const char *filename, char *error, size_t error_size) { FIL *file = &amx_file; FRESULT status = f_open(file, filename, FA_READ); if (status != FR_OK) { snprintf(error, error_size, "Could not open file %s: %d", filename, status); return AMX_ERR_NOTFOUND; } /* Read file header */ memset(&amx, 0, sizeof(amx)); AMX_HEADER hdr; UINT read_count; f_read(file, &hdr, sizeof hdr, &read_count); if (read_count != sizeof hdr || hdr.magic != AMX_MAGIC) return AMX_ERR_FORMAT; if (hdr.flags & AMX_FLAG_OVERLAY) { // Read the header f_lseek(file, 0); f_read(file, vm_data, hdr.cod, &read_count); // Read the data block f_lseek(file, hdr.dat); unsigned dat_size = hdr.hea - hdr.dat; f_read(file, vm_data + hdr.cod, dat_size, &read_count); if (read_count != dat_size) return AMX_ERR_FORMAT; unsigned static_size = (hdr.stp - hdr.dat) + hdr.cod; amx_poolinit(vm_data + static_size, sizeof(vm_data) - static_size); amx.base = vm_data; amx.data = vm_data + hdr.cod; overlay_init(&amx, amx_filename, &amx_file); } else { if (hdr.stp > sizeof(vm_data)) return AMX_ERR_MEMORY; /* Read the actual file, including the header (again) */ f_lseek(file, 0); f_read(file, vm_data, hdr.size, &read_count); if (read_count != hdr.size) return AMX_ERR_FORMAT; } AMXERRORS(amx_Init(&amx, vm_data)); amxinit_display(&amx); amx_CoreInit(&amx); amxinit_string(&amx); amxinit_fixed(&amx); amxinit_wavein(&amx); amxinit_waveout(&amx); amxinit_menu(&amx); amxinit_file(&amx); amxinit_buttons(&amx); amxinit_fourier(&amx); amxinit_time(&amx); amxinit_device(&amx); amxinit_fpga(&amx); // Check that everything has been registered int regstat = amx_Register(&amx, NULL, -1); if (regstat != 0) { // Find out what is missing for (int i = 0; i < NUMENTRIES((AMX_HEADER*)amx.base,natives,libraries); i++) { AMX_FUNCSTUB *func = GETENTRY((AMX_HEADER*)amx.base,natives,i); if (func->address == 0) { snprintf(error, error_size, "Native function not found: %s", GETENTRYNAME((AMX_HEADER*)amx.base,func)); return AMX_ERR_NOTFOUND; } } snprintf(error, error_size, "Error registering native functions"); return regstat; } return 0; }