mirror of
https://github.com/autc04/Retro68.git
synced 2024-12-22 04:30:03 +00:00
8f68ffd203
Specify parameters for all C functions. Not specifying parameters is the same as specifying "void" in C++ and in C23 and later but that's not the case in C prior to C23. Compile C files with the same warnings as C++ files, additionally making the strict prototypes warning an error to catch such problems in the future. This commit isn't intended to address all the other warnings now being emitted.
200 lines
4.0 KiB
C
200 lines
4.0 KiB
C
/*
|
|
Copyright 2018 Wolfgang Thaller.
|
|
|
|
This file is part of Retro68.
|
|
|
|
Retro68 is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Retro68 is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Retro68. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/*
|
|
* The following is a simple "Hello, world." MPW tool.
|
|
*
|
|
* Everything here should move to a library,
|
|
* so this can be written using a standard printf.
|
|
*
|
|
* The basic idea is that MPW makes the low-memory
|
|
* global at 0x316 point to a special struct that
|
|
* contains pointers to callbacks for doing standard
|
|
* input and output (and a few other things).
|
|
* The struct also contains argc and argv,
|
|
* as well as a place to store the tool's exit code.
|
|
* The tool must exit by returning from main() rather
|
|
* than by calling ExitToShell.
|
|
*/
|
|
|
|
#include <MacTypes.h>
|
|
#include <setjmp.h>
|
|
#include <stdlib.h>
|
|
#include <MixedMode.h>
|
|
|
|
#if !TARGET_CPU_PPC
|
|
#include <Retro68Runtime.h>
|
|
#endif
|
|
|
|
#pragma pack (push, 2)
|
|
|
|
struct MPWFile;
|
|
|
|
struct fsysTable
|
|
{
|
|
void (*quit)(void);
|
|
void (*access)(void);
|
|
void (*close)(struct MPWFile *);
|
|
void (*read)(struct MPWFile *);
|
|
void (*write)(struct MPWFile *);
|
|
void (*ioctl)(void);
|
|
};
|
|
|
|
struct devtable
|
|
{
|
|
OSType fsysSig;
|
|
struct fsysTable fsys;
|
|
};
|
|
|
|
struct MPWFile
|
|
{
|
|
short flags;
|
|
short err;
|
|
struct fsysTable *functions;
|
|
long cookie;
|
|
long count;
|
|
void *buffer;
|
|
};
|
|
|
|
struct pgminfo2
|
|
{
|
|
short magic2;
|
|
|
|
int argc;
|
|
char **argv;
|
|
char **envp;
|
|
// 0x0e
|
|
int exitCode;
|
|
|
|
// 0x12
|
|
int x;
|
|
// 0x16
|
|
int y;
|
|
// 0x1a
|
|
short tableSize;
|
|
struct MPWFile *ioptr;
|
|
struct devtable *devptr;
|
|
};
|
|
|
|
struct pgminfo
|
|
{
|
|
OSType magic;
|
|
struct pgminfo2 *rest;
|
|
};
|
|
#pragma pack (pop)
|
|
|
|
|
|
// Get MPW's magic struct
|
|
struct pgminfo2 *getPgmInfo(void)
|
|
{
|
|
struct pgminfo *pgm0 = *(struct pgminfo**) 0x316;
|
|
if(!pgm0)
|
|
return NULL;
|
|
if(pgm0 == (struct pgminfo*)-1)
|
|
return NULL;
|
|
if(pgm0->magic != 'MPGM')
|
|
return NULL;
|
|
if(!pgm0->rest)
|
|
return NULL;
|
|
if(pgm0->rest->magic2 != 0x5348)
|
|
return NULL;
|
|
return pgm0->rest;
|
|
}
|
|
|
|
jmp_buf exit_buf;
|
|
|
|
// called by standard library's exit()
|
|
// Store
|
|
void _exit(int status)
|
|
{
|
|
struct pgminfo2 *pgm = getPgmInfo();
|
|
if(pgm)
|
|
pgm->exitCode = status;
|
|
longjmp(exit_buf, 1);
|
|
}
|
|
|
|
const int procInfo = kCStackBased
|
|
| STACK_ROUTINE_PARAMETER(1, kFourByteCode);
|
|
|
|
int main(int argc, char *argv[], char *envp[])
|
|
{
|
|
struct pgminfo2 *pgm = getPgmInfo();
|
|
if(pgm)
|
|
{
|
|
struct MPWFile *f = &pgm->ioptr[1];
|
|
f->count = 14;
|
|
f->buffer = "Hello, world.\r";
|
|
|
|
#if TARGET_CPU_PPC
|
|
CallUniversalProc((UniversalProcPtr) f->functions->write, procInfo, f);
|
|
#else
|
|
f->functions->write(f);
|
|
#endif
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#if TARGET_CPU_PPC
|
|
|
|
void __do_global_dtors(void);
|
|
|
|
void __start(void)
|
|
{
|
|
if(setjmp(exit_buf))
|
|
;
|
|
else
|
|
{
|
|
atexit(&__do_global_dtors);
|
|
int result;
|
|
{
|
|
char *argv[2] = { "./a.out", NULL };
|
|
char *envp[1] = { NULL };
|
|
result = main(1, argv, envp);
|
|
}
|
|
exit(result);
|
|
}
|
|
}
|
|
|
|
void *__dso_handle = &__dso_handle;
|
|
|
|
#else
|
|
|
|
void _start(void)
|
|
{
|
|
RETRO68_RELOCATE();
|
|
|
|
if(setjmp(exit_buf))
|
|
;
|
|
else
|
|
{
|
|
atexit(&Retro68CallDestructors);
|
|
Retro68CallConstructors();
|
|
|
|
int result;
|
|
{
|
|
char *argv[2] = { "./a.out", NULL };
|
|
char *envp[1] = { NULL };
|
|
result = main(1, argv, envp);
|
|
}
|
|
exit(result);
|
|
}
|
|
}
|
|
|
|
#endif
|