Commit caa4d029 authored by David Cotton's avatar David Cotton
Browse files

Initial import of utility by Robin Cull.

Detail:
	This utility splits a ROM image into it's constituent modules. Each
module is saved into a seperate file numbered 001, 002 etcetera according to
the module's position in the ROM.
	If there are more than 70 files in the ROM it places the first 70 in
a subdirectory called '1', and then next 70 in another called '2', and so on.

Admin:
	I have added a RISC OS - compatible build structure, and a few other
little alterations such as srccommit support and giving the modules 3-digit
numbers.
	Basic tests performed on Lazarus ROM images.

Version 0.01. Tagged as 'ROMUnjoin-0_01'
parent e0f0cc07
| Copyright 2000 Pace Micro Technology plc
|
| Licensed under the Apache License, Version 2.0 (the "License");
| you may not use this file except in compliance with the License.
| You may obtain a copy of the License at
|
| http://www.apache.org/licenses/LICENSE-2.0
|
| Unless required by applicable law or agreed to in writing, software
| distributed under the License is distributed on an "AS IS" BASIS,
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
| See the License for the specific language governing permissions and
| limitations under the License.
|
Dir <Obey$Dir>
amu all
| Copyright 2000 Pace Micro Technology plc
|
| Licensed under the Apache License, Version 2.0 (the "License");
| you may not use this file except in compliance with the License.
| You may obtain a copy of the License at
|
| http://www.apache.org/licenses/LICENSE-2.0
|
| Unless required by applicable law or agreed to in writing, software
| distributed under the License is distributed on an "AS IS" BASIS,
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
| See the License for the specific language governing permissions and
| limitations under the License.
|
Dir <Obey$Dir>
amu clean
c/** gitlab-language=c linguist-language=c linguist-detectable=true
# Copyright 2000 Pace Micro Technology plc
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Project: ROMUnjoin
#
# Generic options:
#
MKDIR = cdir
AS = objasm
CC = cc
CMHG = cmhg
CP = copy
LD = link
RM = remove
WIPE = -wipe
STRIP = stripdepnd
AFLAGS = -depend !Depend -Stamp -quit
CFLAGS = -c -depend !Depend ${INCLUDES} ${DFLAGS}
CPFLAGS = ~cfr~v
WFLAGS = ~c~v
#
# Libraries
#
CLIB = CLIB:o.stubs
RLIB = RISCOSLIB:o.risc_oslib
RSTUBS = RISCOSLIB:o.rstubs
ROMSTUBS = RISCOSLIB:o.romstubs
ROMCSTUBS = RISCOSLIB:o.romcstubs
ABSSYM = RISC_OSLib:o.AbsSym
WRAPPER = s.ModuleWrap
#
# Rule patterns
#
.c.o:; ${CC} ${CFLAGS} -o $@ $<
.s.o:; ${AS} ${AFLAGS} $< $@
#
# Include files
#
INCLUDES = -IC:
#
# Program specific options:
#
COMPONENT = ROMUnjoin
APPLICATION = ROMUnjoin
TARGET = ROMUnjoin
OBJS = o.ROMUnjoin
#
# Build for application:
#
ROMUnjoin: ${OBJS} ${CLIB} dirs
${LD} -o $@ ${OBJS} ${CLIB}
dirs:
${MKDIR} o
#
# build an application:
#
all: ${APPLICATION}
@echo ${APPLICATION} built
clean:
${RM} ${TARGET}
${WIPE} ${OBJS} ${WFLAGS}
${WIPE} o ${WFLAGS}
${STRIP}
# Dynamic dependencies:
/* (0.00)
/* (0.01)
*
* This file is automatically maintained by srccommit, do not edit manually.
*
*/
#define Module_MajorVersion_CMHG 0.00
#define Module_MajorVersion_CMHG 0.01
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 02 Feb 2000
#define Module_MajorVersion "0.00"
#define Module_Version 0
#define Module_MajorVersion "0.01"
#define Module_Version 1
#define Module_MinorVersion ""
#define Module_Date "02 Feb 2000"
#define Module_FullVersion "0.00"
#define Module_FullVersion "0.01"
/* Copyright 2000 Pace Micro Technology plc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __riscos
#include "swis.h"
#include "kernel.h"
#include "VersionNum"
#endif
void getimage(char name[], char **image, int *ilen);
void modDump(char *image, char *dirBase);
char *memfind(char *mem, char *find);
#ifdef __riscos
void hourglass(int state);
#endif
void doexit(void) {
#ifdef __riscos
hourglass(0);
#endif
}
int main(int argc, char *argv[]) {
char *iptr, dirBase[255] = "\0";
int ilen;
atexit(doexit);
fprintf(stdout, "ROM Module Splitter V%s (%s)\n\n", Module_FullVersion, Module_Date);
if (argc >= 3) {
hourglass(1);
sprintf(dirBase, argv[2]);
getimage(argv[1], &iptr, &ilen);
modDump(iptr, dirBase);
hourglass(0);
}
else {
fprintf(stdout, "Splits up a ROM image into its constituent modules.\n");
fprintf(stdout, "Each module is saved into an individual file.\nIf there are more than 78 modules in the ROM, they go into subdirectories numbered 1, 2 etcetera.\n\n");
fprintf(stdout, "Syntax:\tROMSplit <ROM image> <dir base>\n\n");
exit(EXIT_FAILURE);
}
}
void getimage(char name[], char **image, int *ilenptr)
{
FILE *fptr;
if ((fptr = fopen(name, "rb")) == NULL) {
fprintf(stderr, "Can't open %s\n", name);
exit(EXIT_FAILURE);
}
/* Find size of image */
fseek(fptr, 0L, SEEK_END);
*ilenptr = (size_t) ftell(fptr);
fseek(fptr, 0L, SEEK_SET);
/* Alloc & read entire image */
if ((*image = malloc(*ilenptr)) == NULL) {
fprintf(stderr, "Can't allocate %dK for image\n", (*ilenptr)/1024);
exit(EXIT_FAILURE);
}
if (fread(*image, 1, *ilenptr, fptr) != *ilenptr) {
fprintf(stderr, "Can't read %s\n", name);
exit(EXIT_FAILURE);
}
fclose(fptr);
}
void modDump(char *image, char *dirBase) {
char *dptr, *p, *endPtr;
int modNum = 1, modSize, fileNum = 1, dirNum = 1;
char fileName[256];
_kernel_swi_regs regs;
p = memfind(image, "UtilityModule");
dptr = (char *)(((int)p-0x14) & ~3);
while (*((int *)(dptr+0x10)) != p-dptr) {
dptr -= 4;
}
dptr -= 4;
sprintf(fileName, "cdir %s", dirBase);
system(fileName);
while (*((int *)dptr) != 0) {
sprintf(fileName, "cdir %s.%d", dirBase, dirNum);
system(fileName);
fileNum = 1;
while ((fileNum <= 70) && (*((int *)dptr) != 0)) {
sprintf(fileName, "%s.%d.Module%03d\0", dirBase, dirNum, modNum);
modSize = *(int *)(dptr);
endPtr = (char *)(dptr + modSize + 5);
regs.r[0] = 11;
regs.r[1] = (int)&fileName;
regs.r[2] = 4090;
regs.r[4] = 0;
regs.r[5] = (modSize - 1);
_kernel_swi(OS_File, &regs, &regs);
fprintf(stdout,"Writing %7d bytes from %8p to %8p to file %s.\n", modSize, dptr, endPtr, fileName);
regs.r[0] = 10;
regs.r[1] = (int)&fileName;
regs.r[2] = 4090;
regs.r[4] = (int)(dptr + 4);
regs.r[5] = (int)endPtr;
_kernel_swi(OS_File, &regs, &regs);
dptr += *((int *)dptr);
modNum++;
fileNum++;
}
dirNum++;
}
}
char *memfind(char *mem, char *find)
{
char *c = mem;
do
{
while (*c != *find)
c++;
if (!(strcmp(c, find)))
return c;
c++;
} while (1);
}
#ifdef __riscos
/*
* toggle hourglass
*/
void
hourglass(int state)
{
if (state)
_swix(Hourglass_On,0);
else
_swix(Hourglass_Off,0);
}
#endif
/* Copyright 2000 Pace Micro Technology plc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
unsigned int irq : 1;
unsigned int : 1;
unsigned int fiq : 1;
unsigned int id : 4;
unsigned int conformant : 1;
unsigned int chunk_dir : 1;
unsigned int interrupt_status : 1;
unsigned int width : 2;
unsigned int : 4;
unsigned int : 8;
/* Yuck - have to split this because bitfields can't be split over word
* boundaries.
*/
unsigned int product_low_byte : 8;
unsigned int product_hi_byte : 8;
unsigned int manufacturer : 16;
unsigned int country : 8;
} ECId;
typedef struct
{
/* OS ID byte */
union
{
struct
{
unsigned int data : 4;
unsigned int os : 3;
unsigned int : 1;
unsigned int size : 24;
} bits;
unsigned int value;
} first_word;
unsigned int start;
} Chunk;
typedef struct
{
size_t start_code;
size_t init_code;
size_t final_code;
size_t service_handler;
size_t title;
size_t help;
size_t help_command_table;
} ModuleHeader;
enum
{
IntStatusPtrs_Size = 8
};
enum
{
OS_Id_RISCOS,
OS_Id_UNIX = 2,
OS_Id_Manufacturer = 6,
OS_Id_Device
};
enum
{
ChunkData_RISCOS_Loader,
ChunkData_RISCOS_Module,
ChunkData_RISCOS_BBC_ROM,
ChunkData_RISCOS_Sprite
};
void process_image (unsigned char * image);
void write_module (unsigned char * module_start,
size_t modules_size);
int main (int argc, char * argv[])
{
char * image_file_name;
FILE * image_fp;
size_t image_file_size;
unsigned char * image;
assert (sizeof (ECId) == 8);
assert (sizeof (Chunk) == 8);
if (argc < 2)
{
fprintf (stderr, "usage: podulesplit <filename>\n");
exit (EXIT_FAILURE);
}
image_file_name = argv[1];
image_fp = fopen (image_file_name, "rb");
if (!image_fp)
{
fprintf (stderr, "couldn't open file %s\n", image_file_name);
exit (EXIT_FAILURE);
}
fseek (image_fp, 0, SEEK_END);
image_file_size = (size_t) ftell (image_fp);
rewind (image_fp);
image = malloc (image_file_size);
if (!image)
{
fprintf (image_fp, "couldn't allocate memory\n");
fclose (image_fp);
exit (EXIT_FAILURE);
}
fread (image, sizeof (unsigned char), image_file_size, image_fp);
fclose (image_fp);
process_image (image);
free (image);
return EXIT_SUCCESS;
}
void process_image (unsigned char * image)
{
ECId * ec_id = (ECId *) image;
if (ec_id->id != 0)
{
fprintf (stderr,
"Expansion cards with Simple ECIds don't have modules\n");
return;
}
if (!ec_id->interrupt_status || !ec_id->chunk_dir)
{
fprintf (stderr, "ROM doesn't have chunk directory\n");
return;
}
else
{
Chunk * chunk = (Chunk *) (image + sizeof (ECId) + IntStatusPtrs_Size);
while (chunk->first_word.value != 0)
{
switch (chunk->first_word.bits.os)
{
case OS_Id_RISCOS:
switch (chunk->first_word.bits.data)
{
case ChunkData_RISCOS_Loader:
printf ("Loader\n");
break;
case ChunkData_RISCOS_Module:
printf ("Relocatlable Module: ");
write_module (image + chunk->start,
chunk->first_word.bits.size);
break;
case ChunkData_RISCOS_BBC_ROM:
printf ("BBC ROM\n");
break;
case ChunkData_RISCOS_Sprite:
printf ("Sprite\n");
break;
default:
printf ("Warning: found reserved data type %d\n",
chunk->first_word.bits.data);
break;
}
break;
case OS_Id_UNIX:
printf ("UNIX data\n");
break;
case OS_Id_Manufacturer:
printf ("Manufacturer specific data\n");
break;
case OS_Id_Device:
printf ("Device data\n");
break;
default:
printf ("Warning: found reserved OS Id %d\n",
chunk->first_word.bits.os);
break;
}
++chunk;
}
}
}
void write_module (unsigned char * module_start,
size_t module_size)
{
FILE * fp;
char * module_title;
module_title = (char *) module_start +
((ModuleHeader *) module_start)->title;
printf ("%s\n", module_title);
fp = fopen (module_title, "wb");
fwrite (module_start, sizeof (unsigned char), module_size, fp);
fclose (fp);
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment