GetGameDataPointer:
	add #result, #1, sGameData
	ifeq #savefile, 1, .done
	add #result, #1, sBackupGameData
.done
	return

EventFlagPatch:
	; #1: list of event flag numbers, terminated by -1
	; #2: action (0: clear, 1: set, 2: toggle)
	set #address, #1
	set #1, EVENT_FLAGS_OFFSET
	call GetGameDataPointer
	seek #result
	jump .handle_loop
.loop
	push #2
	call FlagAction
	pop #2
.handle_loop
	gethalfwordinc #1, #address
	ifne #1, 0xffff, .loop
	return

EventFlagCheck:
	; #1: list of event flag numbers, terminated by -1
	; #2: kind of check (0: any, nonzero: all)
	jumpz #2, .ok
	set #2, 1
.ok
	set #address, #1
	set #1, EVENT_FLAGS_OFFSET
	call GetGameDataPointer
	seek #result
	set #result, #2
	jump .handle_loop
.loop
	push #2
	set #2, -1
	call FlagAction
	pop #2
	ifne #result, #2, .done
.handle_loop
	gethalfwordinc #1, #address
	ifne #1, 0xffff, .loop
.done
	return

FixSavefileChecksum:
	set #1, #zero
	call GetGameDataPointer
	seek #result
	call CalculateSavefileChecksum
	seek sChecksum
	ifeq #savefile, 1, .ok
	seek sBackupChecksum
.ok
	writehalfword #result
	subtract #1, sExtraData, sGameData
	call GetGameDataPointer
	seek #result
	call CalculateExtraChecksum
	seek sExtraChecksum
	ifeq #savefile, 1, .extra_ok
	seek sBackupExtraChecksum
.extra_ok
	writehalfword #result
	return

ClearSingleEventFlag:
	push #1
	set #1, EVENT_FLAGS_OFFSET
	call GetGameDataPointer
	seek #result
	pop #1
	set #2, #zero
	call FlagAction
	jump FixSavefileChecksum

CountEventFlags:
	push #a
	push #b
	set #a, #1
	set #1, EVENT_FLAGS_OFFSET
	call GetGameDataPointer
	seek #result
	set #b, #zero
.loop
	gethalfwordinc #1, #a
	ifeq #1, 0xffff, .done
	set #2, -1
	call FlagAction
	jumpz #result, .loop
	increment #b
	jump .loop
.done
	set #result, #b
	pop #b
	pop #a
	return

FixExperienceCurves:
	; #1: list of curves (mon, old curve, new curve; 0 ends)
	push #address
	set #address, #1
	set #1, .callback
	call ApplyPartyPatches
	pop #address
	return

.callback
	seek #1
	readbyte #temp
	push #address
.loop
	getbyteinc #2, #address
	jumpz #2, .done
	ifeq #2, #temp, .patch
	increment #address
	increment #address
	jump .loop
.patch
	seekfwd 7
	getbyteinc #2, #address
	getbyte #3, #address
	readbyte #1
	shiftleft #1, 8
	readbyte #temp
	or #1, #temp
	shiftleft #1, 8
	readbyte #temp
	or #1, #temp
	call RecalculateExperience
	set #temp, 0xff
	and #3, #result, #temp
	shiftright #result, 8
	and #2, #result, #temp
	shiftright #1, #result, 8
	seekback 3
	writebyte #1
	writebyte #2
	writebyte #3
.done
	pop #address
	return

ApplyPartyPatches:
	; #1: callback, will receive party pointer, nickname pointer, OT pointer, location (0 = party, 1 = box, 2 = daycare)
	push #e
	push #d
	push #c
	push #b
	push #a
	set #a, #1
	set #1, PARTY_COUNT_OFFSET
	call GetGameDataPointer
	seek #result
	readbyte #temp
	add #1, #result, 8
	add #2, #result, 0x16a
	add #3, #result, 0x128
	set #4, #zero
	callnz #temp, .apply_to_list
	set #1, DAYCARE_MAN_OFFSET
	call .daycare_mon
	set #1, DAYCARE_LADY_OFFSET
	call .daycare_mon
	set #b, sBox1
	call .boxes
	set #b, sBox8
	call .boxes
	pop #a
	pop #b
	pop #c
	pop #d
	pop #e
	return

.boxes
	set #c, 7
.box_loop
	seek #b
	readbyte #temp
	add #1, #b, 22
	add #2, #b, 882
	add #3, #b, 662
	set #4, 1
	callnz #temp, .apply_to_list
	add #b, BOX_SIZE
	decrement #c
	jumpnz #c, .box_loop
	return

.daycare_mon
	call GetGameDataPointer
	seek #result
	readbyte #temp
	and #temp, 1
	retz #temp
	add #1, #result, 23
	add #2, #result, 1
	add #3, #result, 12
	set #4, 2
.apply_to_list
	set #d, #temp
	set #e, #4
.loop
	push #3
	push #2
	push #1
	set #4, #e
	call #a
	pop #1
	set #4, PARTYMON_STRUCT_LENGTH
	jumpz #e, .length_OK
	set #4, BOXMON_STRUCT_LENGTH
.length_OK
	add #1, #4
	pop #2
	add #2, NAME_LENGTH
	pop #3
	add #3, NAME_LENGTH
	decrement #d
	jumpnz #d, .loop
	return

ShiftSaveData:
	; #1: count, #2: amount
	retz #1
	seekfwd #2
	getfilebyte #temp
	seekback #2
	writebyte #temp
	decrement #1
	jump ShiftSaveData
