/* ChipMunch - Move the first 512K of chip memory after the rest - Bryan Ford */

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/execbase.h>
#include <dos/dosextens.h>
#include <workbench/startup.h>
#include <proto/exec.h>
#include <bry/macros.h>

struct ExecBase *SysBase;

struct Process *proc;
	
int __saveds entry(void)
	{
	struct MemHeader *mh, *nmh;
	struct MemChunk *mc, *nmc;
	struct WBStartup *wbs = 0L;
	int ret = 10;
		
		SysBase = *((struct ExecBase**)4);
		proc = FindTask(0L);
		
		if(!(proc->pr_CLI))
			{
				WaitPort(&proc->pr_MsgPort);
				wbs = GetMsg(&proc->pr_MsgPort);
			}
		
		Forbid();
		for(mh = SysBase->MemList.lh_Head;;mh = mh->mh_Node.ln_Succ)
			{
				if(!(mh->mh_Node.ln_Succ))
					break;
				if((mh->mh_Lower < (void*)0x40000) && (mh->mh_Upper > (void*)0x80000) && (mh->mh_Attributes & MEMF_CHIP))
					{
						if(!(nmh = AllocAbs(sizeof(*nmh),(void*)0x80000)))
							break;
						memset(nmh,0,sizeof(*nmh));
						nmh->mh_Node.ln_Type = NT_MEMORY;
						nmh->mh_Node.ln_Pri = mh->mh_Node.ln_Pri+1;
						nmh->mh_Attributes = mh->mh_Attributes;
						for(mc = mh->mh_First;;mc = nmc)
							{
								if(!mc)
									break;
								if((long)(nmc = mc->mc_Next) > (long)nmh)
									{
										mc->mc_Next = 0L;
										nmh->mh_First = nmc;
										nmh->mh_Upper = mh->mh_Upper;
										mh->mh_Upper = nmh;
										nmh->mh_Lower = nmh+1;
										for(mc = nmc;mc;mc = mc->mc_Next)
											{
												mh->mh_Free -= mc->mc_Bytes;
												nmh->mh_Free += mc->mc_Bytes;
											}
										Insert(&SysBase->MemList,nmh,mh->mh_Node.ln_Pred->ln_Pred ? mh->mh_Node.ln_Pred : 0L);
										ret = 0;
										break;
									}
							}
						break;
					}
			}
		Permit();
		
		if(wbs)
			{
				Forbid();
				ReplyMsg(wbs);
			}
		return(ret);
	}