English Amiga Board


Go Back   English Amiga Board > Coders > Coders. Language > Coders. C/C++

 
 
Thread Tools
Old 25 November 2018, 00:46   #1
Warty
Registered User
 
Join Date: Aug 2018
Location: Minneapolis, USA
Posts: 301
Finding start and end of my program's memory?

Hi folks, I have an Amiga C newb question I would appreciate some help with.

I'm porting a UNIX game from forever-ago to the Amiga. I was trying to port it to the CBM 700 machines, but turns out it needed 128k, and I haven't figured out how to get past the 8 bit banking stuff. Anyway, the game runs and everything, but in looking at what save game/restore game did, I think they just saved off a chunk of the computer's memory as raw data, and then read it back in. That's how the top 10 scores work, for example (simpler, as it puts it into a struct, so easy to get start/end addresses).

For saving the game, it uses sbrk(0) to get the end of the program's memory. sbrk() is part of <unistd.h>, which doesn't have an Amiga counterpart.
https://linux.die.net/man/2/sbrk

It uses the address of a certain variable as the start point. I'm not entirely sure how it determined, in the original UNIX build, that that variable was the first one to be stored in memory. I don't have the make scripts but I guess it just called that file first.

I'm not having good luck googling this. Is there a clever Amiga way to find out the end of the program's memory?

I do have some malloc going on, so I don't think I can try to cleverly locate one variable as the last thing allocated, and use that.
Warty is offline  
Old 25 November 2018, 01:19   #2
phx
Natteravn
 
phx's Avatar
 
Join Date: Nov 2009
Location: Herford / Germany
Posts: 2,496
Quote:
Originally Posted by Warty View Post
I'm not having good luck googling this. Is there a clever Amiga way to find out the end of the program's memory?

I do have some malloc going on, so I don't think I can try to cleverly locate one variable as the last thing allocated, and use that.
No. You can't. Amiga ist not Unix. All processes share the same memory and memory allocations may happen at many different locations.
phx is offline  
Old 25 November 2018, 02:02   #3
Don_Adan
Registered User
 
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 55
Posts: 1,960
If I understand correctly what you need, you can deabsolute all (or only one?) address when program is saving, and reallocate these addresses when save game is loading. Some Amiga games used this method. Of course you must known which pointers must be de/reallocated.
Don_Adan is offline  
Old 25 November 2018, 02:20   #4
Warty
Registered User
 
Join Date: Aug 2018
Location: Minneapolis, USA
Posts: 301
Thanks for quick answers. It helps, if only to stop me from wasting more time in going down this rabbit-hole.

I believe "bugger!" sums up my current feelings.

Well, looks like I'm going to get intimately acquainted with the 500 structs and variables that need to be saved off and reloaded in order to 'save game'.

Warty
Warty is offline  
Old 25 November 2018, 11:09   #5
Samurai_Crow
Total Chaos forever!
 
Samurai_Crow's Avatar
 
Join Date: Aug 2007
Location: Waterville, MN, USA
Age: 49
Posts: 2,186
If the structs and variables are allocated in the same order each time, I'd write a custom allocator that pads the beginning of the structure with SIZEOF *BYTE[] (which should be 4 bytes on current Amiga models) so that you can add a singly linked list node to the structs at allocation time.

All you have to do is either replace all calls to the malloc family of functions with macro calls or write a link library that diverts malloc and friends that links in before the C runtime libraries do.
Samurai_Crow is offline  
Old 28 November 2018, 03:41   #6
Warty
Registered User
 
Join Date: Aug 2018
Location: Minneapolis, USA
Posts: 301
I think I have divined the relevant chunks of data that would need storing and restoring. Let me list out the types, and ask for advice.

3 screen buffers worth of 80x23 chars. no problem.
Code:
unsigned char bufPlayer[23][80] = {0};	/* maintain a 1k block of memory as a memory map to the player's version of the map */
unsigned char bufMonsters[23][80] = {0};	/* maintain a 1k block of memory as a memory map to the position of all monsters */
unsigned char bufMaster[23][80] = {0};	/* maintain a 1k block of memory as a memory map to the master game map */
unsigned char *pBufPlayer;	/* pointer to a 1k block of memory as a memory map to the player's map of the floor */
unsigned char *pBufMonsters;	/* pointer to a 1k block of memory as a memory map to the position of all monsters */
unsigned char *pBufMaster;	/* pointer to a 1k block of memory as a memory map to the master map of the floor */
A couple smaller blocks of chars, no problem:
Code:
char whoami[80];	/* Name of player */
char fruit[80];		/* Favorite fruit */
Some ints, no problems:
Code:
int quiet;	/* Number of quiet turns */
int purse;	/* How much gold the rogue has */
int ntraps;	/* Number of traps on this level */
int no_move;	/* Number of turns held in place */
int no_food;	/* Number of levels without food */
int no_command;	/* Number of turns asleep */
int max_level;	/* Deepest player has gone */
int max_hp;	/* Player's max hit points */
int level;	/* What level rogue is on */
int lastscore;	/* Score before this turn */
int inpack;	/* Number of things in pack */
int hungry_state;	/* How hungry is he */
int group;	/* Current group number */
int fung_hit;	/* Number of time fungi has hit */
int food_left;	/* Amount of food in hero's stomach */
bool notify;	/* True if player wants to know */
bool amulet;	/* He found the amulet */
bool after;	/* True if we want after daemons */
array of chars, no problem:
Code:
bool ws_know[MAXSTICKS];	/* Does he know what a stick does */
bool s_know[MAXSCROLLS];	/* Does he know what a scroll does */
bool r_know[MAXRINGS];	/* Does he know what a ring does */
bool p_know[MAXPOTIONS];	/* Does he know what a potion does */
Up to this point, I'm wondering if it wouldn't be an idea to simply get out a big block of memory, since the size is fixed, and make my own pointers to within this block, kind of manually. Then I save the whole block to save game, and to restore a game read the data back into that spot.

But it gets fuzzy for me once I get past the simpler stuff:

Some structs with 2 int members (worst case, I unpack these and then repack the structs).
Code:
coord oldpos;	/* Position before last look() call */
coord delta;	/* Change indicated to get_dir() */
coord ch_ret;	/* Where chasing takes you */
Pointer arrays of type char. Hmm. I guess I could do the pointer assigns myself, to the big block of memory.
Code:
char *ws_type[MAXSTICKS];	/* Is it a wand or a staff */
char *ws_made[MAXSTICKS];	/* What sticks are made of */
char *ws_guess[MAXSTICKS];	/* Players guess at what wand is */
char *w_names[MAXWEAPONS];	/* Names of the various weapons */
char *s_names[MAXSCROLLS];	/* Names of the scrolls */
char *s_guess[MAXSCROLLS];	/* Players guess at what scroll is */
char *r_stones[MAXRINGS];	/* Stone settings of the rings */
char *r_guess[MAXRINGS];	/* Players guess at what ring is */
char *p_guess[MAXPOTIONS];	/* Players guess at what potion is */
char *p_colors[MAXPOTIONS];	/* Colors of the potions */
char *a_names[MAXARMORS];	/* Names of armor types */

This is where I start to think ooh, this is going to be hard for me to do the allocations myself. Many of these have pointers that get allocated, etc.
Code:
struct trap traps[MAXTRAPS];
struct thing player;	/* The rogue */
struct stats max_stats;	/* The maximum for the player */
struct room rooms[MAXROOMS];	/* One for each room -- A level */
struct room *oldrp;	/* Roomin(&oldpos) */
struct object *cur_ring[];	/* Which rings are being worn */
struct object *cur_armor;	/* What a well dresssed rogue wears */
struct magic_item p_magic[MAXPOTIONS];	/* Names and chances for potions */
struct linked_list *mlist;	/* List of monsters on the level */
struct linked_list *lvl_obj;	/* List of objects on this level */
struct delayed_action d_list[MAXDAEMONS];

I can do this with what I might call the "brute force" method: preceding through each of these variables, pushing them into a kind of stack in temp memory, saving out, freeing the temp memory, and doing the reverse on restore. But would a more experienced C programmer have a smart way to do it? This whole thing is basically a learning experience for me, so a brute force attack is something I'll do if I have to do to finish the project, but I'd rather spend the time (even if same amount of time or more) learning a better technique.

Ideas so far:
1. alloc a big block of memory equal to the total I'll need (this is a known quantity, and doesn't change from game to game). Dole out the contents of this bit by bit as each variable is initialized. Basically get rid of global variables and replace them with pointers to slots internal to the superblock I allocated. Saving and restoring is then as simple as saving out that block, and reading it back in (if same session), or reading it back in to wherever it is in a new session. Either way, since it's one allocation as far as Amiga is concerned, it will be contiguous.

2. brute force. Use the variables exactly as I do now, but for save, allocate a single big chunk of memory, iterate through all the variables, pushing them into it, saving that chunk off, freeing the chunk. Do opposite on restore.

3. Get really smart idea here and do that instead.

I haven't measured yet how much memory is needed, but I think it's 10k or less, so even on an unexpanded A1000, temporarily allocating another 10k of memory shouldn't be a problem.
Warty is offline  
Old 28 November 2018, 07:50   #7
Don_Adan
Registered User
 
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 55
Posts: 1,960
For me exist 4 options, for relloc absolute save pointers.
1. Alloc extra memory for one full save, copy save game to this memory, deabsolute all necessary pointers, save this extra memory buffer as normal save. When saved game is loaded relloc all necessary pointers.
2. Deabsolute all necessary pointers on original save data, save this memory as normal save, later rellocate all deabsoluted pointers, continue playing game. When saved game is loaded relloc all necessary pointers
3. Add one extra longword to saved file. Store/place in this extra longword origin of saved game address. Save as saved game original save plus 4 bytes. When game is loading use this extra longword to deabsolute/rellocate all necessary pointers (included origin pointers too).
4. Modify using by game all game pointers from absolute memory to normal offsets. Nothing more is necessary for save/load game.
Which is the best/easiest i dont know, i dont wrote programs in C.
Don_Adan is offline  
Old 28 November 2018, 09:22   #8
meynaf
son of 68k
 
meynaf's Avatar
 
Join Date: Nov 2007
Location: Lyon / France
Age: 51
Posts: 5,323
Several times i've seen saved games containing irrelevant data, things that actually never changed.
So first thing i would do is checking, for each variable, if it really needs to be saved. Object names, for example, typically don't. So find out whatever is constant from game to game, and remove that out of the save list.

If you have lots of strings that are constant, create an array of them and replace pointers to them by indexes into that array. Then you only have to save these indexes, not the strings themselves and it makes your life easier.

Anyway, the amount of work to do depends on how much "clean" you want your code to be...
meynaf is offline  
Old 03 January 2019, 11:24   #9
bebbo
bye
 
Join Date: Jun 2016
Location: Some / Where
Posts: 680
here's another more or less useful approach:

- write your own malloc
- allocate one memory block for your malloc with a fixed address, large enough to be sufficient for the programs life time.
- now your malloc knows the start plus the used size.

simply save and load that area.

cons:
- your program won't start if that memory area isn't available...

on a system with mmu you can fix this, by allocating an address outside of RAM/ROM and map real memory to that location.
bebbo is offline  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
Tracking a game/program's memory usage clebin Coders. General 5 01 December 2017 10:46
Disassembling - finding a game start address SparkyNZ Coders. Asm / Hardware 12 05 March 2015 12:36
Best program to test memory? Mustangjeff support.Hardware 5 05 October 2012 07:43
Strange problem with cyclone not honouring start/end track? BarryB support.Apps 2 20 November 2011 01:15
Finding a bad memory chip ehbowen support.Hardware 0 17 November 2007 23:55

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 17:29.

Top

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Page generated in 0.20901 seconds with 15 queries