Format ElfObj64

include "../include/prog.h" "../include/prog.oh"

#multithread unsafe
dataxu nr#1
charx rcb#1
valuexu is_else_next_mark#1
valueu values_container=NULL

#win32 with _
importx "strcmp" strcmp
importx "strlen" strlen
importx "sscanf" sscanf

function action_code_values()
	return global.values_container
endfunction

import "mem_free" mem_free

function action_code_values_free()
    if global.values_container!=(NULL);call mem_free(#global.values_container);endif
endfunction
function action_code_values_index()
	return #global.nr
endfunction
#pointer
function action_code_get()
    sd nr
    setcall nr action_code_values_index()
    sd x
    set x nr#
    sv pointer
    setcall pointer action_code_values()
    mult x (DWORD)
    add pointer x
    return pointer
endfunction

function action_code_values_action()
	set global.nr 0
	set global.is_else_next_mark (NULL)
	return #global.nr
end

import "swf_actionblock_get_size" swf_actionblock_get_size

import "brace_blocks_counter" brace_blocks_counter

function get_nr_of_forIn_statements()
	sd start;set start cond_blocks_at_index(0)
	sd block;setcall block cond_blocks()
	sd nr=0
	while start!=block
		sub block (DWORD)
		if block#=(brace_blocks_function)
			return nr
		endif
		if block#=(forin_marker)
			inc nr
		endif
	endwhile
	return nr
endfunction

#name/null
function action_code_write_builtin_names(sv codepointer,sd p_action)
	sd name
	set name x_pointer(codepointer)
	datax compare#1
	vstr intstr="int"
	setcall compare strcmp(name,intstr)
	if compare=0
		set p_action# (ActionToInteger)
		return intstr
	endif
	vstr rnd="random"
	setcall compare strcmp(name,rnd)
	if compare=0
	#0�(maximum-1)
		set p_action# (ActionRandomNumber)
		return rnd
	endif
	vstr ascii="ord"
	setcall compare strcmp(name,ascii)
	if compare=0
		set p_action# (ActionCharToAscii)
		return ascii
	endif
	vstr chr="chr"
	setcall compare strcmp(name,chr)
	if compare=0
		set p_action# (ActionAsciiToChar)
		return chr
	endif
	vstr typeOf="typeof"
	setcall compare strcmp(name,typeOf)
	if compare=0
		set p_action# (ActionTypeOf)
		return typeOf
	endif
	vstr stop="stop"
	setcall compare strcmp(name,stop)
	if compare=0
		set p_action# (ActionStop)
		return stop
	endif
	vstr play="play"
	setcall compare strcmp(name,play)
	if compare=0
		set p_action# (ActionPlay)
		return play
	endif
	vstr nframe="nextFrame"
	setcall compare strcmp(name,nframe)
	if compare=0
		set p_action# (ActionNextFrame)
		return nframe
	endif
	vstr pframe="prevFrame"
	setcall compare strcmp(name,pframe)
	if compare=0
		set p_action# (ActionPreviousFrame)
		return pframe
	endif
	vstr gotos="gotoAndStop"
	setcall compare strcmp(name,gotos)
	if compare=0
		set p_action# (ActionGotoFrame)
		incst p_action
		set p_action# (ActionEndFlag)   #even if it's playing, it will stop, no ActionStop here
		return gotos
	endif
	vstr gotop="gotoAndPlay"
	setcall compare strcmp(name,gotop)
	if compare=0
		set p_action# (ActionGotoFrame)
		incst p_action
		set p_action# (ActionPlay)
		return gotop
	endif
	vstr trace="trace"
	setcall compare strcmp(name,trace)
	if compare=0
		set p_action# (ActionTrace)
		return trace
	endif
	vstr jump="§§goto"
	setcall compare strcmp(name,jump)
	if compare=0
		set p_action# (ActionJump)
		return jump
	endif
	return (NULL)
endfunction

^import "x_pointer" x_pointer 1 #full
^import "x_pointer_touchless" x_pointer_touchless 1 #full
#import "x_pointer_x" x_pointer_x
function action_code_get_pointer(sv p_codepointer)
	sd a;set a x_pointer(p_codepointer#)
	add p_codepointer# : #incst p_codepointer#  #to pass the pointer
	return a
end
function action_code_get_pointer_touchless(sv p_codepointer)
	sd a;set a x_pointer_touchless(p_codepointer#)
	add p_codepointer# : #incst p_codepointer#  #to pass the pointer
	return a
end

function infinite_loop_check(sd codepointer)
	sd test;set test codepointer
	if codepointer#=(ActionGetVariable)
		add codepointer (DWORD)
		sd name
		set name action_code_get_pointer_touchless(#codepointer)
		dataxu compare#1
		set compare action_true_compare(name)
		if compare=0
			if codepointer#=(math_end)
				sub codepointer : #decst codepointer
				call action_code_get_pointer(#codepointer) #must test if debug_x to let the x file in good condition
				add codepointer (DWORD)
				return codepointer
			end
		end
	end
	return test
end
function action_true_compare(ss command)
	callret strcmp("true",command) #int datax compare#1
end
import "is_x" is_x
function forinbreak_check(sd codepointer)
	sd start;set start codepointer
	if codepointer#=(call_action_right)
		add codepointer (DWORD)
		sd name
		sv pname;sv rules
		sd x;set x is_x()
		if x=(FALSE)
			if codepointer#v!=(NULL)
				return start
			end
			set rules codepointer
			add codepointer : #incst codepointer
			set pname codepointer
			set name codepointer#v
			add codepointer : #incst codepointer
			if codepointer#!=(args_end)
				return start
			end
			add codepointer (DWORD)
		else
			set name action_code_get_pointer_touchless(#codepointer)
			if codepointer#!=(args_end)
				return start
			end
			add codepointer (DWORD)
			if codepointer#v!=(NULL)
				return start
			end
			add codepointer : #incst codepointer
		end
		datax compare#1
		set compare strcmp("§§pop",name) #is memcmp unsafe? comparing from last to first?
		if compare=0
			if codepointer#=(compare_action)
				add codepointer (DWORD)
				if codepointer#=(ActionEquals2)
					add codepointer (DWORD)
					if codepointer#=(ActionNot)
						add codepointer (DWORD)
						if codepointer#=(ActionGetVariable)
							add codepointer (DWORD)
							sv nl;set nl codepointer
							set name action_code_get_pointer_touchless(#codepointer)
							set compare action_null_compare(name)
							if compare=0
								if codepointer#=(math_end)
									add codepointer (DWORD)
									if codepointer#=(whileblock_end)
										add codepointer (DWORD)
										if x=(FALSE) #is this hacky?
											call x_pointer(nl)
											if nl#!=name ##fast way to see if is prex
												call x_pointer(pname)
												set rules# pname#
												set pname# (args_end)
												add pname (DWORD)
												set pname# (NULL)
											end
										end
										return codepointer
									end
								end
							end
						end
					end
				end
			end
		end
	end
	return start
end
function action_null_compare(ss command)
	callret strcmp("null",command) #int datax compare#1
end

^import "ret_cont_break" ret_cont_break #full
import "brace_blocks_counter_inc" brace_blocks_counter_inc
^import "cond_blocks_at_index" cond_blocks_at_index 1 #full
import "brace_blocks_counter_dec" brace_blocks_counter_dec
^import "cond_blocks_noerror" cond_blocks_noerror #full
import "debug_phase_code_remove" debug_phase_code_remove
import "flag_noDup_get" flag_noDup_get
import "x_pointer_twice_set" x_pointer_twice_set
import "x_pointer_twice_unset" x_pointer_twice_unset
import "label_resolve" label_resolve

#aftercallimport ebool

^import "cond_blocks" cond_blocks #full
import "debug_phase_code" debug_phase_code
import "debug_definefunction" debug_definefunction
import "debug_concludefunction" debug_concludefunction
import "error" error

^import "memalloc" memalloc 1
function action_code_values_init()
	setcall global.values_container memalloc((totalvalues*action_code_values_unit))
endfunction
function action_code_set(sd value)
	callg action_code_set_ex(value,1)
endfunction
function action_code_set_pointer(sd value)
	callg action_code_set_ex(value,(:/DWORD))  #pointers are referencing static mem, not reallocable actionpool
endfunction
function action_code_set_ex(sd value,sd size)
	sd nr
	setcall nr action_code_values_index()
	sd x
	set x nr#
	sd to=DWORD
	mult to x
	add x size
	if x>=(totalvalues)
		call error("size error at values")
	endif
	sd pointer
	setcall pointer action_code_values()
	add pointer to
	if size=1
		set pointer# value
	else
		set pointer#v^ value
	endelse
	set nr# x
endfunction



#entries write

import "action_push" action_push
import "action_one" action_one
^import "action_member_loop_left" action_member_loop_left 1 #full
^import "action_member_loop_right" action_member_loop_right 1 #full
import "brace_blocks_add_write" brace_blocks_add_write
import "brace_blocks_add_write_offset" brace_blocks_add_write_offset
import "brace_blocks_remove_write" brace_blocks_remove_write
import "brace_blocks_remove_write_ex" brace_blocks_remove_write_ex
import "debug_xlog" debug_xlog
import "debug_xlog_stepin" debug_xlog_stepin
import "debug_xlog_stepout" debug_xlog_stepout

#position
function action__code_row(sd codepointer)
	set global.rcb (ret_cont_break_nothing)   #at definefunction is another collision with this but is not a problem now

	setcall codepointer action__code_row_ex(codepointer)
	call debug_phase_code(codepointer)

	ss p;set p ret_cont_break()
	set p# global.rcb
	return codepointer
endfunction
import "debug_xlog_return" debug_xlog_return
import "brace_blocks_remove_write_jump" brace_blocks_remove_write_jump
#position
function action__code_row_ex(sdu codepointer)
	sd pointer
	set pointer codepointer
	setcall pointer action_code_write_conditions(codepointer)
	if pointer!=codepointer
		return pointer
	endif
	setcall pointer action_code_write_function(codepointer)
	if pointer!=codepointer
		return pointer
	endif
	dataxu attrib#1
	set attrib codepointer#
	if attrib=(ActionReturn)
		add codepointer (DWORD)
		call close_scope_forIn_statements()
		setcall codepointer action_code_right_util(codepointer)
		call action_one((ActionReturn))
		call debug_xlog_return()
		set global.rcb (ret_cont_break_something)
		return codepointer
	endif
	ss p
	if attrib=(if_marker) #block_end
		add codepointer (DWORD)
		if codepointer#=(else_marker)
			set p ret_cont_break()
			if p#=(ret_cont_break_nothing)
				call action_code_else_add()
			else #dead jump after return/continue/break
				call action_code_else_resolve((skip_flag)) #and add the condition because there is number_of_unclosed after block_else_end
			end
			call debug_xlog(codepointer) #here is after stepout from previous if (start of elseif or else)
			add codepointer (DWORD)
		else
			call brace_blocks_remove_write((FALSE))
			call debug_xlog(codepointer) #simple if}[ but can also be the last if from elseif
			set global.is_else_next_mark codepointer
		endelse
		return codepointer
	endif
	if attrib=(function_marker) #block_end
		add codepointer (DWORD)
		call brace_blocks_remove_write((TRUE))
		return codepointer
	end
	if attrib=(block_else_end)
		charx test#1
		if codepointer=global.is_else_next_mark
			set test (FALSE)
		else
			set test (TRUE)
		end
		setcall codepointer action_code_conditions_end(codepointer)
		if test=(TRUE) #only at else, at elseif was done in another way
			call debug_xlog(codepointer) #can be a return inside else. then next code is not 100% from this branch
			#and we are not branching at return/continue/break, will be a logical error to write dead code after that
		end
		return codepointer
	endif
	if attrib=(whileblock_end)
		call brace_blocks_remove_write_jump()
		add codepointer (DWORD)
		call debug_xlog(codepointer) #what when break} ? still can't be from that branch because loop condition is breaking that
		#and at whiletrue? an inner break will also break that branch. yes while(true){var a;break;} is extra but this is not logical
		return codepointer
	endif
	if attrib=(break_flag)
		set p ret_cont_break()
		if p#=(ret_cont_break_nothing) #why? for(var mc_name in drivers_container)return null is ok here but at ffdec an extra break is after return
			call action_code_break()
		end
		set global.rcb (ret_cont_break_break)
		add codepointer (DWORD)
		return codepointer
	endif
	if attrib=(continue_flag)
		call action_code_continue()
		add codepointer (DWORD)
		set global.rcb (ret_cont_break_something)
		return codepointer
	endif
	if attrib=(else_marker)
		call error("ELSE is not linked at this point")
	end
	callret action_code_pack(codepointer)
endfunction
function action_code_pack(sdu codepointer)
	sdu ?attrib
	set attrib codepointer#
	add codepointer (DWORD)
	#
	ss ?is_member=FALSE
	ss ?need_right=TRUE
	ss ?need_pop=FALSE
	if attrib=(ActionSetMember)
		set is_member (TRUE)
	elseif attrib=(ActionDelete)
		set is_member (TRUE)
		set need_right (FALSE)
		set need_pop (TRUE)
	elseif attrib=(ActionDefineLocal2)
		set need_right (FALSE)
	elseif attrib=(ActionDelete2)
		set need_right (FALSE)
		set need_pop (TRUE)
	elseif attrib=(label)
		call label_resolve(codepointer#)
		add codepointer (DWORD)
		return codepointer
	endelseif
	#else is ActionDefineLocal/ActionSetVariable
	sd name;sdu member_codepointer_start
	if is_member=(TRUE)
		set member_codepointer_start codepointer
		setcall codepointer action_member_loop_left(codepointer)
	else
		#definelocal or setvariable or delete2
		set name action_code_get_pointer(#codepointer)
		call action_push((ap_Constant8),name)
	endelse
	if need_right=(TRUE)
		sd ?f
		if codepointer#=(ActionIncrement)
			add codepointer (DWORD)
			set f flag_noDup_get()
			if attrib=(ActionSetVariable)
				call action_code_dupGet_var_if(f,name)
			else
				call action_code_dupGet_member_if(f,member_codepointer_start)
			end
			call action_one((ActionIncrement))
		elseif codepointer#=(ActionDecrement)
			add codepointer (DWORD)
			set f flag_noDup_get()
			if attrib=(ActionSetVariable)
				call action_code_dupGet_var_if(f,name)
			else
				call action_code_dupGet_member_if(f,member_codepointer_start)
			end
			call action_one((ActionDecrement))
		elseif codepointer#=(mixt_equal)
			#+= .. ^= ..
			add codepointer (DWORD)
			sd mixt_op;set mixt_op codepointer#;add codepointer (DWORD)
			set f flag_noDup_get()
			if attrib=(ActionSetVariable)
				call action_code_dupGet_var_if(f,name)
			else
				call action_code_dupGet_member_if(f,member_codepointer_start)
			endelse
			setcall codepointer action_code_right(codepointer)
			call action_one(mixt_op)
		else
			setcall codepointer action_code_right(codepointer)
		endelse
	endif
	call action_one(attrib)
	if need_pop=(TRUE)
		call action_one((ActionPop))
	endif
	return codepointer
endfunction
import "actionrecordheader" actionrecordheader
import "swf_actionblock_add" swf_actionblock_add
function action_code_dupGet_var_if(sd f,sd name)
	if f=(flag_none)
		call action_one((ActionPushDuplicate))
	else
		call action_push((ap_Constant8),name)
	end
	callg action_one((ActionGetVariable))
endfunction
const first_storereg=0
const ActionStoreRegister_length=1
function action_code_dupGet_member()
	#maybe can remember and pushdup/store at M before last but there is extra code, and also watch the debugged file writes then, and store only at non squarebracket, can be inner calls there
	#here with not Pop and two regs? will write more code by our side
	call action_one((ActionStackSwap))
	sd reg=first_storereg
	call actionrecordheader((ActionStoreRegister),(ActionStoreRegister_length))
	call swf_actionblock_add(#reg,(ActionStoreRegister_length))
	call action_one((ActionStackSwap))
	call action_one((ActionPushDuplicate))
	call action_push((ap_RegisterNumber),reg)
	call action_one((ActionStackSwap))
	callg action_one((ActionGetMember))
endfunction
function action_code_dupGet_member_if(sd f,sd member_codepointer)
	if f=(flag_none)
		callg action_code_dupGet_member()
		ret
	end
	call x_pointer_twice_set()
	call action_member_loop_right(member_codepointer)
	call x_pointer_twice_unset()
end

import "brace_blocks_add_write_current" brace_blocks_add_write_current

import "add_dummy_jump" add_dummy_jump
import "resolve_back_jump" resolve_back_jump

import "write_forward_offset" write_forward_offset
#next/same
function action_code_write_conditions(sd codepointer)
	#verify for condition tag
	sd infinite_guard
	sd ?cond;set cond codepointer#
	if cond=(for)
		add codepointer (DWORD)
		if codepointer#!=(for_three)
			sd type;set type codepointer#
			add codepointer (DWORD)
			sd name
			if type=(ActionGetVariable)
				set name action_code_get_pointer(#codepointer)
				call action_get_one(name)
				call action_one((ActionEnumerate2))
			elseif type=(ActionGetMember)
				set codepointer action_member_loop_right(codepointer)
				call action_one((ActionEnumerate2))
			else #deprecated ActionEnumerate
				set name action_code_get_pointer(#codepointer)
				call action_push((ap_Constant8),name)
				call action_one((ActionEnumerate))
			end
			call add_while_top_off((forin_marker))
			#
			sd first_reg=first_storereg
			call actionrecordheader((ActionStoreRegister),(ActionStoreRegister_length))
			call swf_actionblock_add(#first_reg,(ActionStoreRegister_length))
			#
			call action_push((ap_Null))
			call action_one((ActionEquals2))
			#write the jump offset
			call write_ifjump_addTo_braceBlocks()
			#
			call debug_xlog(codepointer) #stepped in for in. is earlier than forin construct end. is right after the ifjump
			#
			sd attr2;set attr2 codepointer#;add codepointer (DWORD)
			if attr2=(ActionSetMember)
				setcall codepointer action_member_loop_left(codepointer) #,(NULL))
			else
				#var or set variable
				sd newname;set newname action_code_get_pointer(#codepointer)
				call action_push((ap_Constant8),newname)
			endelse
			call action_push((ap_RegisterNumber),first_reg)
			call action_one(attr2)
			return codepointer
		endif
		add codepointer (DWORD)
		if codepointer#!=(inter_for);setcall codepointer action_code_pack(codepointer);endif
		add codepointer (DWORD)
		#
		sdu ?sizeOff
		if codepointer#!=(inter_for) #else is JUMP 0
			call add_dummy_jump()
			setcall sizeOff swf_actionblock_get_size()
		end
		#
		call add_while_top_off((while_marker))
		#
		if codepointer#!=(inter_for)
			call debug_xlog_stepin(codepointer) #after jump here is having right part of the for
			setcall codepointer action_code_pack(codepointer)
			sub sizeOff (WORD)
			call write_forward_offset(sizeOff,(TRUE))
			call debug_xlog_stepout(codepointer) #next is 100% from prev branch
		endif
		add codepointer (DWORD)
		#
		set infinite_guard codepointer
		set codepointer infinite_loop_check(codepointer)
		if infinite_guard!=codepointer  ##here must set marker for xlog to know if is & or +
			sd block
			setcall block cond_blocks_noerror()
			sub block (2*DWORD)
			set block# (forwhiletrue_marker)
		end
	elseif cond=(while_marker)
		add codepointer (DWORD)
		set infinite_guard codepointer
		set codepointer infinite_loop_check(codepointer)
		if infinite_guard=codepointer
			sd forinbreak_guard;set forinbreak_guard codepointer
			setcall codepointer forinbreak_check(codepointer)
			if codepointer!=forinbreak_guard
				return codepointer   ##skip this obfuscation from ffdec
			end
			call add_while_top_off((while_marker))
		else
			call add_while_top_off((forwhiletrue_marker))
		end
		#here must set marker for xlog to know if is & or +
	elseif cond=(ActionIf)
		add codepointer (DWORD)
		set infinite_guard codepointer
	else
		return codepointer
	endelse
	if infinite_guard=codepointer
		#using the operations function
		sd ?c2=0
		setcall codepointer action_code_right_util_ex(codepointer,#c2)
		call write_ifjump_withNot(c2)
	end
	#why outside infinite? offset_loop at two whiletrue cannot stay on one branch, is extra coding versus a simple solution
	call debug_xlog(codepointer) #after jump
	#before: .x is also not knowing about that . but now with .xx is not a .x parse

	#return the current pointer
	return codepointer
endfunction
function write_ifjump_withNot(sd ?c2)
	#set to be not for entering the block
	if c2!=(ActionNot)
		call action_one((ActionNot))
	else # was not is not, remove was not
		call debug_phase_code_remove(1,(action_debug_comma))
	end
	#write the jump offset
	call write_ifjump_addTo_braceBlocks()
endfunction
import "debug_xlog_loop" debug_xlog_loop
function add_while_top_off(sd typeOfLoop)
	call debug_xlog_loop()
	call brace_blocks_add_write_current()
	sd block
	setcall block cond_blocks()
	set block# typeOfLoop
	call brace_blocks_counter_inc()
	set block cond_blocks() #also for the error check was: add block (DWORD)
	set block# (top_marker)
	call brace_blocks_counter_inc()
endfunction
import "debug_xlog_break" debug_xlog_break
import "debug_xlog_forin" debug_xlog_forin
const forIn_ifBreak_size=3+1+1+3+2
function action_code_break()
	sd c_block;setcall c_block prepare_space_for_break()
	sd p_type;set p_type c_block;sub p_type (2*DWORD)
	if p_type#=(forin_marker) # forin_marker
		call action_push((ap_Null))
		call action_one((ActionEquals2))
		call write_ifjump()
	else  # while_marker forwhiletrue_marker
		call write_jump(0)
	endelse
	call debug_xlog_break()
	#
	setcall c_block# swf_actionblock_get_size();sub c_block# (WORD)
	#this is a forin end, it is looping at the remaining values until NULL from ActionEnumerate/2 behaviour
	if p_type#=(forin_marker)
		call write_jump((-actionrecord_jump_size-forIn_ifBreak_size))
		call debug_xlog_forin((xlog_forin_break-_0))
	endif
	#
	call brace_blocks_counter_inc()
endfunction
function remove_forIn_stack()
	call action_push((ap_Null))
	call action_one((ActionEquals2))
	call action_one((ActionNot))
	call actionrecordheader((ActionIf),2)
	#minus ActionNot
	sd sz=-1-forIn_ifBreak_size
	call swf_actionblock_add(#sz,2)
	callg debug_xlog_forin((xlog_forin_return-_0))
endfunction
function close_scope_forIn_statements()
    sd nr_of_forIn_statements;setcall nr_of_forIn_statements get_nr_of_forIn_statements()
    while nr_of_forIn_statements>0
        call remove_forIn_stack()
        dec nr_of_forIn_statements
    endwhile
endfunction
function write_jump(sd size)
    call actionrecordheader((ActionJump),(actionjump_contentsize))
    call swf_actionblock_add(#size,(actionjump_contentsize))
endfunction
#cond_blocks top pointer
function prepare_space_for_break()  #here is moving if-elses and at breaks/loopoffset is not comparing but moving them bulk
	sd start;set start cond_blocks_at_index(0)
	sd c_blocks;setcall c_blocks cond_blocks()
	sd copy_cursor;set copy_cursor c_blocks
	while start!=c_blocks
        sub c_blocks (DWORD)
        if c_blocks#=(top_marker)
            add c_blocks (DWORD)
            sd cursor;set cursor copy_cursor;sub cursor (DWORD)
            while copy_cursor!=c_blocks
                set copy_cursor# cursor#
                sub copy_cursor (DWORD)
                sub cursor (DWORD)
            endwhile
            return c_blocks
        endif
	endwhile
    call error("it is not the right place for Break")
endfunction
function write_ifjump_addTo_braceBlocks()
    call write_ifjump()
    call brace_blocks_add_write()
endfunction
function write_ifjump()
    call actionrecordheader((ActionIf),2)
    data dummyoffset=0
    call swf_actionblock_add(#dummyoffset,2)
endfunction

function action_code_continue()
	sd start;set start cond_blocks_at_index(0)
	sd c_blocks;set c_blocks cond_blocks_noerror()
	while start!=c_blocks
		sub c_blocks (DWORD)
		if c_blocks#=(top_marker)
			#the loop type and to the offset to jump from here
			sub c_blocks (2*DWORD)
			sd off_to_jump;set off_to_jump c_blocks#
			#
			call add_dummy_jump()
			call resolve_back_jump(off_to_jump)
			ret
		endif
	endwhile
	call error("Continue without a loop error")
endfunction

function action_code_else_add()
    #write dummy jump
    call actionrecordheader((ActionJump),(actionjump_contentsize))
    sd dummyjump
    call swf_actionblock_add(#dummyjump,(actionjump_contentsize))
	call action_code_else_resolve((no_flag))
end
function action_code_else_resolve(sd flag)
	#end previous if
	call brace_blocks_remove_write((FALSE))
	#add current offset
	call brace_blocks_add_write_offset((smallbackjump),flag)
endfunction
function action_code_conditions_end(sd codepointer)
	add codepointer (DWORD)
	sd ?number_of_unclosed
	set number_of_unclosed codepointer#
	add codepointer (DWORD)
	while number_of_unclosed>^0
		call brace_blocks_remove_write_ex()
		dec number_of_unclosed
	endwhile
	return codepointer
endfunction

#codepointer
function action_code_write_function(sd codepointer)
	sd pointer
	setcall pointer action_definefunction(codepointer)
	if pointer!=codepointer
		return pointer
	endif
	if codepointer#!=(call_action_left)
		return codepointer
	endif
	ss ?want_return=FALSE
	setcall codepointer action_code_write_function_call(codepointer,#want_return)
	if want_return=(FALSE)  #can be modified inside
		call action_one((ActionPop))
	endif
	return codepointer
endfunction

import "debug_xlog_call" debug_xlog_call
#codepointer
function action_code_write_function_call(sv codepointer,ss pwant_return)
	add codepointer (DWORD)
	sd pointer
	setcall pointer action_code_write_builtin_function(codepointer,pwant_return)
	if pointer!=codepointer
		return pointer
	endif
	sd member
	setcall codepointer action_code_new_or_call(codepointer,#member)
	if member=(no_pointer)
		call action_one((ActionCallFunction))
	else
		call action_one((ActionCallMethod))
	endelse
	call debug_xlog_call()
	return codepointer
endfunction
#codepointer
function action_code_write_builtin_function(sv codepointer,ss pwant_return)
	sv pointer
	set pointer codepointer
	if pointer#!=(no_pointer)
		#no builtin at members
		return codepointer
	endif
	add pointer :  #to pass the pointer
	#
	sd cursor
	sd was;set was pointer# ;#cannot set later, trace('b') is ok but trace(eval('b')) will write to .x and at next x run will wrong the pointer
	setcall cursor action_code_write_builtin_set(pointer,pwant_return)
	if cursor=pointer
		set pointer# was
		return codepointer
	endif
	#moved above: call x_pointer_x(pointer) #in case is to .x, must trim pointer
	return cursor
endfunction
import "debug_xlog_unimplemented" debug_xlog_unimplemented
import "goto_add" goto_add
#codepointer
function action_code_write_builtin_set(sv codepointer,ss pwant_return)
	ss name
	#these acts must stay on stack, can be builtin inside builtin
	sd ?actsdata#2;sd acts^actsdata
	set name action_code_write_builtin_names(codepointer,acts)
	if name!=(NULL)
		sd ?act;set act acts#d
		sd test;set test codepointer
		add test :   #to pass the pointer
		if test#!=(args_end)
			if act!=(ActionGotoFrame)
				ss addr
				if act=(ActionJump)
					if test#=(ActionGetVariable)
						add test (DWORD)
						set addr x_pointer(test)
						add test :
						if test#=(math_end)
							add test (DWORD)
						else
							call error("simple address expected at goto")
						end
					else
						call error("ActionGetVariable expected at goto")
					end
				else
					if act=(ActionTrace)
						if pwant_return#=(TRUE)  #same like at gotoAndStop
							return codepointer
						endif
					end
					setcall test action_code_right_util(test)
				end
				if test#=(args_end)
					if act=(ActionJump)
						sdu ?addres ;#at ffdec are only short addresses? anyway, allow full address
						sd ?scan;set scan sscanf(addr,"addr%x",#addres)
						if scan=1
							call debug_xlog_unimplemented() #must branch at label and for forward also writeJump, for forward like elseClosing, for backward another way, at the moment label is 100% ignored
							sdu ?offset;set offset swf_actionblock_get_size()
							add offset (actionrecordheader_size)
							set addres goto_add(addres,offset)
							call write_jump(addres)
							set pwant_return# (TRUE)   #no ActionPop required, if is at right side can error here if wanting
							set global.rcb (ret_cont_break_something)
						else
							call error("goto addr sscanf error")
						end
					else
						call action_one(act)
						if act=(ActionTrace)
							set pwant_return# (TRUE)  #to skip pop
						endif
					end
					add test (DWORD)
					return test
				endif
				#this is not ok but is lazy and mc overrides are not a must for builtin functions
				vstr builtin="builtin function expects at most one parameter"
				call error(builtin)
			endif
			#here is another format, if the first is not unsigned 16 then call movie clip function instead of actiongotoframe
			if test#=(ap_Integer)
				add test (DWORD)
				if test#<=^0xffFF #attention at negative numbers, ignoring gotoandstop mc behaviour
					sd ?val;set val test#
					add test (DWORD)
					if test#=(math_end)
						add test (DWORD)
						if test#=(args_end)
							if pwant_return#=(FALSE)   #can be in a ...=gotoAndStop+... attribution and add extra code there
								#                      because ActionGotoFrame is not pushing a return value
								call actionrecordheader(act,(WORD))
								dec val      ##gotoAnd..(1) = GotoFrame 0
								call swf_actionblock_add(#val,(WORD))
								set pwant_return# (TRUE)   #no ActionPop required
								#
								sd ?act2
								incst acts
								set act2 acts#d
								if act2!=(ActionEndFlag)
									#ActionPlay
									call swf_actionblock_add(#act2,(BYTE))
								endif
								#
								add test (DWORD)
								return test
							endif
						endif
					endif
				endif
			endif
		elseif act<=(ActionStop)  #this is skipping 1,2,3 but there are no actions in the model
			if pwant_return#=(FALSE)  #same like at gotoAndStop
				call action_one(act)
				set pwant_return# (TRUE)  #to skip pop
				add test (DWORD)
				return test
			endif
		endelseif
	endif
	return codepointer
endfunction
^import "x_call" x_call 3 #full
^import "debug_x_preexpand" debug_x_preexpand 1 #full
^import "action_caller" action_caller 3
#codepointer
function action_code_new_or_call(sv codepointer,sv pmember)
	sd fname
	sd mathpointer;set mathpointer codepointer
	set codepointer x_call(pmember,#fname,codepointer)
	if codepointer=mathpointer
		set pmember# debug_x_preexpand(#codepointer)
		setcall codepointer action_caller(pmember#,#fname,codepointer)
	end
	call action_push((ap_Constant8),fname)
	return codepointer
endfunction
#codepointer
function action_code_right(sd codepointer)
    sd pointer
    setcall pointer action_definefunction(codepointer)
    if pointer!=codepointer
        return pointer
    endif
	callret action_code_right_util(codepointer)
endfunction
#codepointer
function action_code_right_util(sd codepointer)
	callret action_code_right_util_ex(codepointer,(NULL))
end
import "actionpush" actionpush
function action_code_right_util_ex(sd codepointer,sd outside_compare2)
	if codepointer#=(new_action)
		add codepointer (DWORD)
		sd member
		setcall codepointer action_code_new_or_call(codepointer,#member)
		if member=(no_pointer)
			call action_one((ActionNewObject))
		else
			call action_one((ActionNewMethod))
		endelse
		return codepointer
	endif
	sd ?compare_op_1
	sd ?compare_op_2
	setcall codepointer action_code_right_number(codepointer)
	sd ?was_operation=no_action
	while codepointer#!=(math_end)
		sd ?operation
		set operation codepointer#
		add codepointer (DWORD)
		if operation=(compare_action)
			set compare_op_1 codepointer#
			add codepointer (DWORD)
			set compare_op_2 codepointer#
			add codepointer (DWORD)
		elseif operation=(ifElse_start)
			#can be a simple get for a bool and still working here. if was_operation=(no_action);call error("inline ifelse doesn't know what to ask")
			if was_operation=(compare_action)   #needed to optimize ActionNot
				call write_ifjump_withNot(compare_op_2)
			else
				call write_ifjump_withNot(0)
			end
			call debug_xlog_stepin(codepointer) #after jump, is stepping in ?: and will return and continue the branch
			setcall codepointer action_code_right_util(codepointer)
			call action_code_else_add()
			call debug_xlog(codepointer) #at start of second part and after.stepout, but if before was a return? this is a new branch
			setcall codepointer action_code_right_util(codepointer)
			call actionpush() # must release example 2:[jump 0]3 , next will correct jump 0
			call brace_blocks_remove_write((TRUE))
			call debug_xlog_stepout(codepointer) #and continue after :]|
			return codepointer
		elseif operation=(ActionNot)
			call action_one((ActionNot))
			set was_operation (ActionNot)
			continue
		endelseif
		setcall codepointer action_code_right_number(codepointer)
		if operation!=(compare_action)
			call action_one(operation)
		else
			call action_one(compare_op_1)
			if compare_op_2!=0;call action_one(compare_op_2);endif
		endelse
		set was_operation operation
	endwhile
	if outside_compare2!=(NULL)
		if was_operation=(compare_action)
			set outside_compare2# compare_op_2
		elseif was_operation=(ActionNot)
			set outside_compare2# (ActionNot)
		end
	end
	add codepointer (DWORD)
	return codepointer
endfunction

#codepointer
function action_code_right_number(sd codepointer)
	if codepointer#=(parenthesis_start)
		add codepointer (DWORD)
		callret action_code_right_util(codepointer)
	endif
	if codepointer#=(call_action_right)
		callret action_code_write_function_call(codepointer,(TRUE))
	endif
	sd ?attrib;sd var
	set attrib codepointer#
	add codepointer (DWORD)
	if attrib=(ActionGetMember)
		setcall codepointer action_member_loop_right(codepointer)
	else
		if attrib=(ActionGetVariable)
			set var action_code_get_pointer(#codepointer)
			call action_one_command(var)
		elseif attrib=(ap_Double)
			sd ?high;set high codepointer#;add codepointer (DWORD)
			call action_push(attrib,high,codepointer#)
			add codepointer (DWORD)
		elseif attrib=(ap_Integer)
			call action_push(attrib,codepointer#)
			add codepointer (DWORD)
		else
			#ap_Constant8
			set var action_code_get_pointer(#codepointer)
			call action_push(attrib,var)
		endelse
	endelse
	return codepointer
endfunction
function action_one_command(ss command)
	datax compare#1
	#
	setcall compare action_null_compare(command)
	if compare=0
		callg action_push((ap_Null))
		ret
	endif
	setcall compare strcmp("undefined",command)
	if compare=0
		callg action_push((ap_Undefined))
		ret
	endif
	set compare action_true_compare(command)
	if compare=0
		callg action_push((ap_Boolean),1)
		ret
	endif
	setcall compare strcmp("false",command)
	if compare=0
		callg action_push((ap_Boolean),0)
		ret
	endif
	callg action_get_one(command)
endfunction
function action_get_one(ss variable)
    call action_push((ap_Constant8),variable)
    callg action_one((ActionGetVariable))
endfunction

import "dtitles_func" dtitles_func
#codepointer
function action_definefunction(sd codepointer)
	if codepointer#!=(function_action)
		return codepointer
	endif
	add codepointer (DWORD)

	sd debug_related#3  #for debug file offset and codeSize pointer and line offset, must be recursive too
	setcall codepointer action_deffunction(codepointer,#debug_related)

	#this on same row with dummy at .log
	call debug_xlog_stepin(codepointer) #after define function tag
	#all previous codes must pe catched at this phase, this place for this function is tested, example: function(){\nvar a
	call debug_phase_code(codepointer)

	#a function marker for return and for..in case
	sd block;setcall block cond_blocks()
	set block# (brace_blocks_function)
	call brace_blocks_counter_inc()
	#
	call brace_blocks_add_write()
	#
	sd ?index_atstart
	setcall index_atstart brace_blocks_counter()
	sd ?index_current=0xffFFffFF
	#
	call dtitles_func()
	while index_atstart<=^index_current
		setcall codepointer action__code_row(codepointer)
		setcall index_current brace_blocks_counter()
	endwhile
	#close function marker for return and for..in case
	call brace_blocks_counter_dec()
	#for debug log codeSize
	call debug_concludefunction(#debug_related)

	call debug_xlog_stepout(codepointer) #step out and back to same branch . oaalt need to recon rows with only one |. \ is not while read parsing right in oaalt
	return codepointer
endfunction
#codepointer
function action_deffunction(sv codepointer,sv debug_related)
	ss fn_name
	set fn_name action_code_get_pointer(#codepointer)

	sv ?fn_name_size
	setcall fn_name_size strlen(fn_name)
	inc fn_name_size ## it cannot be for len_of, it was reallocated at comments remover
	#
	svu ?fn_size
	set fn_size fn_name_size
	const NumParams_size=2
	const codeSize_size=2
	add fn_size (NumParams_size+codeSize_size)
	#
	sd ?NumParams=0 #is ui16, will break at the check if is a problem here
	sv args
	set args codepointer
	sd arg
	while codepointer#!=(no_pointer)  #first time get for ACTIONRECORDHEADER.Length and NumParams
		set arg action_code_get_pointer_touchless(#codepointer)
		addcall fn_size strlen(arg)
		inc fn_size
		inc NumParams
	endwhile
	add codepointer :  #to pass the pointer
	#
	if fn_size>^(maxuint16)
		call error("error at define function")
	endif
	call actionrecordheader((ActionDefineFunction),fn_size)
	call swf_actionblock_add(fn_name,fn_name_size)
	call swf_actionblock_add(#NumParams,(NumParams_size))
	#
	sd ?wr_size
	while args#!=(no_pointer)  #second time write to swf
		set arg action_code_get_pointer(#args)
		setcall wr_size strlen(arg)
		inc wr_size
		call swf_actionblock_add(arg,wr_size)
	endwhile
	#get reg, not depending on brace blocks because } is closed in the loop there, for debug
	call debug_definefunction(debug_related)
	#
	data dummyoffset=0
	call swf_actionblock_add(#dummyoffset,(WORD))  #codeSize
	#
	return codepointer
endfunction

entryraw global()
