lib file = ; lib s = ; lib sdl = ; lib consts = ; lib m = ; lib tbl = ; lib cfg = "config.ssz"; lib com = "common.ssz"; const int NumCharPalletes = 12; public &SffHeader { public ubyte ver0, ver1, ver2, ver3; public uint firstSpriteHeaderOffset, firstPaletteHeaderOffset; public uint numberOfPalettes, numberOfSprites; public bool read(&.file.File f=, uint lofs=, uint tofs=) { ubyte ub; loop{ index i = 0; %char s; do: if(!f.read!ubyte?(ub=)) ret false; s .= (char)ub; i++; while i < 12: if(!.s.equ(s, "ElecbyteSpr"\0)){ .com.error!self?("ElecbyteSprじゃない"); ret false; } } if(!f.read!ubyte?(`ver3=)) ret false; if(!f.read!ubyte?(`ver2=)) ret false; if(!f.read!ubyte?(`ver1=)) ret false; if(!f.read!ubyte?(`ver0=)) ret false; uint dummy; switch(`ver0){ case 0d1: if(!f.read!uint?(dummy=)) ret false; `numberOfPalettes = 0x0; if(!f.read!uint?(`numberOfSprites=)) ret false; if(!f.read!uint?(`firstSpriteHeaderOffset=)) ret false; if(!f.read!uint?(dummy=)) ret false; `firstPaletteHeaderOffset = 0x0; case 0d2: if(!f.read!uint?(dummy=)) ret false; if(!f.read!uint?(dummy=)) ret false; if(!f.read!uint?(dummy=)) ret false; if(!f.read!uint?(dummy=)) ret false; if(!f.read!uint?(dummy=)) ret false; if(!f.read!uint?(`firstSpriteHeaderOffset=)) ret false; if(!f.read!uint?(`numberOfSprites=)) ret false; if(!f.read!uint?(`firstPaletteHeaderOffset=)) ret false; if(!f.read!uint?(`numberOfPalettes=)) ret false; if(!f.read!uint?(lofs=)) ret false; if(!f.read!uint?(dummy=)) ret false; if(!f.read!uint?(tofs=)) ret false; default: ret false; } ret true; } } &PalleteList { %^uint palletes; %index palidxs; public &.tbl.IntTable!uint, index? palTable; public void clear() { `palletes.new(0); `palidxs.new(0); `palTable.clear(); } public ^uint newPal(index pi=) { `palidxs.new[#`palletes] = (pi = #`palletes); `palletes.new[-1].new(256); ret `palletes[-1]; } public void setSource(index pi, ^uint pal) { `palidxs.new[pi] = pi; `palletes.new[pi] = pal; } public ^uint get(index pi) { ret `palletes[`palidxs[pi]]; } public void remap(index source, index dest) { `palidxs[source] = dest; } public void resetRemap() { loop{index i = 0; while; do: `palidxs[i] = i; i++; while i < #`palidxs:} } } public &Sprite { public ^uint colorPallet; public ^ubyte pxl; public %byte pluginbuf; public &.sdl.Rect rct; public short imageGroup, imageNumber; public index palidx = -1, link = -1; public int rle = 0; public void shareCopy(`self sp=) { `colorPallet = sp.colorPallet; `pxl = sp.pxl; `rct.w = sp.rct.w; `rct.h = sp.rct.h; `palidx = sp.palidx; `rle = sp.rle; } public void copy(`self sp=) { `shareCopy(sp=); `pluginbuf = sp.pluginbuf; `rct = sp.rct; `imageGroup = sp.imageGroup; `imageNumber = sp.imageNumber; `link = sp.link; } public ^uint getPal(&.PalleteList pl=) { if(#`colorPallet > 0) ret `colorPallet; ret pl.get(`palidx); } public bool readHeader(&.file.File f=) { if(!f.read!short?(`rct.x=)) ret false; if(!f.read!short?(`rct.y=)) ret false; if(!f.read!short?(`imageGroup=)) ret false; if(!f.read!short?(`imageNumber=)) ret false; ret true; } public bool readPcxHeader(&.file.File f=, long offset) { f.seek(offset, .file.Seek::SET); ubyte dummy, encoding, bpp; if(!f.read!ubyte?(dummy=)) ret false; if(!f.read!ubyte?(dummy=)) ret false; if(!f.read!ubyte?(encoding=)) ret false; if(!f.read!ubyte?(bpp=)) ret false; if(bpp != 0d8){ .com.error!.self?("256色じゃない"); ret false; } ushort x, y, w, h; if(!f.read!ushort?(x=)) ret false; if(!f.read!ushort?(y=)) ret false; if(!f.read!ushort?(w=)) ret false; if(!f.read!ushort?(h=)) ret false; f.seek(offset+66, .file.Seek::SET); ushort bpl; if(!f.read!ushort?(bpl=)) ret false; `rct.w = w - x + 0x1; `rct.h = h - y + 0x1; `rle = encoding == 0x1 ? (int)bpl : 0; ret true; } public bool readHeaderV2( &.file.File f=, uint ofs=, uint siz=, uint lofs, uint tofs, ushort idxlnked=) { if(!f.read!short?(`imageGroup=)) ret false; if(!f.read!short?(`imageNumber=)) ret false; if(!f.read!ushort?(`rct.w=)) ret false; if(!f.read!ushort?(`rct.h=)) ret false; if(!f.read!short?(`rct.x=)) ret false; if(!f.read!short?(`rct.y=)) ret false; if(!f.read!ushort?(idxlnked=)) ret false; ubyte fmt, dummy; if(!f.read!ubyte?(fmt=)) ret false; `rle = -(int)fmt; if(!f.read!ubyte?(dummy=)) ret false; if(!f.read!uint?(ofs=)) ret false; if(!f.read!uint?(siz=)) ret false; ushort pali, flg; if(!f.read!ushort?(pali=)) ret false; `palidx = (index)pali; if(!f.read!ushort?(flg=)) ret false; ofs += (flg & 0d1) == 0x0 ? lofs : tofs; ret true; } public bool read( &.file.File f=, &.SffHeader sh=, long offset, uint loh, uint nsh, ^`self prev, bool palletSame=, &.PalleteList pl=, bool c00) { uint lenghtOfSubheader = loh; if(nsh > (uint)offset) lenghtOfSubheader = nsh - (uint)offset;//lohを無視 if(!f.read!bool?(palletSame=)) ret false; if(#prev == 0) palletSame = false; if(!`readPcxHeader(f=, offset)) ret false; f.seek(offset + 128, .file.Seek::SET); `pxl.new((index)lenghtOfSubheader - (128+(c00||palletSame?0:768))); f.readAry!ubyte?(`pxl); loop{ index i = 0; ubyte r, g, b; if(palletSame){ if(#prev > 0) `palidx = prev~palidx; if(`palidx < 0) pl.newPal(`palidx=); break, break; } ^uint pal = pl.newPal(`palidx=); if(c00) f.seek(offset + (long)lenghtOfSubheader - 768, .file.Seek::SET); do: if(!f.read!ubyte?(r=)) ret false; if(!f.read!ubyte?(g=)) ret false; if(!f.read!ubyte?(b=)) ret false; pal[i] = (uint)r<<0d16 | (uint)g<<0d8 | (uint)b; i++; while i < 256: } if( !.cfg.SaveMemory || (index)`rct.w*(index)`rct.h < (`rct.w >= 0d256 ? (#`pxl/256)*(index)`rct.w : #`pxl)) { `rlePcxDecode(); } ret true; } public bool readV2(&.file.File f=, long ofs, uint dsz) { f.seek(ofs+4, .file.Seek::SET); `pxl.new((index)dsz); f.readAry!ubyte?(`pxl); if(`rle < 0) switch(-`rle){ case 2: `rle8Decode(); case 3: `rle5Decode(); case 4: `lz5Decode(); default: ret false; } ret true; } public void rlePcxDecode() { if(#`pxl == 0 || `rle <= 0) ret; ^/ubyte rle = `pxl; `pxl.new((index)((uint)`rct.w * `rct.h)); loop{ int w = (int)`rct.w; int leng = #`pxl; index i = 0, j = 0, k = 0; do: loop{ int size; ubyte d = rle[i++]; branch{ cond d >= 0xC0: size = (int)(d & 0x3F); d = rle[i++]; else: size = 1; } while; do: `pxl[j] = d; j += (int)(k < w); if(++k == `rle){ k = 0; size = 0; } while --size >= 0: } while j < leng: } `rle = 0; } public void rle8Decode() { if(#`pxl == 0) ret; ^/ubyte rle = `pxl; `pxl.new((index)((uint)`rct.w * `rct.h)); loop{ int leng = #`pxl; index i = 0, j = 0; while; do: loop{ int size; ubyte d = rle[i++]; branch{ cond (d&0xC0) == 0x40: size = (int)(d & 0x3F); d = rle[i++]; else: size = 1; } while; do: `pxl[j++] = d; while --size >= 0: } while j < leng: } `rle = 0; } public void rle5Decode() { if(#`pxl == 0) ret; ^/ubyte rle = `pxl; `pxl.new((index)((uint)`rct.w * `rct.h)); loop{ int leng = #`pxl; index i = 0, j = 0; while; do: loop{ int rlen = (int)rle[i++]; int dlen = (int)(rle[i] & 0x7F); ubyte c = rle[i++]>>0d7 != 0x0 ? rle[i++] : 0x0; do: `pxl[j++] = c; while --rlen >= 0: if(--dlen >= 0){ c = rle[i] & 0x1F; rlen = (int)(rle[i++]>>0d5); break, do; } } while j < leng: } `rle = 0; } public void lz5Decode() { if(#`pxl == 0) ret; ^/ubyte rle = `pxl; `pxl.new((index)((uint)`rct.w * `rct.h)); loop{ int leng = #`pxl; index i = 0, j = 0; uint s = 0x0, rbc = 0x0; ubyte ct = rle[i++], rb = 0x0; while; do: branch{ int size; uint d; cond (ct & 0d1<> rbc; rbc += 0d2; size = (int)(d & 0x3F); branch{ cond rbc < 0d8: d = (uint)rle[i++] + 0x1; else: d = (uint)rb + 0d1; rbc = 0x0; rb = 0x0; } } do: `pxl[j] = `pxl[j-(index)d]; j++; while --size >= 0: } else: loop{ d = rle[i++]; branch{ cond (d&0xE0) == 0x00: size = (int)rle[i++] + 8; else: size = (int)(d >> 0d5); d &= 0x1F; } while; do: `pxl[j++] = d; while --size >= 0: } } if(++s >= 0d8){ s = 0x0; ct = rle[i++]; } while j < leng: } `rle = 0; } public bool loadFromSff(^/char fn, short ig, short in) { &.file.File f; if(!f.open(fn, "rb")) ret false; &.SffHeader h; uint lofs, tofs; if(!h.read(f=, lofs=, tofs=)) ret false; uint shofs = h.firstSpriteHeaderOffset, misc, size; ushort indexOfPrevious; &.PalleteList pl; loop{ index i = 0; %uint newSubHeaderOffset .= shofs; bool palletSame; ~$bool() foo = [bool(){ switch(h.ver0){ case 0d1: if(!f.read!uint?(misc=)) ret false; if(!f.read!uint?(size=)) ret false; if(!`readHeader(f=)) ret false; if(!f.read!ushort?(indexOfPrevious=)) ret false; case 0d2: if( !`readHeaderV2( f=, misc=, size=, lofs, tofs, indexOfPrevious=)) ret false; } ret true; }]; ^`self dummy; while; do: newSubHeaderOffset .= shofs; f.seek((long)shofs, .file.Seek::SET); if(!foo(::)) ret false; if(`palidx >= 0 && (`imageGroup != ig || `imageNumber != in)) continue; loop{ uint ip = !indexOfPrevious; while; do: if(ip == indexOfPrevious) ret false; ip = indexOfPrevious; shofs = h.ver0 == 0d1 ? newSubHeaderOffset[(index)ip] : h.firstSpriteHeaderOffset + ip*0d28; f.seek((long)shofs, .file.Seek::SET); if(!foo(::)) ret false; while size == 0d0: } switch(h.ver0){ case 0d1: if( !`read( f=, h=, (long)(shofs + 0d32), size, misc, dummy, palletSame=, pl=, false)) ret false; case 0d2: if(!`readV2(f=, (long)misc, size)) ret false; } if(`imageGroup == ig && `imageNumber == in) break; dummy.new(1); dummy~palidx = `palidx; continue: shofs = h.ver0 == 0d1 ? misc : shofs + 0d28; i++; while i < (index)h.numberOfSprites: ret false; } if(h.ver0 == 0d1){ `colorPallet = pl.get(`palidx); `palidx = -1; ret true; } loop{ uint ip; indexOfPrevious = (uint)`palidx; do: ip = indexOfPrevious; shofs = h.firstPaletteHeaderOffset + ip*0d16; f.seek((long)shofs + 6, .file.Seek::SET); if(!f.read!ushort?(indexOfPrevious=)) ret false; if(!f.read!uint?(misc=)) ret false; if(!f.read!uint?(size=)) ret false; while size == 0d0 && ip != indexOfPrevious: } f.seek((long)(lofs+misc), .file.Seek::SET); `colorPallet.new(256); loop{ index i = 0, l = (index)size / 4; ubyte r, g, b, dummy; do: if(!f.read!ubyte?(r=)) ret false; if(!f.read!ubyte?(g=)) ret false; if(!f.read!ubyte?(b=)) ret false; if(!f.read!ubyte?(dummy=)) ret false; `colorPallet[i] = (uint)r<<0d16 | (uint)g<<0d8 | (uint)b; i++; while i < l: } if(#`colorPallet == 0) `colorPallet.new(256); `palidx = -1; ret true; } public void draw(float x, float y, float xscale, float yscale, ^uint pal) { &.sdl.Rect tile; tile.set(0, 0, 0d0, 0d0); float x2 = x - xscale*(float)`rct.x; float y2 = y - yscale*(float)`rct.y; if(xscale < 0.0) x2 *= -1.0; if(yscale < 0.0) y2 = -y2 + 240.0; .sdl.screen.renderMugenZoom( .com.scrrect=, 0.0, 0.0, `pxl, pal, 0, `rct=, -x2*.com.WidthScale, -y2*.com.HeightScale, tile=, xscale*.com.WidthScale, xscale*.com.WidthScale, yscale*.com.HeightScale, 0.0, 0x0, 255, `rle, `pluginbuf=); } } public &Sff { public &.SffHeader head; public &.tbl.IntTable!uint, &.Sprite? spriteTable; public &.PalleteList palList; new() { `clear(); } public void clear() { `spriteTable.clear(); `palList.clear(); loop{ index i = 0, foo; ^index idx; while; do: `palList.newPal(foo=); i++; idx.new(1); idx<> = foo; `palList.palTable.set(0d1<<0d16 | (uint)i, idx); while i < .NumCharPalletes: } } public bool loadFile(^/char filename, bool chr) { &.file.File f; if(!f.open(filename, "rb")) ret false; `clear(); uint lofs, tofs; if(!`head.read(f=, lofs=, tofs=)) ret false; if(`head.ver0 != 0d1)loop{ index i = 0; ^uint pal; ushort group, item, link, dummy; uint ofs, siz; ^index idx; while; do: f.seek((long)`head.firstPaletteHeaderOffset + 16*i, .file.Seek::SET); if(!f.read!ushort?(group=)) ret false; if(!f.read!ushort?(item=)) ret false; if(!f.read!ushort?(dummy=)) ret false; if(!f.read!ushort?(link=)) ret false; if(!f.read!uint?(ofs=)) ret false; if(!f.read!uint?(siz=)) ret false; idx.new(1); branch{ cond siz == 0x0: pal = `palList.get((index)link); idx<> = (index)link; else: f.seek((long)(lofs+ofs), .file.Seek::SET); pal.new(256); loop{ index i = 0, l = (index)siz / 4; ubyte r, g, b, dummy8; do: if(!f.read!ubyte?(r=)) ret false; if(!f.read!ubyte?(g=)) ret false; if(!f.read!ubyte?(b=)) ret false; if(!f.read!ubyte?(dummy8=)) ret false; pal[i] = (uint)r<<0d16 | (uint)g<<0d8 | (uint)b; i++; while i < l: } idx<> = i; } `palList.setSource(i, pal); `palList.palTable.set((uint)group<<0d16 | item, idx); i++; while i < (index)`head.numberOfPalettes: } uint shofs = `head.firstSpriteHeaderOffset, size; loop{ index i = 0; uint misc; ^&.Sprite spriteList; spriteList.new((index)`head.numberOfSprites); ushort indexOfPrevious; index prev = -1; while; do: f.seek((long)shofs, .file.Seek::SET); switch(`head.ver0){ case 0d1: if(!f.read!uint?(misc=)) ret false; if(!f.read!uint?(size=)) ret false; if(!spriteList[i].readHeader(f=)) ret false; if(!f.read!ushort?(indexOfPrevious=)) ret false; case 0d2: if( !spriteList[i].readHeaderV2( f=, misc=, size=, lofs, tofs, indexOfPrevious=)) ret false; } branch{ bool ps; cond size != 0d0: switch(`head.ver0){ case 0d1: if( !spriteList[i].read( f=, `head=, (long)(shofs + 0d32), size, misc, spriteList[prev..prev+1], ps=, `palList=, chr && spriteList[i].imageGroup == 0 && spriteList[i].imageNumber == 0)) ret false; case 0d2: if(!spriteList[i].readV2(f=, (long)misc, size)) ret false; } prev = i; else: spriteList[i].shareCopy(spriteList[(index)indexOfPrevious]=); spriteList[i].link = (index)indexOfPrevious; } `spriteTable.operate( (uint)spriteList[i].imageGroup | (uint)spriteList[i].imageNumber<<0d16, [void(^&.Sprite s=){if(#s == 0) s = spriteList[i..i+1];}]); shofs = `head.ver0 == 0d1 ? misc : shofs + 0d28; i++; while i < (index)`head.numberOfSprites: } ret true; } public ^&.Sprite getSprite(short group, short number) { ret `spriteTable.get((uint)group | (uint)number<<0d16); } public ^&.Sprite getOwnPalSprite(short group, short number) { ^&.Sprite sp = `spriteTable.get((uint)group | (uint)number<<0d16); if(#sp == 0) ret sp; ^&.Sprite ops.new(1); ops~copy(sp<>=); ops~colorPallet = .s.clone!uint?(sp~getPal(`palList=)); ret ops; } } public &Anim { public ^&.Sff sff; public ^&.Sprite spr; public %frame_t frames; public &.sdl.Rect tile; public index loopstart = 0, current = 0, drawidx = 0; public int nrepeat = -1; public int time = 0; public int repeatcnt = 0; public int mask = -1; public short salpha = -1, dalpha = 0; public byte h = 1, v = 1; public bool newframe = true, loopend = false; new() { `tile.set(0, 0, 0d0, 0d0); } public void reset() { `current = 0; `drawidx = 0; `time = 0; `repeatcnt = 0; `newframe = true; `loopend = false; } public void copy(`self a=) { `sff = a.sff; `spr = a.spr; `frames = a.frames; `tile = a.tile; `loopstart = a.loopstart; `current = a.current; `drawidx = a.drawidx; `nrepeat = a.nrepeat; `time = a.time; `repeatcnt = a.repeatcnt; `mask = a.mask; `salpha = a.salpha; `dalpha = a.dalpha; `h = a.h; `v = a.v; `newframe = a.newframe; `loopend = a.loopend; } public void setFrames(%`frame_t f, index l, int r) { `frames = f; `loopstart = l; `nrepeat = r; } public ^frame_t currentFrame() { ret `frames[`current..`current+1]; } public int animTime() { if(#`frames == 0) ret 0; if(`loopend && `time == 0) loop{ index i = `loopstart; do: if(i == `current) ret 0; if(`frames[i].time != 0) break; i++; while i < #`frames: } int at = `time; branch{ cond `frames[-1].time < 0: at++; loop{index j = 0; while; do: at += `frames[j].time; j++; while j < `current: } else: loop{ index i = `current; if(`frames[i].time == 0) at--; while; do: at -= `frames[i].time; i++; while i < #`frames: } } ret at; } public int animElemTime(int elem) { int t; if(elem > #`frames){ t = `animTime(); ret t > 0 ? 0 : t; } int e = elem - 1; if(`loopend && `time == 0 && `current == `loopstart){ t = 0; loop{index i = e; while; do: t += `frames[i].time; i++; while i < #`frames && `frames[i].time >= 0: } ret t; } t = `time; loop{index i = e; while; do: t += `frames[i].time; i++; while i < `current && `frames[i].time >= 0: } loop{index i = `current; while; do: t -= `frames[i].time; i++; while i < e && `frames[i].time >= 0: } ret t; } public int animElemNo(int time) { if(time == 0 && `loopend && `time == 0 && `current == `loopstart){ ret #`frames; } branch{ int t = time, oldt = 0; cond t < 0: loop{ index i = `current; t += `time; bool lp = false; continue; do: t += `frames[i].time; continue: if(lp && `frames[i].time < 0){ ret i + 1; } if(t >= 0){ if(t == 0 && `loopend && i == `loopstart) ret #`frames; ret i + 1; } i--; while i >= 0 && (`current < `loopstart || i >= `loopstart): if(t == oldt) break; oldt = t; lp = true; i = #`frames - 1; do; } else: loop{ index i = `current; t -= `frames[i].time - `time; continue; do: t -= `frames[i].time; continue: if(t <= 0 || `frames[i].time < 0){ if(t == 0 && `loopend && i == `loopstart) ret #`frames; ret i + 1; } i++; if(i >= #`frames){ if(t == oldt) break, break; oldt = t; i = `loopstart; } while true: } } ret 1; } public void setAnimElem(int e) { `current = .m.max!index?(0, e-1); if(`current >= #`frames){ `current = `loopstart + `current % (#`frames-`loopstart); } `drawidx = `current; `time = 0; `newframe = true; `updateSprite(); `loopend = false; } public void updateSprite() { if(#`frames == 0) ret; if(`newframe){ `spr = `sff~getSprite(`frames[`current].group, `frames[`current].number); } `newframe = false; `drawidx = `current; } public void action() { if(#`frames == 0) ret; `updateSprite(); `frames[`current].action(`=); } int alphaFoo() { ubyte sa, da; branch{ cond `salpha >= 0: sa = (ubyte)`salpha; da = (ubyte)`dalpha; else: sa = `frames[`drawidx].salpha; da = `frames[`drawidx].dalpha; } branch{ cond sa == 0d1 && da == 0d255: ret -2; else: sa = (ubyte)((int)sa * .com.brightness >> 8); branch{ cond sa < 0d5 && da == 0d255: ret 0; cond sa == 0d255 && da == 0d255: ret -1; } } int alpha = (int)sa; if((uint)sa+da < 0d254 || 0d256 < (uint)sa+da){ alpha |= (int)da << 10 | 1 << 9; } ret alpha; } ^uint palFoo(^&.com.PalFX fx) { if(#fx == 0 || fx~time == 0) ret `spr~getPal(`sff~palList=); ret fx~getFxPal(`spr~getPal(`sff~palList=), `alphaFoo() == -2); } public void draw( &.sdl.Rect rect=, float x, float y, float cscalex, float cscaley, float xtscale, float xbscale, float yscale, float rasterxadd, float rx, ^&.com.PalFX fx) { if(#`spr == 0 || #`spr~pxl == 0) ret; int h = `h*`frames[`drawidx].h, v = `v*`frames[`drawidx].v; float xs = (float)h*cscalex*xtscale, ys = (float)v*cscaley*yscale; float bs = xbscale; .m.limRange!float?(xs=, -16000.0/.com.WidthScale, 16000.0/.com.WidthScale); .m.limRange!float?( ys=, -16000.0/.com.HeightScale, 16000.0/.com.HeightScale); .m.limRange!float?(bs=, -16000.0/.com.WidthScale, 16000.0/.com.WidthScale); float x2 = cscalex*x - xs*(float)(`spr~rct.x - `frames[`drawidx].x) + rx; float y2 = cscaley*y - ys*(float)(`spr~rct.y - `frames[`drawidx].y); if(xs < 0.0){ x2 *= -1.0; x2 += rx*2.0; if(rx != 0.0) x2 += xs; } if(ys < 0.0){ y2 *= -1.0; y2 += 240.0; if(rx != 0.0) y2 += ys; } if(`tile.w == 0x1){ float tmp = xs * ((float)`tile.x + (`tile.x > 0 ? 0.0 : (float)`spr~rct.w)); x2 -= (float)(int)(x2 / tmp) * tmp; } if(`tile.h == 0x1){ float tmp = ys * ((float)`tile.y + (`tile.y > 0 ? 0.0 : (float)`spr~rct.h)); y2 -= (float)(int)(y2 / tmp) * tmp; } .sdl.screen.renderMugenZoom( rect=, rx*.com.WidthScale, 0.0, `spr~pxl, `palFoo(fx), `mask, `spr~rct=, (rx-x2)*.com.WidthScale, -y2*.com.HeightScale, `tile=, xs*.com.WidthScale, cscalex*bs*(float)h*.com.WidthScale, ys*.com.HeightScale, cscalex*rasterxadd*(.com.WidthScale/.com.HeightScale), 0x0, `alphaFoo(), `spr~rle, `spr~pluginbuf=); } public void angleDraw( float x, float y, float xscale, float yscale, float angle, bool angleset, float axscl, float ayscl, ^&.com.PalFX fx) { if(#`spr == 0 || #`spr~pxl == 0) ret; float rx = x + 160.0; int h = `h*`frames[`drawidx].h; int v = `v*`frames[`drawidx].v; float xs = xscale * axscl, ys = yscale * ayscl; float agl = angle*(float)(`h * `v * (xs < 0.0 ? -1: 1) * (ys < 0.0 ? -1: 1)); uint uagl = (uint)((512.0/.m.PI)*agl + 0.5) & 0x3ff; if(uagl == 0x0) branch{ cond angleset: `draw( .com.scrrect=, x+160.0 - xs*(float)(h*`frames[`drawidx].x), y, 1.0, 1.0, xs, xs, ys, 0.0, 0.0, fx); else: `draw( .com.scrrect=, x - (float)h*xscale*(axscl - 1.0)*(float)`frames[`drawidx].x, y, 1.0, 1.0, xs, xs, ys, 0.0, 160.0, fx); comm: ret; } .sdl.screen.renderMugenZoom( .com.scrrect=, rx*.com.WidthScale, (y+ys*(float)(v*`frames[`drawidx].y))*.com.HeightScale, `spr~pxl, `palFoo(fx), `mask, `spr~rct=, #xs*(float)`spr~rct.x*.com.WidthScale, #ys*(float)`spr~rct.y*.com.HeightScale, `tile=, xs*(float)h*.com.WidthScale, xs*(float)h*.com.WidthScale, ys*(float)v*.com.HeightScale, 0.0, uagl, `alphaFoo(), `spr~rle, `spr~pluginbuf=); } public void setup(^&.Sff sff) { `sff = sff; } }