/* ** $Id: lapi.c,v 2.244 2014/12/26 14:43:45 roberto Exp $ ** Lua API ** See Copyright Notice in lua.h */ #define lapi_c #define LUA_CORE #include "lprefix.h" #include #include #include "lua.h" #include "lapi.h" #include "ldebug.h" #include "ldo.h" #include "lfunc.h" #include "lgc.h" #include "lmem.h" #include "lobject.h" #include "lstate.h" #include "lstring.h" #include "ltable.h" #include "ltm.h" #include "lundump.h" #include "lvm.h" const char lua_ident[] = "$LuaVersion: " LUA_COPYRIGHT " $" "$LuaAuthors: " LUA_AUTHORS " $"; /* value at a non-valid index */ #define NONVALIDVALUE cast(TValue *, luaO_nilobject) /* corresponding test */ #define isvalid(o) ((o) != luaO_nilobject) /* test for pseudo index */ #define ispseudo(i) ((i) <= LUA_REGISTRYINDEX) /* test for upvalue */ #define isupvalue(i) ((i) < LUA_REGISTRYINDEX) /* test for valid but not pseudo index */ #define isstackindex(i, o) (isvalid(o) && !ispseudo(i)) #define api_checkvalidindex(o) api_check(isvalid(o), "invalid index") #define api_checkstackindex(i, o) \ api_check(isstackindex(i, o), "index not in the stack") static TValue *index2addr (lua_State *L, int idx) { CallInfo *ci = L->ci; if (idx > 0) { TValue *o = ci->func + idx; api_check(idx <= ci->top - (ci->func + 1), "unacceptable index"); if (o >= L->top) return NONVALIDVALUE; else return o; } else if (!ispseudo(idx)) { /* negative index */ api_check(idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index"); return L->top + idx; } else if (idx == LUA_REGISTRYINDEX) return &G(L)->l_registry; else { /* upvalues */ idx = LUA_REGISTRYINDEX - idx; api_check(idx <= MAXUPVAL + 1, "upvalue index too large"); if (ttislcf(ci->func)) /* light C function? */ return NONVALIDVALUE; /* it has no upvalues */ else { CClosure *func = clCvalue(ci->func); return (idx <= func->nupvalues) ? &func->upvalue[idx-1] : NONVALIDVALUE; } } } /* ** to be called by 'lua_checkstack' in protected mode, to grow stack ** capturing memory errors */ static void growstack (lua_State *L, void *ud) { int size = *(int *)ud; luaD_growstack(L, size); } LUA_API int lua_checkstack (lua_State *L, int n) { int res; CallInfo *ci = L->ci; lua_lock(L); api_check(n >= 0, "negative 'n'"); if (L->stack_last - L->top > n) /* stack large enough? */ res = 1; /* yes; check is OK */ else { /* no; need to grow stack */ int inuse = cast_int(L->top - L->stack) + EXTRA_STACK; if (inuse > LUAI_MAXSTACK - n) /* can grow without overflow? */ res = 0; /* no */ else /* try to grow stack */ res = (luaD_rawrunprotected(L, &growstack, &n) == LUA_OK); } if (res && ci->top < L->top + n) ci->top = L->top + n; /* adjust frame top */ lua_unlock(L); return res; } LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { int i; if (from == to) return; lua_lock(to); api_checknelems(from, n); api_check(G(from) == G(to), "moving among independent states"); api_check(to->ci->top - to->top >= n, "not enough elements to move"); from->top -= n; for (i = 0; i < n; i++) { setobj2s(to, to->top++, from->top + i); } lua_unlock(to); } LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { lua_CFunction old; lua_lock(L); old = G(L)->panic; G(L)->panic = panicf; lua_unlock(L); return old; } LUA_API const lua_Number *lua_version (lua_State *L) { static const lua_Number version = LUA_VERSION_NUM; if (L == NULL) return &version; else return G(L)->version; } /* ** basic stack manipulation */ /* ** convert an acceptable stack index into an absolute index */ LUA_API int lua_absindex (lua_State *L, int idx) { return (idx > 0 || ispseudo(idx)) ? idx : cast_int(L->top - L->ci->func + idx); } LUA_API int lua_gettop (lua_State *L) { return cast_int(L->top - (L->ci->func + 1)); } LUA_API void lua_settop (lua_State *L, int idx) { StkId func = L->ci->func; lua_lock(L); if (idx >= 0) { api_check(idx <= L->stack_last - (func + 1), "new top too large"); while (L->top < (func + 1) + idx) setnilvalue(L->top++); L->top = (func + 1) + idx; } else { api_check(-(idx+1) <= (L->top - (func + 1)), "invalid new top"); L->top += idx+1; /* 'subtract' index (index is negative) */ } lua_unlock(L); } /* ** Reverse the stack segment from 'from' to 'to' ** (auxiliary to 'lua_rotate') */ static void reverse (lua_State *L, StkId from, StkId to) { for (; from < to; from++, to--) { TValue temp; setobj(L, &temp, from); setobjs2s(L, from, to); setobj2s(L, to, &temp); } } /* ** Let x = AB, where A is a prefix of length 'n'. Then, ** rotate x n == BA. But BA == (A^r . B^r)^r. */ LUA_API void lua_rotate (lua_State *L, int idx, int n) { StkId p, t, m; lua_lock(L); t = L->top - 1; /* end of stack segment being rotated */ p = index2addr(L, idx); /* start of segment */ api_checkstackindex(idx, p); api_check((n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'"); m = (n >= 0 ? t - n : p - n - 1); /* end of prefix */ reverse(L, p, m); /* reverse the prefix with length 'n' */ reverse(L, m + 1, t); /* reverse the suffix */ reverse(L, p, t); /* reverse the entire segment */ lua_unlock(L); } LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) { TValue *fr, *to; lua_lock(L); fr = index2addr(L, fromidx); to = index2addr(L, toidx); api_checkvalidindex(to); setobj(L, to, fr); if (isupvalue(toidx)) /* function upvalue? */ luaC_barrier(L, clCvalue(L->ci->func), fr); /* LUA_REGISTRYINDEX does not need gc barrier (collector revisits it before finishing collection) */ lua_unlock(L); } LUA_API void lua_pushvalue (lua_State *L, int idx) { lua_lock(L); setobj2s(L, L->top, index2addr(L, idx)); api_incr_top(L); lua_unlock(L); } /* ** access functions (stack -> C) */ LUA_API int lua_type (lua_State *L, int idx) { StkId o = index2addr(L, idx); return (isvalid(o) ? ttnov(o) : LUA_TNONE); } LUA_API const char *lua_typename (lua_State *L, int t) { UNUSED(L); api_check(LUA_TNONE <= t && t < LUA_NUMTAGS, "invalid tag"); return ttypename(t); } LUA_API int lua_iscfunction (lua_State *L, int idx) { StkId o = index2addr(L, idx); return (ttislcf(o) || (ttisCclosure(o))); } LUA_API int lua_isinteger (lua_State *L, int idx) { StkId o = index2addr(L, idx); return ttisinteger(o); } LUA_API int lua_isnumber (lua_State *L, int idx) { lua_Number n; const TValue *o = index2addr(L, idx); return tonumber(o, &n); } LUA_API int lua_isstring (lua_State *L, int idx) { const TValue *o = index2addr(L, idx); return (ttisstring(o) || cvt2str(o)); } LUA_API int lua_isuserdata (lua_State *L, int idx) { const TValue *o = index2addr(L, idx); return (ttisfulluserdata(o) || ttislightuserdata(o)); } LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { StkId o1 = index2addr(L, index1); StkId o2 = index2addr(L, index2); return (isvalid(o1) && isvalid(o2)) ? luaV_rawequalobj(o1, o2) : 0; } LUA_API void lua_arith (lua_State *L, int op) { lua_lock(L); if (op != LUA_OPUNM && op != LUA_OPBNOT) api_checknelems(L, 2); /* all other operations expect two operands */ else { /* for unary operations, add fake 2nd operand */ api_checknelems(L, 1); setobjs2s(L, L->top, L->top - 1); L->top++; } /* first operand at top - 2, second at top - 1; result go to top - 2 */ luaO_arith(L, op, L->top - 2, L->top - 1, L->top - 2); L->top--; /* remove second operand */ lua_unlock(L); } LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) { StkId o1, o2; int i = 0; lua_lock(L); /* may call tag method */ o1 = index2addr(L, index1); o2 = index2addr(L, index2); if (isvalid(o1) && isvalid(o2)) { switch (op) { case LUA_OPEQ: i = luaV_equalobj(L, o1, o2); break; case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break; case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break; default: api_check(0, "invalid option"); } } lua_unlock(L); return i; } LUA_API size_t lua_stringtonumber (lua_State *L, const char *s) { size_t sz = luaO_str2num(s, L->top); if (sz != 0) api_incr_top(L); return sz; } LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *pisnum) { lua_Number n; const TValue *o = index2addr(L, idx); int isnum = tonumber(o, &n); if (!isnum) n = 0; /* call to 'tonumber' may change 'n' even if it fails */ if (pisnum) *pisnum = isnum; return n; } LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *pisnum) { lua_Integer res; const TValue *o = index2addr(L, idx); int isnum = tointeger(o, &res); if (!isnum) res = 0; /* call to 'tointeger' may change 'n' even if it fails */ if (pisnum) *pisnum = isnum; return res; } LUA_API int lua_toboolean (lua_State *L, int idx) { const TValue *o = index2addr(L, idx); return !l_isfalse(o); } LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { StkId o = index2addr(L, idx); if (!ttisstring(o)) { if (!cvt2str(o)) { /* not convertible? */ if (len != NULL) *len = 0; return NULL; } lua_lock(L); /* 'luaO_tostring' may create a new string */ luaC_checkGC(L); o = index2addr(L, idx); /* previous call may reallocate the stack */ luaO_tostring(L, o); lua_unlock(L); } if (len != NULL) *len = tsvalue(o)->len; return svalue(o); } LUA_API size_t lua_rawlen (lua_State *L, int idx) { StkId o = index2addr(L, idx); switch (ttnov(o)) { case LUA_TSTRING: return tsvalue(o)->len; case LUA_TUSERDATA: return uvalue(o)->len; case LUA_TTABLE: return luaH_getn(hvalue(o)); default: return 0; } } LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { StkId o = index2addr(L, idx); if (ttislcf(o)) return fvalue(o); else if (ttisCclosure(o)) return clCvalue(o)->f; else return NULL; /* not a C function */ } LUA_API void *lua_touserdata (lua_State *L, int idx) { StkId o = index2addr(L, idx); switch (ttnov(o)) { case LUA_TUSERDATA: return getudatamem(uvalue(o)); case LUA_TLIGHTUSERDATA: return pvalue(o); default: return NULL; } } LUA_API lua_State *lua_tothread (lua_State *L, int idx) { StkId o = index2addr(L, idx); return (!ttisthread(o)) ? NULL : thvalue(o); } LUA_API const void *lua_topointer (lua_State *L, int idx) { StkId o = index2addr(L, idx); switch (ttype(o)) { case LUA_TTABLE: return hvalue(o); case LUA_TLCL: return clLvalue(o); case LUA_TCCL: return clCvalue(o); case LUA_TLCF: return cast(void *, cast(size_t, fvalue(o))); case LUA_TTHREAD: return thvalue(o); case LUA_TUSERDATA: case LUA_TLIGHTUSERDATA: return lua_touserdata(L, idx); default: return NULL; } } /* ** push functions (C -> stack) */ LUA_API void lua_pushnil (lua_State *L) { lua_lock(L); setnilvalue(L->top); api_incr_top(L); lua_unlock(L); } LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { lua_lock(L); setfltvalue(L->top, n); api_incr_top(L); lua_unlock(L); } LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { lua_lock(L); setivalue(L->top, n); api_incr_top(L); lua_unlock(L); } LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) { TString *ts; lua_lock(L); luaC_checkGC(L); ts = luaS_newlstr(L, s, len); setsvalue2s(L, L->top, ts); api_incr_top(L); lua_unlock(L); return getstr(ts); } LUA_API const char *lua_pushstring (lua_State *L, const char *s) { if (s == NULL) { lua_pushnil(L); return NULL; } else { TString *ts; lua_lock(L); luaC_checkGC(L); ts = luaS_new(L, s); setsvalue2s(L, L->top, ts); api_incr_top(L); lua_unlock(L); return getstr(ts); } } LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt, va_list argp) { const char *ret; lua_lock(L); luaC_checkGC(L); ret = luaO_pushvfstring(L, fmt, argp); lua_unlock(L); return ret; } LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { const char *ret; va_list argp; lua_lock(L); luaC_checkGC(L); va_start(argp, fmt); ret = luaO_pushvfstring(L, fmt, argp); va_end(argp); lua_unlock(L); return ret; } LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { lua_lock(L); if (n == 0) { setfvalue(L->top, fn); } else { CClosure *cl; api_checknelems(L, n); api_check(n <= MAXUPVAL, "upvalue index too large"); luaC_checkGC(L); cl = luaF_newCclosure(L, n); cl->f = fn; L->top -= n; while (n--) { setobj2n(L, &cl->upvalue[n], L->top + n); /* does not need barrier because closure is white */ } setclCvalue(L, L->top, cl); } api_incr_top(L); lua_unlock(L); } LUA_API void lua_pushboolean (lua_State *L, int b) { lua_lock(L); setbvalue(L->top, (b != 0)); /* ensure that true is 1 */ api_incr_top(L); lua_unlock(L); } LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { lua_lock(L); setpvalue(L->top, p); api_incr_top(L); lua_unlock(L); } LUA_API int lua_pushthread (lua_State *L) { lua_lock(L); setthvalue(L, L->top, L); api_incr_top(L); lua_unlock(L); return (G(L)->mainthread == L); } /* ** get functions (Lua -> stack) */ LUA_API int lua_getglobal (lua_State *L, const char *name) { Table *reg = hvalue(&G(L)->l_registry); const TValue *gt; /* global table */ lua_lock(L); gt = luaH_getint(reg, LUA_RIDX_GLOBALS); setsvalue2s(L, L->top++, luaS_new(L, name)); luaV_gettable(L, gt, L->top - 1, L->top - 1); lua_unlock(L); return ttnov(L->top - 1); } LUA_API int lua_gettable (lua_State *L, int idx) { StkId t; lua_lock(L); t = index2addr(L, idx); luaV_gettable(L, t, L->top - 1, L->top - 1); lua_unlock(L); return ttnov(L->top - 1); } LUA_API int lua_getfield (lua_State *L, int idx, const char *k) { StkId t; lua_lock(L); t = index2addr(L, idx); setsvalue2s(L, L->top, luaS_new(L, k)); api_incr_top(L); luaV_gettable(L, t, L->top - 1, L->top - 1); lua_unlock(L); return ttnov(L->top - 1); } LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) { StkId t; lua_lock(L); t = index2addr(L, idx); setivalue(L->top, n); api_incr_top(L); luaV_gettable(L, t, L->top - 1, L->top - 1); lua_unlock(L); return ttnov(L->top - 1); } LUA_API int lua_rawget (lua_State *L, int idx) { StkId t; lua_lock(L); t = index2addr(L, idx); api_check(ttistable(t), "table expected"); setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1)); lua_unlock(L); return ttnov(L->top - 1); } LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) { StkId t; lua_lock(L); t = index2addr(L, idx); api_check(ttistable(t), "table expected"); setobj2s(L, L->top, luaH_getint(hvalue(t), n)); api_incr_top(L); lua_unlock(L); return ttnov(L->top - 1); } LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) { StkId t; TValue k; lua_lock(L); t = index2addr(L, idx); api_check(ttistable(t), "table expected"); setpvalue(&k, cast(void *, p)); setobj2s(L, L->top, luaH_get(hvalue(t), &k)); api_incr_top(L); lua_unlock(L); return ttnov(L->top - 1); } LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { Table *t; lua_lock(L); luaC_checkGC(L); t = luaH_new(L); sethvalue(L, L->top, t); api_incr_top(L); if (narray > 0 || nrec > 0) luaH_resize(L, t, narray, nrec); lua_unlock(L); } LUA_API int lua_getmetatable (lua_State *L, int objindex) { const TValue *obj; Table *mt; int res = 0; lua_lock(L); obj = index2addr(L, objindex); switch (ttnov(obj)) { case LUA_TTABLE: mt = hvalue(obj)->metatable; break; case LUA_TUSERDATA: mt = uvalue(obj)->metatable; break; default: mt = G(L)->mt[ttnov(obj)]; break; } if (mt != NULL) { sethvalue(L, L->top, mt); api_incr_top(L); res = 1; } lua_unlock(L); return res; } LUA_API int lua_getuservalue (lua_State *L, int idx) { StkId o; lua_lock(L); o = index2addr(L, idx); api_check(ttisfulluserdata(o), "full userdata expected"); getuservalue(L, uvalue(o), L->top); api_incr_top(L); lua_unlock(L); return ttnov(L->top - 1); } /* ** set functions (stack -> Lua) */ LUA_API void lua_setglobal (lua_State *L, const char *name) { Table *reg = hvalue(&G(L)->l_registry); const TValue *gt; /* global table */ lua_lock(L); api_checknelems(L, 1); gt = luaH_getint(reg, LUA_RIDX_GLOBALS); setsvalue2s(L, L->top++, luaS_new(L, name)); luaV_settable(L, gt, L->top - 1, L->top - 2); L->top -= 2; /* pop value and key */ lua_unlock(L); } LUA_API void lua_settable (lua_State *L, int idx) { StkId t; lua_lock(L); api_checknelems(L, 2); t = index2addr(L, idx); luaV_settable(L, t, L->top - 2, L->top - 1); L->top -= 2; /* pop index and value */ lua_unlock(L); } LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { StkId t; lua_lock(L); api_checknelems(L, 1); t = index2addr(L, idx); setsvalue2s(L, L->top++, luaS_new(L, k)); luaV_settable(L, t, L->top - 1, L->top - 2); L->top -= 2; /* pop value and key */ lua_unlock(L); } LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) { StkId t; lua_lock(L); api_checknelems(L, 1); t = index2addr(L, idx); setivalue(L->top++, n); luaV_settable(L, t, L->top - 1, L->top - 2); L->top -= 2; /* pop value and key */ lua_unlock(L); } LUA_API void lua_rawset (lua_State *L, int idx) { StkId o; Table *t; lua_lock(L); api_checknelems(L, 2); o = index2addr(L, idx); api_check(ttistable(o), "table expected"); t = hvalue(o); setobj2t(L, luaH_set(L, t, L->top-2), L->top-1); invalidateTMcache(t); luaC_barrierback(L, t, L->top-1); L->top -= 2; lua_unlock(L); } LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) { StkId o; Table *t; lua_lock(L); api_checknelems(L, 1); o = index2addr(L, idx); api_check(ttistable(o), "table expected"); t = hvalue(o); luaH_setint(L, t, n, L->top - 1); luaC_barrierback(L, t, L->top-1); L->top--; lua_unlock(L); } LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) { StkId o; Table *t; TValue k; lua_lock(L); api_checknelems(L, 1); o = index2addr(L, idx); api_check(ttistable(o), "table expected"); t = hvalue(o); setpvalue(&k, cast(void *, p)); setobj2t(L, luaH_set(L, t, &k), L->top - 1); luaC_barrierback(L, t, L->top - 1); L->top--; lua_unlock(L); } LUA_API int lua_setmetatable (lua_State *L, int objindex) { TValue *obj; Table *mt; lua_lock(L); api_checknelems(L, 1); obj = index2addr(L, objindex); if (ttisnil(L->top - 1)) mt = NULL; else { api_check(ttistable(L->top - 1), "table expected"); mt = hvalue(L->top - 1); } switch (ttnov(obj)) { case LUA_TTABLE: { hvalue(obj)->metatable = mt; if (mt) { luaC_objbarrier(L, gcvalue(obj), mt); luaC_checkfinalizer(L, gcvalue(obj), mt); } break; } case LUA_TUSERDATA: { uvalue(obj)->metatable = mt; if (mt) { luaC_objbarrier(L, uvalue(obj), mt); luaC_checkfinalizer(L, gcvalue(obj), mt); } break; } default: { G(L)->mt[ttnov(obj)] = mt; break; } } L->top--; lua_unlock(L); return 1; } LUA_API void lua_setuservalue (lua_State *L, int idx) { StkId o; lua_lock(L); api_checknelems(L, 1); o = index2addr(L, idx); api_check(ttisfulluserdata(o), "full userdata expected"); setuservalue(L, uvalue(o), L->top - 1); luaC_barrier(L, gcvalue(o), L->top - 1); L->top--; lua_unlock(L); } /* ** 'load' and 'call' functions (run Lua code) */ #define checkresults(L,na,nr) \ api_check((nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \ "results from function overflow current stack size") LUA_API void lua_callk (lua_State *L, int nargs, int nresults, lua_KContext ctx, lua_KFunction k) { StkId func; lua_lock(L); api_check(k == NULL || !isLua(L->ci), "cannot use continuations inside hooks"); api_checknelems(L, nargs+1); api_check(L->status == LUA_OK, "cannot do calls on non-normal thread"); checkresults(L, nargs, nresults); func = L->top - (nargs+1); if (k != NULL && L->nny == 0) { /* need to prepare continuation? */ L->ci->u.c.k = k; /* save continuation */ L->ci->u.c.ctx = ctx; /* save context */ luaD_call(L, func, nresults, 1); /* do the call */ } else /* no continuation or no yieldable */ luaD_call(L, func, nresults, 0); /* just do the call */ adjustresults(L, nresults); lua_unlock(L); } /* ** Execute a protected call. */ struct CallS { /* data to 'f_call' */ StkId func; int nresults; }; static void f_call (lua_State *L, void *ud) { struct CallS *c = cast(struct CallS *, ud); luaD_call(L, c->func, c->nresults, 0); } LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, lua_KContext ctx, lua_KFunction k) { struct CallS c; int status; ptrdiff_t func; lua_lock(L); api_check(k == NULL || !isLua(L->ci), "cannot use continuations inside hooks"); api_checknelems(L, nargs+1); api_check(L->status == LUA_OK, "cannot do calls on non-normal thread"); checkresults(L, nargs, nresults); if (errfunc == 0) func = 0; else { StkId o = index2addr(L, errfunc); api_checkstackindex(errfunc, o); func = savestack(L, o); } c.func = L->top - (nargs+1); /* function to be called */ if (k == NULL || L->nny > 0) { /* no continuation or no yieldable? */ c.nresults = nresults; /* do a 'conventional' protected call */ status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); } else { /* prepare continuation (call is already protected by 'resume') */ CallInfo *ci = L->ci; ci->u.c.k = k; /* save continuation */ ci->u.c.ctx = ctx; /* save context */ /* save information for error recovery */ ci->extra = savestack(L, c.func); ci->u.c.old_errfunc = L->errfunc; L->errfunc = func; setoah(ci->callstatus, L->allowhook); /* save value of 'allowhook' */ ci->callstatus |= CIST_YPCALL; /* function can do error recovery */ luaD_call(L, c.func, nresults, 1); /* do the call */ ci->callstatus &= ~CIST_YPCALL; L->errfunc = ci->u.c.old_errfunc; status = LUA_OK; /* if it is here, there were no errors */ } adjustresults(L, nresults); lua_unlock(L); return status; } LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, const char *chunkname, const char *mode) { ZIO z; int status; lua_lock(L); if (!chunkname) chunkname = "?"; luaZ_init(L, &z, reader, data); status = luaD_protectedparser(L, &z, chunkname, mode); if (status == LUA_OK) { /* no errors? */ LClosure *f = clLvalue(L->top - 1); /* get newly created function */ if (f->nupvalues >= 1) { /* does it have an upvalue? */ /* get global table from registry */ Table *reg = hvalue(&G(L)->l_registry); const TValue *gt = luaH_getint(reg, LUA_RIDX_GLOBALS); /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ setobj(L, f->upvals[0]->v, gt); luaC_upvalbarrier(L, f->upvals[0]); } } lua_unlock(L); return status; } LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) { int status; TValue *o; lua_lock(L); api_checknelems(L, 1); o = L->top - 1; if (isLfunction(o)) status = luaU_dump(L, getproto(o), writer, data, strip); else status = 1; lua_unlock(L); return status; } LUA_API int lua_status (lua_State *L) { return L->status; } /* ** Garbage-collection function */ LUA_API int lua_gc (lua_State *L, int what, int data) { int res = 0; global_State *g; lua_lock(L); g = G(L); switch (what) { case LUA_GCSTOP: { g->gcrunning = 0; break; } case LUA_GCRESTART: { luaE_setdebt(g, 0); g->gcrunning = 1; break; } case LUA_GCCOLLECT: { luaC_fullgc(L, 0); break; } case LUA_GCCOUNT: { /* GC values are expressed in Kbytes: #bytes/2^10 */ res = cast_int(gettotalbytes(g) >> 10); break; } case LUA_GCCOUNTB: { res = cast_int(gettotalbytes(g) & 0x3ff); break; } case LUA_GCSTEP: { l_mem debt = 1; /* =1 to signal that it did an actual step */ int oldrunning = g->gcrunning; g->gcrunning = 1; /* allow GC to run */ if (data == 0) { luaE_setdebt(g, -GCSTEPSIZE); /* to do a "small" step */ luaC_step(L); } else { /* add 'data' to total debt */ debt = cast(l_mem, data) * 1024 + g->GCdebt; luaE_setdebt(g, debt); luaC_checkGC(L); } g->gcrunning = oldrunning; /* restore previous state */ if (debt > 0 && g->gcstate == GCSpause) /* end of cycle? */ res = 1; /* signal it */ break; } case LUA_GCSETPAUSE: { res = g->gcpause; g->gcpause = data; break; } case LUA_GCSETSTEPMUL: { res = g->gcstepmul; if (data < 40) data = 40; /* avoid ridiculous low values (and 0) */ g->gcstepmul = data; break; } case LUA_GCISRUNNING: { res = g->gcrunning; break; } default: res = -1; /* invalid option */ } lua_unlock(L); return res; } /* ** miscellaneous functions */ LUA_API int lua_error (lua_State *L) { lua_lock(L); api_checknelems(L, 1); luaG_errormsg(L); /* code unreachable; will unlock when control actually leaves the kernel */ return 0; /* to avoid warnings */ } LUA_API int lua_next (lua_State *L, int idx) { StkId t; int more; lua_lock(L); t = index2addr(L, idx); api_check(ttistable(t), "table expected"); more = luaH_next(L, hvalue(t), L->top - 1); if (more) { api_incr_top(L); } else /* no more elements */ L->top -= 1; /* remove key */ lua_unlock(L); return more; } LUA_API void lua_concat (lua_State *L, int n) { lua_lock(L); api_checknelems(L, n); if (n >= 2) { luaC_checkGC(L); luaV_concat(L, n); } else if (n == 0) { /* push empty string */ setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); api_incr_top(L); } /* else n == 1; nothing to do */ lua_unlock(L); } LUA_API void lua_len (lua_State *L, int idx) { StkId t; lua_lock(L); t = index2addr(L, idx); luaV_objlen(L, L->top, t); api_incr_top(L); lua_unlock(L); } LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) { lua_Alloc f; lua_lock(L); if (ud) *ud = G(L)->ud; f = G(L)->frealloc; lua_unlock(L); return f; } LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) { lua_lock(L); G(L)->ud = ud; G(L)->frealloc = f; lua_unlock(L); } LUA_API void *lua_newuserdata (lua_State *L, size_t size) { Udata *u; lua_lock(L); luaC_checkGC(L); u = luaS_newudata(L, size); setuvalue(L, L->top, u); api_incr_top(L); lua_unlock(L); return getudatamem(u); } static const char *aux_upvalue (StkId fi, int n, TValue **val, CClosure **owner, UpVal **uv) { switch (ttype(fi)) { case LUA_TCCL: { /* C closure */ CClosure *f = clCvalue(fi); if (!(1 <= n && n <= f->nupvalues)) return NULL; *val = &f->upvalue[n-1]; if (owner) *owner = f; return ""; } case LUA_TLCL: { /* Lua closure */ LClosure *f = clLvalue(fi); TString *name; Proto *p = f->p; if (!(1 <= n && n <= p->sizeupvalues)) return NULL; *val = f->upvals[n-1]->v; if (uv) *uv = f->upvals[n - 1]; name = p->upvalues[n-1].name; return (name == NULL) ? "(*no name)" : getstr(name); } default: return NULL; /* not a closure */ } } LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { const char *name; TValue *val = NULL; /* to avoid warnings */ lua_lock(L); name = aux_upvalue(index2addr(L, funcindex), n, &val, NULL, NULL); if (name) { setobj2s(L, L->top, val); api_incr_top(L); } lua_unlock(L); return name; } LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { const char *name; TValue *val = NULL; /* to avoid warnings */ CClosure *owner = NULL; UpVal *uv = NULL; StkId fi; lua_lock(L); fi = index2addr(L, funcindex); api_checknelems(L, 1); name = aux_upvalue(fi, n, &val, &owner, &uv); if (name) { L->top--; setobj(L, val, L->top); if (owner) { luaC_barrier(L, owner, L->top); } else if (uv) { luaC_upvalbarrier(L, uv); } } lua_unlock(L); return name; } static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) { LClosure *f; StkId fi = index2addr(L, fidx); api_check(ttisLclosure(fi), "Lua function expected"); f = clLvalue(fi); api_check((1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index"); if (pf) *pf = f; return &f->upvals[n - 1]; /* get its upvalue pointer */ } LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) { StkId fi = index2addr(L, fidx); switch (ttype(fi)) { case LUA_TLCL: { /* lua closure */ return *getupvalref(L, fidx, n, NULL); } case LUA_TCCL: { /* C closure */ CClosure *f = clCvalue(fi); api_check(1 <= n && n <= f->nupvalues, "invalid upvalue index"); return &f->upvalue[n - 1]; } default: { api_check(0, "closure expected"); return NULL; } } } LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1, int fidx2, int n2) { LClosure *f1; UpVal **up1 = getupvalref(L, fidx1, n1, &f1); UpVal **up2 = getupvalref(L, fidx2, n2, NULL); luaC_upvdeccount(L, *up1); *up1 = *up2; (*up1)->refcount++; if (upisopen(*up1)) (*up1)->u.open.touched = 1; luaC_upvalbarrier(L, *up1); } class="cp">#define REG_BLTCPTH (0x048/2) /* W A Blitter pointer to source C (high 3 bits) */ #define REG_BLTCPTL (0x04A/2) /* W A Blitter pointer to source C (low 15 bits) */ #define REG_BLTBPTH (0x04C/2) /* W A Blitter pointer to source B (high 3 bits) */ #define REG_BLTBPTL (0x04E/2) /* W A Blitter pointer to source B (low 15 bits) */ #define REG_BLTAPTH (0x050/2) /* W A Blitter pointer to source A (high 3 bits) */ #define REG_BLTAPTL (0x052/2) /* W A Blitter pointer to source A (low 15 bits) */ #define REG_BLTDPTH (0x054/2) /* W A Blitter pointer to destination D (high 3 bits) */ #define REG_BLTDPTL (0x056/2) /* W A Blitter pointer to destination D (low 15 bits) */ #define REG_BLTSIZE (0x058/2) /* W A Blitter start and size (window width, height) */ #define REG_BLTCON0L (0x05A/2) /* W A Blitter control 0, lower 8 bits (minterms) */ #define REG_BLTSIZV (0x05C/2) /* W A Blitter V size (for 15 bit vertical size) (ECS) */ #define REG_BLTSIZH (0x05E/2) /* W A Blitter H size and start (for 11 bit H size) (ECS) */ #define REG_BLTCMOD (0x060/2) /* W A Blitter modulo for source C */ #define REG_BLTBMOD (0x062/2) /* W A Blitter modulo for source B */ #define REG_BLTAMOD (0x064/2) /* W A Blitter modulo for source A */ #define REG_BLTDMOD (0x066/2) /* W A Blitter modulo for destination D */ #define REG_BLTCDAT (0x070/2) /* W A Blitter source C data register */ #define REG_BLTBDAT (0x072/2) /* W A Blitter source B data reglster */ #define REG_BLTADAT (0x074/2) /* W A Blitter source A data register */ #define REG_DENISEID (0x07C/2) /* R D Denise ID: OCS = 0xFF, ECS = 0xFC, AGA = 0xF8 */ #define REG_DSRSYNC (0x07E/2) /* W P Disk sync pattern register for disk read */ #define REG_COP1LCH (0x080/2) /* W A Coprocessor first location register (high 3 bits) */ #define REG_COP1LCL (0x082/2) /* W A Coprocessor first location register (low 15 bits) */ #define REG_COP2LCH (0x084/2) /* W A Coprocessor second location register (high 3 bits) */ #define REG_COP2LCL (0x086/2) /* W A Coprocessor second location register (low 15 bits) */ #define REG_COPJMP1 (0x088/2) /* S A Coprocessor restart at first location */ #define REG_COPJMP2 (0x08A/2) /* S A Coprocessor restart at second location */ #define REG_COPINS (0x08C/2) /* W A Coprocessor instruction fetch identify */ #define REG_DIWSTRT (0x08E/2) /* W A Display window start (upper left vert-horiz position) */ #define REG_DIWSTOP (0x090/2) /* W A Display window stop (lower right vert.-horiz. position) */ #define REG_DDFSTRT (0x092/2) /* W A Display bit plane data fetch start (horiz. position) */ #define REG_DDFSTOP (0x094/2) /* W A Display bit plane data fetch stop (horiz. position) */ #define REG_DMACON (0x096/2) /* W A D P DMA control write (clear or set) */ #define REG_CLXCON (0x098/2) /* W D Collision control */ #define REG_INTENA (0x09A/2) /* W P Interrupt enable bits (clear or set bits) */ #define REG_INTREQ (0x09C/2) /* W P Interrupt request bits (clear or set bits) */ #define REG_ADKCON (0x09E/2) /* W P Audio, disk, UART control */ #define REG_AUD0LCH (0x0A0/2) /* W A Audio channel 0 location (high 3 bits) */ #define REG_AUD0LCL (0x0A2/2) /* W A Audio channel 0 location (low 15 bits) */ #define REG_AUD0LEN (0x0A4/2) /* W P Audio channel 0 length */ #define REG_AUD0PER (0x0A6/2) /* W P Audio channel 0 period */ #define REG_AUD0VOL (0x0A8/2) /* W P Audio channel 0 volume */ #define REG_AUD0DAT (0x0AA/2) /* W P Audio channel 0 data */ #define REG_AUD1LCH (0x0B0/2) /* W A Audio channel 1 location (high 3 bits) */ #define REG_AUD1LCL (0x0B2/2) /* W A Audio channel 1 location (low 15 bits) */ #define REG_AUD1LEN (0x0B4/2) /* W P Audio channel 1 length */ #define REG_AUD1PER (0x0B6/2) /* W P Audio channel 1 period */ #define REG_AUD1VOL (0x0B8/2) /* W P Audio channel 1 volume */ #define REG_AUD1DAT (0x0BA/2) /* W P Audio channel 1 data */ #define REG_AUD2LCH (0x0C0/2) /* W A Audio channel 2 location (high 3 bits) */ #define REG_AUD2LCL (0x0C2/2) /* W A Audio channel 2 location (low 15 bits) */ #define REG_AUD2LEN (0x0C4/2) /* W P Audio channel 2 length */ #define REG_AUD2PER (0x0C6/2) /* W P Audio channel 2 period */ #define REG_AUD2VOL (0x0C8/2) /* W P Audio channel 2 volume */ #define REG_AUD2DAT (0x0CA/2) /* W P Audio channel 2 data */ #define REG_AUD3LCH (0x0D0/2) /* W A Audio channel 3 location (high 3 bits) */ #define REG_AUD3LCL (0x0D2/2) /* W A Audio channel 3 location (low 15 bits) */ #define REG_AUD3LEN (0x0D4/2) /* W P Audio channel 3 length */ #define REG_AUD3PER (0x0D6/2) /* W P Audio channel 3 period */ #define REG_AUD3VOL (0x0D8/2) /* W P Audio channel 3 volume */ #define REG_AUD3DAT (0x0DA/2) /* W P Audio channel 3 data */ #define REG_BPL1PTH (0x0E0/2) /* W A Bit plane 1 pointer (high 3 bits) */ #define REG_BPL1PTL (0x0E2/2) /* W A Bit plane 1 pointer (low 15 bits) */ #define REG_BPL2PTH (0x0E4/2) /* W A Bit plane 2 pointer (high 3 bits) */ #define REG_BPL2PTL (0x0E6/2) /* W A Bit plane 2 pointer (low 15 bits) */ #define REG_BPL3PTH (0x0E8/2) /* W A Bit plane 3 pointer (high 3 bits) */ #define REG_BPL3PTL (0x0EA/2) /* W A Bit plane 3 pointer (low 15 bits) */ #define REG_BPL4PTH (0x0EC/2) /* W A Bit plane 4 pointer (high 3 bits) */ #define REG_BPL4PTL (0x0EE/2) /* W A Bit plane 4 pointer (low 15 bits) */ #define REG_BPL5PTH (0x0F0/2) /* W A Bit plane 5 pointer (high 3 bits) */ #define REG_BPL5PTL (0x0F2/2) /* W A Bit plane 5 pointer (low 15 bits) */ #define REG_BPL6PTH (0x0F4/2) /* W A Bit plane 6 pointer (high 3 bits) */ #define REG_BPL6PTL (0x0F6/2) /* W A Bit plane 6 pointer (low 15 bits) */ #define REG_BPLCON0 (0x100/2) /* W A D Bit plane control register (misc. control bits) */ #define REG_BPLCON1 (0x102/2) /* W D Bit plane control reg. (scroll value PF1, PF2) */ #define REG_BPLCON2 (0x104/2) /* W D Bit plane control reg. (priority control) */ #define REG_BPL1MOD (0x108/2) /* W A Bit plane modulo (odd planes) */ #define REG_BPL2MOD (0x10A/2) /* W A Bit Plane modulo (even planes) */ #define REG_BPL1DAT (0x110/2) /* W D Bit plane 1 data (parallel-to-serial convert) */ #define REG_BPL2DAT (0x112/2) /* W D Bit plane 2 data (parallel-to-serial convert) */ #define REG_BPL3DAT (0x114/2) /* W D Bit plane 3 data (parallel-to-serial convert) */ #define REG_BPL4DAT (0x116/2) /* W D Bit plane 4 data (parallel-to-serial convert) */ #define REG_BPL5DAT (0x118/2) /* W D Bit plane 5 data (parallel-to-serial convert) */ #define REG_BPL6DAT (0x11A/2) /* W D Bit plane 6 data (parallel-to-serial convert) */ #define REG_SPR0PTH (0x120/2) /* W A Sprite 0 pointer (high 3 bits) */ #define REG_SPR0PTL (0x122/2) /* W A Sprite 0 pointer (low 15 bits) */ #define REG_SPR1PTH (0x124/2) /* W A Sprite 1 pointer (high 3 bits) */ #define REG_SPR1PTL (0x126/2) /* W A Sprite 1 pointer (low 15 bits) */ #define REG_SPR2PTH (0x128/2) /* W A Sprite 2 pointer (high 3 bits) */ #define REG_SPR2PTL (0x12A/2) /* W A Sprite 2 pointer (low 15 bits) */ #define REG_SPR3PTH (0x12C/2) /* W A Sprite 3 pointer (high 3 bits) */ #define REG_SPR3PTL (0x12E/2) /* W A Sprite 3 pointer (low 15 bits) */ #define REG_SPR4PTH (0x130/2) /* W A Sprite 4 pointer (high 3 bits) */ #define REG_SPR4PTL (0x132/2) /* W A Sprite 4 pointer (low 15 bits) */ #define REG_SPR5PTH (0x134/2) /* W A Sprite 5 pointer (high 3 bits) */ #define REG_SPR5PTL (0x136/2) /* W A Sprite 5 pointer (low 15 bits) */ #define REG_SPR6PTH (0x138/2) /* W A Sprite 6 pointer (high 3 bits) */ #define REG_SPR6PTL (0x13A/2) /* W A Sprite 6 pointer (low 15 bits) */ #define REG_SPR7PTH (0x13C/2) /* W A Sprite 7 pointer (high 3 bits) */ #define REG_SPR7PTL (0x13E/2) /* W A Sprite 7 pointer (low 15 bits) */ #define REG_SPR0POS (0x140/2) /* W A D Sprite 0 vert-horiz start position data */ #define REG_SPR0CTL (0x142/2) /* W A D Sprite 0 vert stop position and control data */ #define REG_SPR0DATA (0x144/2) /* W D Sprite 0 image data register A */ #define REG_SPR0DATB (0x146/2) /* W D Sprite 0 image data register B */ #define REG_SPR1POS (0x148/2) /* W A D Sprite 1 vert-horiz start position data */ #define REG_SPR1CTL (0x14A/2) /* W A D Sprite 1 vert stop position and control data */ #define REG_SPR1DATA (0x14C/2) /* W D Sprite 1 image data register A */ #define REG_SPR1DATB (0x14E/2) /* W D Sprite 1 image data register B */ #define REG_SPR2POS (0x150/2) /* W A D Sprite 2 vert-horiz start position data */ #define REG_SPR2CTL (0x152/2) /* W A D Sprite 2 vert stop position and control data */ #define REG_SPR2DATA (0x154/2) /* W D Sprite 2 image data register A */ #define REG_SPR2DATB (0x156/2) /* W D Sprite 2 image data register B */ #define REG_SPR3POS (0x158/2) /* W A D Sprite 3 vert-horiz start position data */ #define REG_SPR3CTL (0x15A/2) /* W A D Sprite 3 vert stop position and control data */ #define REG_SPR3DATA (0x15C/2) /* W D Sprite 3 image data register A */ #define REG_SPR3DATB (0x15E/2) /* W D Sprite 3 image data register B */ #define REG_SPR4POS (0x160/2) /* W A D Sprite 4 vert-horiz start position data */ #define REG_SPR4CTL (0x162/2) /* W A D Sprite 4 vert stop position and control data */ #define REG_SPR4DATA (0x164/2) /* W D Sprite 4 image data register A */ #define REG_SPR4DATB (0x166/2) /* W D Sprite 4 image data register B */ #define REG_SPR5POS (0x168/2) /* W A D Sprite 5 vert-horiz start position data */ #define REG_SPR5CTL (0x16A/2) /* W A D Sprite 5 vert stop position and control data */ #define REG_SPR5DATA (0x16C/2) /* W D Sprite 5 image data register A */ #define REG_SPR5DATB (0x16E/2) /* W D Sprite 5 image data register B */ #define REG_SPR6POS (0x170/2) /* W A D Sprite 6 vert-horiz start position data */ #define REG_SPR6CTL (0x172/2) /* W A D Sprite 6 vert stop position and control data */ #define REG_SPR6DATA (0x174/2) /* W D Sprite 6 image data register A */ #define REG_SPR6DATB (0x176/2) /* W D Sprite 6 image data register B */ #define REG_SPR7POS (0x178/2) /* W A D Sprite 7 vert-horiz start position data */ #define REG_SPR7CTL (0x17A/2) /* W A D Sprite 7 vert stop position and control data */ #define REG_SPR7DATA (0x17C/2) /* W D Sprite 7 image data register A */ #define REG_SPR7DATB (0x17E/2) /* W D Sprite 7 image data register B */ #define REG_COLOR00 (0x180/2) /* W D Color table 00 */ #define REG_COLOR01 (0x182/2) /* W D Color table 01 */ #define REG_COLOR02 (0x184/2) /* W D Color table 02 */ #define REG_COLOR03 (0x186/2) /* W D Color table 03 */ #define REG_COLOR04 (0x188/2) /* W D Color table 04 */ #define REG_COLOR05 (0x18A/2) /* W D Color table 05 */ #define REG_COLOR06 (0x18C/2) /* W D Color table 06 */ #define REG_COLOR07 (0x18E/2) /* W D Color table 07 */ #define REG_COLOR08 (0x190/2) /* W D Color table 08 */ #define REG_COLOR09 (0x192/2) /* W D Color table 09 */ #define REG_COLOR10 (0x194/2) /* W D Color table 10 */ #define REG_COLOR11 (0x196/2) /* W D Color table 11 */ #define REG_COLOR12 (0x198/2) /* W D Color table 12 */ #define REG_COLOR13 (0x19A/2) /* W D Color table 13 */ #define REG_COLOR14 (0x19C/2) /* W D Color table 14 */ #define REG_COLOR15 (0x19E/2) /* W D Color table 15 */ #define REG_COLOR16 (0x1A0/2) /* W D Color table 16 */ #define REG_COLOR17 (0x1A2/2) /* W D Color table 17 */ #define REG_COLOR18 (0x1A4/2) /* W D Color table 18 */ #define REG_COLOR19 (0x1A6/2) /* W D Color table 19 */ #define REG_COLOR20 (0x1A8/2) /* W D Color table 20 */ #define REG_COLOR21 (0x1AA/2) /* W D Color table 21 */ #define REG_COLOR22 (0x1AC/2) /* W D Color table 22 */ #define REG_COLOR23 (0x1AE/2) /* W D Color table 23 */ #define REG_COLOR24 (0x1B0/2) /* W D Color table 24 */ #define REG_COLOR25 (0x1B2/2) /* W D Color table 25 */ #define REG_COLOR26 (0x1B4/2) /* W D Color table 26 */ #define REG_COLOR27 (0x1B6/2) /* W D Color table 27 */ #define REG_COLOR28 (0x1B8/2) /* W D Color table 28 */ #define REG_COLOR29 (0x1BA/2) /* W D Color table 29 */ #define REG_COLOR30 (0x1BC/2) /* W D Color table 30 */ #define REG_COLOR31 (0x1BE/2) /* W D Color table 31 */ /* DMACON bit layout */ #define DMACON_AUD0EN 0x0001 #define DMACON_AUD1EN 0x0002 #define DMACON_AUD2EN 0x0004 #define DMACON_AUD3EN 0x0008 #define DMACON_DSKEN 0x0010 #define DMACON_SPREN 0x0020 #define DMACON_BLTEN 0x0040 #define DMACON_COPEN 0x0080 #define DMACON_BPLEN 0x0100 #define DMACON_DMAEN 0x0200 #define DMACON_BLTPRI 0x0400 #define DMACON_RSVED1 0x0800 #define DMACON_RSVED2 0x1000 #define DMACON_BZERO 0x2000 #define DMACON_BBUSY 0x4000 #define DMACON_SETCLR 0x8000 /* BPLCON0 bit layout */ #define BPLCON0_RSVED1 0x0001 #define BPLCON0_ERSY 0x0002 #define BPLCON0_LACE 0x0004 #define BPLCON0_LPEN 0x0008 #define BPLCON0_RSVED2 0x0010 #define BPLCON0_RSVED3 0x0020 #define BPLCON0_RSVED4 0x0040 #define BPLCON0_RSVED5 0x0080 #define BPLCON0_GAUD 0x0100 #define BPLCON0_COLOR 0x0200 #define BPLCON0_DBLPF 0x0400 #define BPLCON0_HOMOD 0x0800 #define BPLCON0_BPU0 0x1000 #define BPLCON0_BPU1 0x2000 #define BPLCON0_BPU2 0x4000 #define BPLCON0_HIRES 0x8000 /* INTENA/INTREQ bit layout */ #define INTENA_TBE 0x0001 #define INTENA_DSKBLK 0x0002 #define INTENA_SOFT 0x0004 #define INTENA_PORTS 0x0008 #define INTENA_COPER 0x0010 #define INTENA_VERTB 0x0020 #define INTENA_BLIT 0x0040 #define INTENA_AUD0 0x0080 #define INTENA_AUD1 0x0100 #define INTENA_AUD2 0x0200 #define INTENA_AUD3 0x0400 #define INTENA_RBF 0x0800 #define INTENA_DSKSYN 0x1000 #define INTENA_EXTER 0x2000 #define INTENA_INTEN 0x4000 #define INTENA_SETCLR 0x8000 #define MAX_PLANES 6 /* 0 to 6, inclusive ( but we count from 0 to 5 ) */ /* Clock speeds */ #define AMIGA_68000_NTSC_CLOCK XTAL_28_63636MHz/4 #define AMIGA_68000_PAL_CLOCK XTAL_28_37516MHz/4 #define AMIGA_68EC020_NTSC_CLOCK XTAL_28_63636MHz/2 #define AMIGA_68EC020_PAL_CLOCK XTAL_28_37516MHz/2 #define CDTV_CLOCK_X1 XTAL_28_63636MHz #define CDTV_CLOCK_X5 XTAL_28_37516MHz #define ANGUS_CHIP_RAM_MASK 0x07fffe #define FAT_ANGUS_CHIP_RAM_MASK 0x0ffffe #define ECS_CHIP_RAM_MASK 0x1ffffe #define AGA_CHIP_RAM_MASK 0x1ffffe #define FLAGS_AGA_CHIPSET (1 << 0) typedef struct _amiga_machine_interface amiga_machine_interface; struct _amiga_machine_interface { UINT32 chip_ram_mask; UINT16 (*joy0dat_r)(void); UINT16 (*joy1dat_r)(void); void (*potgo_w)(UINT16 data); UINT16 (*dskbytr_r)(void); void (*dsklen_w)(UINT16 data); void (*serdat_w)(running_machine *, UINT16 data); void (*scanline0_callback)(running_machine *); void (*reset_callback)(void); void (*nmi_callback)(void); UINT32 flags; }; #define IS_AGA(intf) ( intf->chip_ram_mask == AGA_CHIP_RAM_MASK && (( intf->flags & FLAGS_AGA_CHIPSET) != 0)) #define IS_ECS(intf) ( intf->chip_ram_mask == ECS_CHIP_RAM_MASK && (( intf->flags & FLAGS_AGA_CHIPSET) == 0)) #define IS_ECS_OR_AGA(intf) ( intf->chip_ram_mask == ECS_CHIP_RAM_MASK) typedef struct _amiga_autoconfig_device amiga_autoconfig_device; struct _amiga_autoconfig_device { UINT8 link_memory; /* link into free memory list */ UINT8 rom_vector_valid; /* ROM vector offset valid */ UINT8 multi_device; /* multiple devices on card */ UINT8 size; /* number of 64k pages */ UINT16 product_number; /* product number */ UINT8 prefer_8meg; /* prefer 8MB address space */ UINT8 can_shutup; /* can be shut up */ UINT16 mfr_number; /* manufacturers number */ UINT32 serial_number; /* serial number */ UINT16 rom_vector; /* ROM vector offset */ UINT8 (*int_control_r)(void); /* interrupt control read */ void (*int_control_w)(UINT8 data); /* interrupt control write */ void (*install)(offs_t base); /* memory installation */ void (*uninstall)(offs_t base); /* memory uninstallation */ }; /*----------- defined in machine/amiga.c -----------*/ extern UINT16 *amiga_chip_ram; extern UINT32 *amiga_chip_ram32; extern size_t amiga_chip_ram_size; extern UINT16 *amiga_custom_regs; extern UINT16 *amiga_expansion_ram; extern UINT16 *amiga_autoconfig_mem; extern const char *const amiga_custom_names[0x100]; extern UINT16 (*amiga_chip_ram_r)(offs_t offset); extern void (*amiga_chip_ram_w)(offs_t offset, UINT16 data); void amiga_machine_config(running_machine *machine, const amiga_machine_interface *intf); MACHINE_RESET( amiga ); CUSTOM_INPUT( amiga_joystick_convert ); READ16_HANDLER( amiga_cia_r ); WRITE16_HANDLER( amiga_cia_w ); READ16_HANDLER( amiga_custom_r ); WRITE16_HANDLER( amiga_custom_w ); void amiga_serial_in_w(running_machine *machine, UINT16 data); attotime amiga_get_serial_char_period(running_machine *machine); void amiga_add_autoconfig(running_machine *machine, const amiga_autoconfig_device *device); READ16_HANDLER( amiga_autoconfig_r ); WRITE16_HANDLER( amiga_autoconfig_w ); void amiga_cia_0_irq(const device_config *device, int state); void amiga_cia_1_irq(const device_config *device, int state); const amiga_machine_interface *amiga_get_interface(void); /*----------- defined in audio/amiga.c -----------*/ CUSTOM_START( amiga_sh_start ); void amiga_audio_update(void); void amiga_audio_data_w(int which, UINT16 data); /*----------- defined in video/amiga.c -----------*/ PALETTE_INIT( amiga ); VIDEO_START( amiga ); VIDEO_UPDATE( amiga ); UINT32 amiga_gethvpos(const device_config *screen); void copper_setpc(UINT32 pc); void amiga_set_genlock_color(UINT16 color); void amiga_render_scanline(running_machine *machine, bitmap_t *bitmap, int scanline); void amiga_sprite_dma_reset(int which); void amiga_sprite_enable_comparitor(int which, int enable); #endif /* __AMIGA_H__ */