o cleanup
@@ -1,10 +0,0 @@
|
||||
SHELL = sh
|
||||
OPTIMIZE = -O2
|
||||
CC = gcc
|
||||
CSTD = c99
|
||||
override CFLAGS = -pedantic -std=$(CSTD) -Wall -Wstrict-prototypes $(OPTIMIZE)
|
||||
|
||||
all: huffman-decode huffman-encode
|
||||
|
||||
clean:
|
||||
rm -f huffman-decode huffman-encode bin2avrS
|
||||
@@ -1,224 +0,0 @@
|
||||
/* huffman-decode.c */
|
||||
/*
|
||||
This file is part of the AVR-Huffman.
|
||||
Copyright (C) 2009 Daniel Otte (daniel.otte@rub.de)
|
||||
|
||||
This program 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.
|
||||
|
||||
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define V_NODE (-2)
|
||||
#define V_EOF (-1)
|
||||
|
||||
#define PREFIX_SIZE_B 32
|
||||
|
||||
#define ALLOC_ERROR {fprintf(stderr,"failed to alloc memory in %s @ %d !\n",__FILE__, __LINE__); exit(-1);}
|
||||
|
||||
#define DEBUG 0
|
||||
|
||||
typedef struct {
|
||||
int16_t value;
|
||||
void* left;
|
||||
void* right;
|
||||
} node_t;
|
||||
|
||||
node_t* tree=NULL;
|
||||
uint16_t tree_index;
|
||||
|
||||
void prefix_increment(uint8_t* prefix){
|
||||
uint8_t i;
|
||||
for(i=0; i<PREFIX_SIZE_B; ++i){
|
||||
prefix[i] += 1;
|
||||
if(prefix[i]!=0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void prefix_shiftleft(uint8_t* prefix){
|
||||
uint8_t i;
|
||||
uint8_t c[2]={0,0};
|
||||
uint8_t ci=0;
|
||||
for(i=0; i<PREFIX_SIZE_B; ++i){
|
||||
c[ci] = (prefix[i])>>7;
|
||||
prefix[i]<<=1;
|
||||
ci ^= 1;
|
||||
prefix[i]|=c[ci];
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t append_tree(int16_t value, uint16_t depth){
|
||||
static uint8_t prefix[PREFIX_SIZE_B];
|
||||
static uint8_t cdepth=0;
|
||||
node_t* current=tree;
|
||||
int8_t i,t;
|
||||
for(;cdepth<depth;++cdepth){
|
||||
prefix_shiftleft(prefix);
|
||||
}
|
||||
for(i=depth-1; i>=0; --i){
|
||||
t=(prefix[i/8])&(1<<(i%8));
|
||||
if(t==0){
|
||||
if(current->left==NULL){
|
||||
// current->left=calloc(1, sizeof(node_t));
|
||||
current->left=&(tree[tree_index++]);
|
||||
((node_t*)(current->left))->value = V_NODE;
|
||||
}
|
||||
current = current->left;
|
||||
} else {
|
||||
if(current->right==NULL){
|
||||
// current->right=calloc(1, sizeof(node_t));
|
||||
current->right=&(tree[tree_index++]);
|
||||
((node_t*)(current->right))->value = V_NODE;
|
||||
}
|
||||
current = current->right;
|
||||
}
|
||||
}
|
||||
if(current==NULL)
|
||||
ALLOC_ERROR
|
||||
current->value=value;
|
||||
prefix_increment(prefix);
|
||||
return prefix[depth/8]&(1<<(depth%8));
|
||||
}
|
||||
|
||||
void set_last_to_eof(void){
|
||||
node_t* current=tree;
|
||||
while(current->value==V_NODE)
|
||||
current=current->right;
|
||||
current->value=V_EOF;
|
||||
}
|
||||
|
||||
void build_tree(FILE* f){
|
||||
uint16_t treesize;
|
||||
uint16_t x1, x2;
|
||||
x1 =fgetc(f);
|
||||
x2 =fgetc(f);
|
||||
if(x1!=0xc0 || (x2&0xFE)!=0xde){
|
||||
fprintf(stderr,"No magic values found!\n");
|
||||
}
|
||||
treesize= fgetc(f);
|
||||
if(treesize>0xff){
|
||||
fprintf(stderr,"You are trying to uncompress an empty file!\n");
|
||||
exit(-3);
|
||||
}
|
||||
treesize = 2*(((x2&1)<<8)+treesize)-1;
|
||||
//printf("Using treesize=%i with size of %i\n", treesize, sizeof(node_t));
|
||||
tree = calloc(treesize, sizeof(node_t));
|
||||
if(tree==NULL)
|
||||
ALLOC_ERROR
|
||||
tree->value = V_NODE;
|
||||
tree_index=1;
|
||||
uint16_t depth=0;
|
||||
uint16_t count=0;
|
||||
uint8_t v;
|
||||
do{
|
||||
while(count==0){
|
||||
depth++;
|
||||
count= fgetc(f);
|
||||
if(count==255)
|
||||
count += fgetc(f);
|
||||
}
|
||||
v = fgetc(f);
|
||||
--count;
|
||||
}while(!append_tree(v, depth));
|
||||
set_last_to_eof();
|
||||
}
|
||||
|
||||
|
||||
void free_tree(node_t* node){
|
||||
free(node);
|
||||
}
|
||||
|
||||
FILE* outfile;
|
||||
FILE* infile;
|
||||
|
||||
void write_char(uint8_t v){
|
||||
fputc(v, outfile);
|
||||
}
|
||||
|
||||
uint8_t read_bit(void){
|
||||
static uint8_t buffer;
|
||||
static uint8_t index=0;
|
||||
uint8_t t;
|
||||
if(index==0){
|
||||
buffer = fgetc(infile);
|
||||
if(feof(infile))
|
||||
return 0xFF;
|
||||
}
|
||||
t=buffer>>7;
|
||||
buffer<<=1;
|
||||
index = (index+1)%8;
|
||||
return t;
|
||||
}
|
||||
|
||||
uint16_t decompress_byte(void){
|
||||
node_t* current=tree;
|
||||
uint8_t t;
|
||||
while(current->value==V_NODE){
|
||||
t=read_bit();
|
||||
if(t==0xFF)
|
||||
return EOF;
|
||||
if(t==0){
|
||||
current=current->left;
|
||||
} else {
|
||||
current=current->right;
|
||||
}
|
||||
if(current==NULL){
|
||||
fprintf(stderr, "Tree damaged!\n");
|
||||
exit(-4);
|
||||
}
|
||||
}
|
||||
return current->value;
|
||||
}
|
||||
|
||||
void decompress(void){
|
||||
uint16_t t;
|
||||
for(;;){
|
||||
t=decompress_byte();
|
||||
if(t==(uint16_t)EOF)
|
||||
return;
|
||||
write_char(t);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv){
|
||||
int i;
|
||||
FILE* fin;
|
||||
FILE* fg;
|
||||
// outfile=stdout;
|
||||
for(i=1;i<argc;++i){
|
||||
fin = fopen(argv[i], "r");
|
||||
fg = fopen("graphout.dot", "w");
|
||||
outfile = fopen("decompress.out", "w");
|
||||
puts("building tree ...");
|
||||
build_tree(fin);
|
||||
fclose(fg);
|
||||
infile=fin;
|
||||
puts("decompression ...");
|
||||
decompress();
|
||||
fclose(fin);
|
||||
fclose(outfile);
|
||||
free_tree(tree);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,470 +0,0 @@
|
||||
/* huffman-encode.c */
|
||||
/*
|
||||
This file is part of the AVR-Huffman.
|
||||
Copyright (C) 2009 Daniel Otte (daniel.otte@rub.de)
|
||||
|
||||
This program 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.
|
||||
|
||||
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define DEBUG 0
|
||||
#define XDEBUG 0
|
||||
|
||||
typedef struct{
|
||||
uint8_t depth;
|
||||
uint16_t value;
|
||||
uint32_t weight;
|
||||
void* left;
|
||||
void* right;
|
||||
} node_t;
|
||||
|
||||
typedef struct{
|
||||
uint16_t value;
|
||||
unsigned depth;
|
||||
void* encoding;
|
||||
} item_t;
|
||||
|
||||
typedef struct{
|
||||
uint8_t initialized;
|
||||
item_t* item;
|
||||
void* parent;
|
||||
void* left;
|
||||
void* right;
|
||||
} node2_t;
|
||||
|
||||
uint32_t histogram[256];
|
||||
node_t* pool[256+1];
|
||||
unsigned poolsize;
|
||||
unsigned item_count;
|
||||
node_t* tree;
|
||||
node_t* treenodes;
|
||||
unsigned treeindex=0;
|
||||
item_t* itemlist;
|
||||
unsigned itemindex=0;
|
||||
node2_t* node2list=NULL;
|
||||
unsigned node2list_index=0;
|
||||
item_t* valueencode[256];
|
||||
item_t* eof_encoding;
|
||||
|
||||
void reset_histogram(void){
|
||||
memset(histogram, 0, 256*sizeof(uint32_t));
|
||||
}
|
||||
|
||||
void build_histogram(char* fname){
|
||||
FILE* f;
|
||||
int t;
|
||||
f = fopen(fname, "r");
|
||||
while((t=fgetc(f))!=EOF){
|
||||
histogram[(uint8_t)t&0xFF]++;
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
|
||||
void build_pool(void){
|
||||
unsigned i,j;
|
||||
memset(pool, 0, 256*sizeof(node_t*));
|
||||
for(i=0,j=0;i<256;++i){
|
||||
if(histogram[i]==0)
|
||||
continue;
|
||||
pool[j] = malloc(sizeof(node_t));
|
||||
if(pool[j]==NULL){
|
||||
fprintf(stderr,"out of memory error (%d)!\n", __LINE__);
|
||||
exit(-1);
|
||||
}
|
||||
pool[j]->depth = 0;
|
||||
pool[j]->value = i;
|
||||
pool[j]->left = NULL;
|
||||
pool[j]->right = NULL;
|
||||
pool[j]->weight = histogram[i];
|
||||
j++;
|
||||
}
|
||||
pool[j] = malloc(sizeof(node_t));
|
||||
if(pool[j]==NULL){
|
||||
fprintf(stderr,"out of memory error (%d)!\n", __LINE__);
|
||||
exit(-1);
|
||||
}
|
||||
pool[j]->depth = 0;
|
||||
pool[j]->value = 0xFFFF;
|
||||
pool[j]->left = NULL;
|
||||
pool[j]->right = NULL;
|
||||
pool[j]->weight = 1;
|
||||
j++;
|
||||
poolsize = j;
|
||||
item_count = j;
|
||||
}
|
||||
|
||||
void find_lightest2(unsigned* a, unsigned* b, unsigned* depth){
|
||||
unsigned ia=0;
|
||||
unsigned ib=0;
|
||||
uint32_t wa, wb;
|
||||
unsigned i;
|
||||
wa = wb = 0xFFFFFFFF;
|
||||
for(i=0; i<poolsize; ++i){
|
||||
if(pool[i]==NULL)
|
||||
continue;
|
||||
if(wa>=pool[i]->weight){
|
||||
wb = wa;
|
||||
ib = ia;
|
||||
wa = pool[i]->weight;
|
||||
ia = i;
|
||||
}else{
|
||||
if(wb>pool[i]->weight){
|
||||
wb = pool[i]->weight;
|
||||
ib = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(wb == 0xFFFFFFFF || wa == 0xFFFFFFFF){
|
||||
fprintf(stderr, "Error while searching!\n");
|
||||
exit(-2);
|
||||
}
|
||||
if(pool[ia]->depth <= pool[ib]->depth){
|
||||
*a = ia;
|
||||
*b = ib;
|
||||
*depth = pool[ib]->depth;
|
||||
} else {
|
||||
*a = ib;
|
||||
*b = ia;
|
||||
*depth = pool[ia]->depth;
|
||||
}
|
||||
}
|
||||
|
||||
void init_tree(void){
|
||||
treenodes = malloc((poolsize-1)*sizeof(node_t));
|
||||
if(treenodes==NULL){
|
||||
fprintf(stderr,"out of memory error (%d)!\n", __LINE__);
|
||||
exit(-1);
|
||||
}
|
||||
#if XDEBUG
|
||||
printf("treenodes := %p\n", (void*)treenodes);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void update_tree(void){
|
||||
if(poolsize<2)
|
||||
return;
|
||||
unsigned a,b, depth;
|
||||
find_lightest2(&a,&b,&depth);
|
||||
#if XDEBUG
|
||||
printf("joining %d and %d\n", a,b);
|
||||
#endif
|
||||
treenodes[treeindex].depth = depth+1;
|
||||
treenodes[treeindex].weight = pool[a]->weight + pool[b]->weight;
|
||||
treenodes[treeindex].left = (pool[a]);
|
||||
treenodes[treeindex].right = (pool[b]);
|
||||
#if XDEBUG
|
||||
printf(" idx = %d\n self = %p\n depth = %d\n weight = %d\n"
|
||||
" left = %p\n right = %p\n",
|
||||
treeindex, (void*)&(treenodes[treeindex]), treenodes[treeindex].depth,
|
||||
treenodes[treeindex].weight, treenodes[treeindex].left,
|
||||
treenodes[treeindex].right);
|
||||
#endif
|
||||
pool[a] = &(treenodes[treeindex]);
|
||||
pool[b] = pool[poolsize-1];
|
||||
pool[poolsize-1] = NULL;
|
||||
--poolsize;
|
||||
++treeindex;
|
||||
}
|
||||
|
||||
void build_tree(void){
|
||||
while(poolsize>1){
|
||||
update_tree();
|
||||
}
|
||||
tree = &(treenodes[treeindex-1]);
|
||||
}
|
||||
|
||||
|
||||
void free_leaf(node_t* node){
|
||||
if(node->depth==0){
|
||||
free(node);
|
||||
}else{
|
||||
free_leaf(node->left);
|
||||
free_leaf(node->right);
|
||||
}
|
||||
}
|
||||
|
||||
void free_tree(void){
|
||||
free_leaf(tree);
|
||||
free(treenodes);
|
||||
tree = NULL;
|
||||
}
|
||||
|
||||
void init_itemlist(void){
|
||||
itemlist = calloc((item_count),sizeof(item_t));
|
||||
if(itemlist==NULL){
|
||||
fprintf(stderr,"out of memory error (%d)!\n", __LINE__);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void update_itemlist(node_t* node, unsigned depth){
|
||||
if(node->depth==0){
|
||||
itemlist[itemindex].value = node->value;
|
||||
itemlist[itemindex].depth = depth;
|
||||
++itemindex;
|
||||
} else {
|
||||
update_itemlist(node->left, depth+1);
|
||||
update_itemlist(node->right, depth+1);
|
||||
}
|
||||
}
|
||||
|
||||
void build_itemlist(void){
|
||||
update_itemlist(tree, 0);
|
||||
}
|
||||
|
||||
int item_compare_depth(const void* a, const void* b){
|
||||
if(((item_t*)a)->value==0xFFFF)
|
||||
return 1;
|
||||
if(((item_t*)b)->value==0xFFFF)
|
||||
return -1;
|
||||
return ((item_t*)a)->depth - ((item_t*)b)->depth;
|
||||
}
|
||||
|
||||
void sort_itemlist(void){
|
||||
qsort(itemlist, item_count, sizeof(item_t), item_compare_depth);
|
||||
}
|
||||
|
||||
#define PREFIX_SIZE_B 32
|
||||
|
||||
void prefix_increment(uint8_t* prefix){
|
||||
uint8_t i;
|
||||
for(i=0; i<PREFIX_SIZE_B; ++i){
|
||||
prefix[i] += 1;
|
||||
if(prefix[i]!=0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void prefix_shiftleft(uint8_t* prefix){
|
||||
uint8_t i;
|
||||
uint8_t c[2]={0,0};
|
||||
uint8_t ci=0;
|
||||
for(i=0; i<PREFIX_SIZE_B; ++i){
|
||||
c[ci] = (prefix[i])>>7;
|
||||
prefix[i]<<=1;
|
||||
ci ^= 1;
|
||||
prefix[i]|=c[ci];
|
||||
}
|
||||
}
|
||||
|
||||
void gen_itemencoding(void){
|
||||
uint8_t prefix[PREFIX_SIZE_B];
|
||||
memset(prefix, 0, PREFIX_SIZE_B);
|
||||
unsigned depth=0;
|
||||
unsigned depth_B=0;
|
||||
unsigned i,j;
|
||||
for(i=0; i<item_count; ++i){
|
||||
if(depth!=itemlist[i].depth){
|
||||
for(j=depth; j<itemlist[i].depth; ++j)
|
||||
prefix_shiftleft(prefix);
|
||||
depth = itemlist[i].depth;
|
||||
depth_B = (depth+7)/8;
|
||||
}
|
||||
itemlist[i].encoding=malloc(depth_B);
|
||||
if(itemlist[i].encoding==NULL){
|
||||
fprintf(stderr,"out of memory error (%d)!\n", __LINE__);
|
||||
exit(-1);
|
||||
}
|
||||
memcpy(itemlist[i].encoding, prefix, depth_B);
|
||||
prefix_increment(prefix);
|
||||
}
|
||||
}
|
||||
|
||||
void add_item2(item_t* item){
|
||||
int i;
|
||||
uint8_t t;
|
||||
node2_t* current;
|
||||
current = node2list;
|
||||
char c;
|
||||
c = item->value;
|
||||
// printf(" %2.2X (%c) => ", c, (c>32&&c<128)?c:' ');
|
||||
for(i=item->depth-1; i>=0; --i){
|
||||
t = (((uint8_t*)(item->encoding))[i/8])&(1<<(i%8));
|
||||
if(current->initialized==0){
|
||||
current->initialized=1;
|
||||
current->parent = NULL;
|
||||
current->item = NULL;
|
||||
current->left = NULL;
|
||||
current->right = NULL;
|
||||
node2list_index++;
|
||||
}
|
||||
if(t==0){
|
||||
// putchar('0');
|
||||
if(current->left){
|
||||
current = current->left;
|
||||
} else {
|
||||
current->left = &(node2list[node2list_index++]);
|
||||
((node2_t*)(current->left))->parent = current;
|
||||
current = current->left;
|
||||
current->initialized=1;
|
||||
current->item=NULL;
|
||||
}
|
||||
} else {
|
||||
// putchar('1');
|
||||
if(current->right){
|
||||
current = current->right;
|
||||
} else {
|
||||
current->right = &(node2list[node2list_index++]);
|
||||
((node2_t*)(current->right))->parent = current;
|
||||
current = current->right;
|
||||
current->initialized=1;
|
||||
current->item=NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
current->item = item;
|
||||
current->left = NULL;
|
||||
current->right = NULL;
|
||||
// printf("\n");
|
||||
}
|
||||
|
||||
void gen_tree2(void){
|
||||
unsigned i;
|
||||
node2list = calloc(2*item_count-1, sizeof(node2_t));
|
||||
#if XDEBUG
|
||||
printf("item_count = %d\n", item_count);
|
||||
#endif
|
||||
if(node2list==NULL){
|
||||
fprintf(stderr,"out of memory error (%d)!\n", __LINE__);
|
||||
exit(-1);
|
||||
}
|
||||
for(i=0;i<item_count;++i){
|
||||
add_item2(&(itemlist[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void bit_writer(FILE* f, uint8_t bit, uint8_t flush){
|
||||
static uint8_t buffer;
|
||||
static uint8_t buffer_index=0;
|
||||
if(flush){
|
||||
for(;buffer_index<8;++buffer_index)
|
||||
buffer<<=1;
|
||||
}
|
||||
if(buffer_index==8){
|
||||
fputc(buffer, f);
|
||||
buffer_index=0;
|
||||
}
|
||||
|
||||
buffer<<=1;
|
||||
buffer|=bit?1:0;
|
||||
buffer_index++;
|
||||
}
|
||||
|
||||
void encoding_writer(FILE* f, uint8_t* data, uint16_t length){
|
||||
int i;
|
||||
if(data==NULL)
|
||||
bit_writer(f, 0, 1);
|
||||
for(i=length-1;i>=0;--i){
|
||||
bit_writer(f,data[i/8]&(1<<(i%8)),0);
|
||||
}
|
||||
}
|
||||
|
||||
void build_valueencode(void){
|
||||
unsigned i;
|
||||
memset(valueencode, 0, 256*sizeof(void*));
|
||||
for(i=0; i<item_count-1; ++i){
|
||||
valueencode[itemlist[i].value] = &(itemlist[i]);
|
||||
}
|
||||
eof_encoding = &(itemlist[i]);
|
||||
}
|
||||
|
||||
void write_tree(FILE* f){
|
||||
unsigned i,j;
|
||||
unsigned last=0;
|
||||
unsigned last_depth=1;
|
||||
fputc(0xc0, f);
|
||||
fputc(0xde + (item_count>>8), f);
|
||||
fputc(item_count,f);
|
||||
for(i=0; i<item_count; ++i){
|
||||
if(itemlist[i].depth!=last_depth){
|
||||
if(i-last>=255){
|
||||
fputc(255, f);
|
||||
fputc(i-last-255, f);
|
||||
} else {
|
||||
fputc(i-last, f);
|
||||
}
|
||||
for(j=last; j<i; ++j){
|
||||
fputc(itemlist[j].value, f);
|
||||
}
|
||||
for(j=last_depth+1; j<itemlist[i].depth; ++j)
|
||||
fputc(0, f);
|
||||
last=i;
|
||||
last_depth=itemlist[i].depth;
|
||||
|
||||
}
|
||||
}
|
||||
if(i-last>=255){
|
||||
fputc(255, f);
|
||||
fputc(i-last-255, f);
|
||||
} else {
|
||||
fputc(i-last, f);
|
||||
}
|
||||
for(j=last; j<i; ++j){
|
||||
fputc(itemlist[j].value, f);
|
||||
}
|
||||
}
|
||||
|
||||
void compress_file(FILE* fin, FILE* fout){
|
||||
int t;
|
||||
while((t=fgetc(fin))!=EOF){
|
||||
t = (uint8_t)t;
|
||||
if(valueencode[t]==NULL){
|
||||
fprintf(stderr,"no encoding for %2.2X (%c) found!\n",t,(t>32&&t<128)?t:' ');
|
||||
exit(-3);
|
||||
}
|
||||
encoding_writer(fout, valueencode[t]->encoding, valueencode[t]->depth);
|
||||
};
|
||||
encoding_writer(fout, eof_encoding->encoding, eof_encoding->depth);
|
||||
encoding_writer(fout, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
void compress_huffman(char * filename_in, char * filename_out){
|
||||
FILE* fin;
|
||||
FILE* fout;
|
||||
reset_histogram();
|
||||
build_histogram(filename_in);
|
||||
build_pool();
|
||||
init_tree();
|
||||
build_tree();
|
||||
init_itemlist();
|
||||
build_itemlist();
|
||||
free_tree();
|
||||
sort_itemlist();
|
||||
gen_itemencoding();
|
||||
gen_tree2();
|
||||
build_valueencode();
|
||||
fin = fopen(filename_in, "r");
|
||||
fout = fopen(filename_out, "w");
|
||||
write_tree(fout);
|
||||
compress_file(fin, fout);
|
||||
fclose(fin);
|
||||
fclose(fout);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv){
|
||||
char filename_out[strlen(argv[1])+20];
|
||||
strcpy(filename_out, argv[1]);
|
||||
strcat(filename_out, ".hfm");
|
||||
compress_huffman(argv[1],filename_out);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<Project name="MMC_Card"><File path="fat.c"></File><File path="fat.h"></File><File path="main.c"></File><File path="makefile"></File><File path="mmc.c"></File><File path="mmc.h"></File><File path="usart.c"></File><File path="usart.h"></File></Project>
|
||||
@@ -1,316 +0,0 @@
|
||||
/*#######################################################################################
|
||||
FAT for AVR (MMC/SD)
|
||||
|
||||
Copyright (C) 2004 Ulrich Radig
|
||||
|
||||
Bei Fragen und Verbesserungen wendet euch per EMail an
|
||||
|
||||
mail@ulrichradig.de
|
||||
|
||||
oder im Forum meiner Web Page : www.ulrichradig.de
|
||||
|
||||
|
||||
Dieses Programm ist freie Software. Sie k<>nnen es unter den Bedingungen der
|
||||
GNU General Public License, wie von der Free Software Foundation ver<65>ffentlicht,
|
||||
weitergeben und/oder modifizieren, entweder gem<65><6D> Version 2 der Lizenz oder
|
||||
(nach Ihrer Option) jeder sp<73>teren Version.
|
||||
|
||||
Die Ver<65>ffentlichung dieses Programms erfolgt in der Hoffnung,
|
||||
da<EFBFBD> es Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE,
|
||||
sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT
|
||||
F<EFBFBD>R EINEN BESTIMMTEN ZWECK. Details finden Sie in der GNU General Public License.
|
||||
|
||||
Sie sollten eine Kopie der GNU General Public License zusammen mit diesem
|
||||
Programm erhalten haben.
|
||||
Falls nicht, schreiben Sie an die Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||||
#######################################################################################*/
|
||||
|
||||
#include "fat.h"
|
||||
|
||||
unsigned char cluster_size;
|
||||
unsigned int fat_offset;
|
||||
unsigned int cluster_offset;
|
||||
unsigned int volume_boot_record_addr;
|
||||
|
||||
//############################################################################
|
||||
//Auslesen Cluster Size der MMC/SD Karte und Speichern der gr<67><72>e ins EEprom
|
||||
//Auslesen Cluster Offset der MMC/SD Karte und Speichern der gr<67><72>e ins EEprom
|
||||
void fat_init (void)
|
||||
//############################################################################
|
||||
{
|
||||
struct BootSec *bootp; //Zeiger auf Bootsektor Struktur
|
||||
|
||||
unsigned char Buffer[BlockSize];
|
||||
|
||||
//volume_boot_record_addr = fat_addr (Buffer);
|
||||
mmc_read_sector (MASTER_BOOT_RECORD,Buffer); //Read Master Boot Record
|
||||
if (Buffer[510] == 0x55 && Buffer[511] == 0xAA)
|
||||
{
|
||||
FAT_DEBUG("\r\nMBR Signatur found!\r\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
FAT_DEBUG("\r\nMBR Signatur not found!\r\n");
|
||||
while(1);
|
||||
}
|
||||
|
||||
|
||||
volume_boot_record_addr = Buffer[VBR_ADDR] + (Buffer[VBR_ADDR+1] << 8);
|
||||
|
||||
mmc_read_sector (volume_boot_record_addr,Buffer);
|
||||
if (Buffer[510] == 0x55 && Buffer[511] == 0xAA)
|
||||
{
|
||||
FAT_DEBUG("\r\nVBR Signatur found!\r\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
FAT_DEBUG("\r\nVBR Signatur not found!\r\n");
|
||||
volume_boot_record_addr = MASTER_BOOT_RECORD;//<- added by Hennie
|
||||
mmc_read_sector (MASTER_BOOT_RECORD,Buffer); //Read Master Boot Record
|
||||
}
|
||||
|
||||
bootp=(struct BootSec *)Buffer;
|
||||
cluster_size = bootp->BPB_SecPerClus;
|
||||
fat_offset = bootp->BPB_RsvdSecCnt;
|
||||
|
||||
cluster_offset = ((bootp->BPB_BytesPerSec * 32)/BlockSize);
|
||||
cluster_offset += fat_root_dir_addr(Buffer);
|
||||
}
|
||||
|
||||
//############################################################################
|
||||
//Auslesen der Adresse des First Root Directory von Volume Boot Record
|
||||
unsigned int fat_root_dir_addr (unsigned char *Buffer)
|
||||
//############################################################################
|
||||
{
|
||||
struct BootSec *bootp; //Zeiger auf Bootsektor Struktur
|
||||
unsigned int FirstRootDirSecNum;
|
||||
//auslesen des Volume Boot Record von der MMC/SD Karte
|
||||
mmc_read_sector (volume_boot_record_addr,Buffer);
|
||||
bootp=(struct BootSec *)Buffer;
|
||||
|
||||
//berechnet den ersten Sector des Root Directory
|
||||
FirstRootDirSecNum = ( bootp->BPB_RsvdSecCnt +
|
||||
(bootp->BPB_NumFATs * bootp->BPB_FATSz16));
|
||||
|
||||
FirstRootDirSecNum+= volume_boot_record_addr;
|
||||
|
||||
return(FirstRootDirSecNum);
|
||||
}
|
||||
|
||||
//############################################################################
|
||||
// Ausgabe des angegebenen Directory Eintrag in Entry_Count
|
||||
// ist kein Eintrag vorhanden, ist der Eintrag im
|
||||
// R<>ckgabe Cluster 0xFFFF. Es wird immer nur ein Eintrag ausgegeben
|
||||
// um Speicherplatz zu sparen um es auch f<>r kleine Atmels zu benutzen
|
||||
unsigned int fat_read_dir_ent (unsigned int dir_cluster, //Angabe Dir Cluster
|
||||
unsigned char Entry_Count, //Angabe welcher Direintrag
|
||||
unsigned long *Size, //R<>ckgabe der File Gr<47><72>e
|
||||
unsigned char *Dir_Attrib, //R<>ckgabe des Dir Attributs
|
||||
unsigned char *Buffer) //Working Buffer
|
||||
//############################################################################
|
||||
{
|
||||
unsigned char *pointer;
|
||||
unsigned int TMP_Entry_Count = 0;
|
||||
unsigned long Block = 0;
|
||||
struct DirEntry *dir; //Zeiger auf einen Verzeichniseintrag
|
||||
|
||||
pointer = Buffer;
|
||||
|
||||
if (dir_cluster == 0)
|
||||
{
|
||||
Block = fat_root_dir_addr(Buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Berechnung des Blocks aus BlockCount und Cluster aus FATTabelle
|
||||
//Berechnung welcher Cluster zu laden ist
|
||||
//Auslesen der FAT - Tabelle
|
||||
fat_load (dir_cluster,&Block,Buffer);
|
||||
Block = ((Block-2) * cluster_size) + cluster_offset;
|
||||
}
|
||||
|
||||
//auslesen des gesamten Root Directory
|
||||
for (unsigned int blk = Block;;blk++)
|
||||
{
|
||||
mmc_read_sector (blk,Buffer); //Lesen eines Blocks des Root Directory
|
||||
for (unsigned int a=0;a<BlockSize; a = a + 32)
|
||||
{
|
||||
dir=(struct DirEntry *)&Buffer[a]; //Zeiger auf aktuellen Verzeichniseintrag holen
|
||||
|
||||
if (dir->DIR_Name[0] == 0) //Kein weiterer Eintrag wenn erstes Zeichen des Namens 0 ist
|
||||
{
|
||||
return (0xFFFF);
|
||||
}
|
||||
|
||||
//Pr<50>fen ob es ein 8.3 Eintrag ist
|
||||
//Das ist der Fall wenn es sich nicht um einen Eintrag f<>r lange Dateinamen
|
||||
//oder um einen als gel<65>scht markierten Eintrag handelt.
|
||||
if ((dir->DIR_Attr != ATTR_LONG_NAME) &&
|
||||
(dir->DIR_Name[0] != DIR_ENTRY_IS_FREE))
|
||||
{
|
||||
//Ist es der gew<65>nschte Verzeichniseintrag
|
||||
if (TMP_Entry_Count == Entry_Count)
|
||||
{
|
||||
//Speichern des Verzeichnis Eintrages in den R<>ckgabe Buffer
|
||||
for(unsigned char b=0;b<11;b++)
|
||||
{
|
||||
if (dir->DIR_Name[b] != SPACE)
|
||||
{
|
||||
if (b == 8)
|
||||
{
|
||||
*pointer++= '.';
|
||||
}
|
||||
*pointer++=dir->DIR_Name[b];
|
||||
}
|
||||
}
|
||||
*pointer++='\0';
|
||||
*Dir_Attrib = dir->DIR_Attr;
|
||||
|
||||
//Speichern der Filegr<67><72>e
|
||||
*Size=dir->DIR_FileSize;
|
||||
|
||||
//Speichern des Clusters des Verzeichniseintrages
|
||||
dir_cluster = dir->DIR_FstClusLO;
|
||||
|
||||
//Eintrag gefunden R<>cksprung mit Cluster File Start
|
||||
return(dir_cluster);
|
||||
}
|
||||
TMP_Entry_Count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (0xFFFF); //Kein Eintrag mehr gefunden R<>cksprung mit 0xFFFF
|
||||
}
|
||||
|
||||
//############################################################################
|
||||
// Auslesen der Cluster f<>r ein File aus der FAT
|
||||
// in den Buffer(512Byte). Bei einer 128MB MMC/SD
|
||||
// Karte ist die Cluster gr<67><72>e normalerweise 16KB gro<72>
|
||||
// das bedeutet das File kann max. 4MByte gro<72> sein.
|
||||
// Bei gr<67><72>eren Files mu<6D> der Buffer gr<67><72>er definiert
|
||||
// werden! (Ready)
|
||||
// Cluster = Start Clusterangabe aus dem Directory
|
||||
void fat_load ( unsigned int Cluster, //Angabe Startcluster
|
||||
unsigned long *Block,
|
||||
unsigned char *TMP_Buffer) //Workingbuffer
|
||||
//############################################################################
|
||||
{
|
||||
//Zum <20>berpr<70>fen ob der FAT Block schon geladen wurde
|
||||
unsigned int FAT_Block_Store = 0;
|
||||
|
||||
//Byte Adresse innerhalb des Fat Blocks
|
||||
unsigned int FAT_Byte_Addresse;
|
||||
|
||||
//FAT Block Adresse
|
||||
unsigned int FAT_Block_Addresse;
|
||||
|
||||
//Berechnung f<>r den ersten FAT Block (FAT Start Addresse)
|
||||
for (unsigned int a = 0;;a++)
|
||||
{
|
||||
if (a == *Block)
|
||||
{
|
||||
*Block = (0x0000FFFF & Cluster);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Cluster == 0xFFFF)
|
||||
{
|
||||
break; //Ist das Ende des Files erreicht Schleife beenden
|
||||
}
|
||||
//Berechnung des Bytes innerhalb des FAT Block<63>s
|
||||
FAT_Byte_Addresse = (Cluster*2) % BlockSize;
|
||||
|
||||
//Berechnung des Blocks der gelesen werden mu<6D>
|
||||
FAT_Block_Addresse = ((Cluster*2) / BlockSize) +
|
||||
volume_boot_record_addr + fat_offset;
|
||||
//Lesen des FAT Blocks
|
||||
//<2F>berpr<70>fung ob dieser Block schon gelesen wurde
|
||||
if (FAT_Block_Addresse != FAT_Block_Store)
|
||||
{
|
||||
FAT_Block_Store = FAT_Block_Addresse;
|
||||
//Lesen des FAT Blocks
|
||||
mmc_read_sector (FAT_Block_Addresse,TMP_Buffer);
|
||||
}
|
||||
|
||||
//Lesen der n<>chsten Clusternummer
|
||||
Cluster = (TMP_Buffer[FAT_Byte_Addresse + 1] << 8) +
|
||||
TMP_Buffer[FAT_Byte_Addresse];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//############################################################################
|
||||
//Lesen eines 512Bytes Blocks von einem File
|
||||
void fat_read_file (unsigned int Cluster,//Angabe des Startclusters vom File
|
||||
unsigned char *Buffer, //Workingbuffer
|
||||
unsigned long BlockCount) //Angabe welcher Bock vom File geladen
|
||||
//werden soll a 512 Bytes
|
||||
//############################################################################
|
||||
{
|
||||
//Berechnung des Blocks aus BlockCount und Cluster aus FATTabelle
|
||||
//Berechnung welcher Cluster zu laden ist
|
||||
|
||||
unsigned long Block = (BlockCount/cluster_size);
|
||||
|
||||
//Auslesen der FAT - Tabelle
|
||||
fat_load (Cluster,&Block,Buffer);
|
||||
Block = ((Block-2) * cluster_size) + cluster_offset;
|
||||
//Berechnung des Blocks innerhalb des Cluster
|
||||
Block += (BlockCount % cluster_size);
|
||||
//Read Data Block from Device
|
||||
mmc_read_sector (Block,Buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
//############################################################################
|
||||
//Lesen eines 512Bytes Blocks von einem File
|
||||
void fat_write_file (unsigned int cluster,//Angabe des Startclusters vom File
|
||||
unsigned char *buffer, //Workingbuffer
|
||||
unsigned long blockCount) //Angabe welcher Bock vom File gespeichert
|
||||
//werden soll a 512 Bytes
|
||||
//############################################################################
|
||||
{
|
||||
//Berechnung des Blocks aus BlockCount und Cluster aus FATTabelle
|
||||
//Berechnung welcher Cluster zu speichern ist
|
||||
unsigned char tmp_buffer[513];
|
||||
unsigned long block = (blockCount/cluster_size);
|
||||
|
||||
//Auslesen der FAT - Tabelle
|
||||
fat_load (cluster,&block,tmp_buffer);
|
||||
block = ((block-2) * cluster_size) + cluster_offset;
|
||||
//Berechnung des Blocks innerhalb des Cluster
|
||||
block += (blockCount % cluster_size);
|
||||
//Write Data Block to Device
|
||||
mmc_write_sector (block,buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
//####################################################################################
|
||||
//Sucht ein File im Directory
|
||||
unsigned char fat_search_file (unsigned char *File_Name, //Name des zu suchenden Files
|
||||
unsigned int *Cluster, //Angabe Dir Cluster welches
|
||||
//durchsucht werden soll
|
||||
//und R<>ckgabe des clusters
|
||||
//vom File welches gefunden
|
||||
//wurde
|
||||
unsigned long *Size, //R<>ckgabe der File Gr<47><72>e
|
||||
unsigned char *Dir_Attrib,//R<>ckgabe des Dir Attributs
|
||||
unsigned char *Buffer) //Working Buffer
|
||||
//####################################################################################
|
||||
{
|
||||
unsigned int Dir_Cluster_Store = *Cluster;
|
||||
for (unsigned char a = 0;a < 100;a++)
|
||||
{
|
||||
*Cluster = fat_read_dir_ent(Dir_Cluster_Store,a,Size,Dir_Attrib,Buffer);
|
||||
if (*Cluster == 0xffff)
|
||||
{
|
||||
return(0); //File not Found
|
||||
}
|
||||
if(strcasecmp((char *)File_Name,(char *)Buffer) == 0)
|
||||
{
|
||||
return(1); //File Found
|
||||
}
|
||||
}
|
||||
return(2); //Error
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
/*#######################################################################################
|
||||
Connect ARM to MMC/SD
|
||||
|
||||
Copyright (C) 2004 Ulrich Radig
|
||||
#######################################################################################*/
|
||||
|
||||
#ifndef _FAT_H_
|
||||
#define _FAT_H_
|
||||
|
||||
#include <string.h>
|
||||
#include "mmc.h"
|
||||
#include "usart.h"
|
||||
|
||||
#define FAT_DEBUG usart_write
|
||||
//#define FAT_DEBUG(...)
|
||||
|
||||
|
||||
//Prototypes
|
||||
extern unsigned int fat_root_dir_addr (unsigned char *);
|
||||
extern unsigned int fat_read_dir_ent (unsigned int,unsigned char,unsigned long*,unsigned char *,unsigned char *);
|
||||
extern void fat_load (unsigned int,unsigned long *,unsigned char *);
|
||||
extern void fat_read_file (unsigned int,unsigned char *,unsigned long);
|
||||
extern void fat_write_file (unsigned int,unsigned char *,unsigned long);
|
||||
extern void fat_init (void);
|
||||
extern unsigned char fat_search_file (unsigned char *,unsigned int *,unsigned long *,unsigned char *,unsigned char *);
|
||||
|
||||
//Block Size in Bytes
|
||||
#define BlockSize 512
|
||||
|
||||
//Master Boot Record
|
||||
#define MASTER_BOOT_RECORD 0
|
||||
|
||||
//Volume Boot Record location in Master Boot Record
|
||||
#define VBR_ADDR 0x1C6
|
||||
|
||||
//define ASCII
|
||||
#define SPACE 0x20
|
||||
#define DIR_ENTRY_IS_FREE 0xE5
|
||||
#define FIRST_LONG_ENTRY 0x01
|
||||
#define SECOND_LONG_ENTRY 0x42
|
||||
|
||||
//define DIR_Attr
|
||||
#define ATTR_LONG_NAME 0x0F
|
||||
#define ATTR_READ_ONLY 0x01
|
||||
#define ATTR_HIDDEN 0x02
|
||||
#define ATTR_SYSTEM 0x04
|
||||
#define ATTR_VOLUME_ID 0x08
|
||||
#define ATTR_DIRECTORY 0x10
|
||||
#define ATTR_ARCHIVE 0x20
|
||||
|
||||
struct BootSec
|
||||
{
|
||||
unsigned char BS_jmpBoot[3];
|
||||
unsigned char BS_OEMName[8];
|
||||
unsigned int BPB_BytesPerSec; //2 bytes
|
||||
unsigned char BPB_SecPerClus;
|
||||
unsigned int BPB_RsvdSecCnt; //2 bytes
|
||||
unsigned char BPB_NumFATs;
|
||||
unsigned int BPB_RootEntCnt; //2 bytes
|
||||
unsigned int BPB_TotSec16; //2 bytes
|
||||
unsigned char BPB_Media;
|
||||
unsigned int BPB_FATSz16; //2 bytes
|
||||
unsigned int BPB_SecPerTrk; //2 bytes
|
||||
unsigned int BPB_NumHeads; //2 bytes
|
||||
unsigned long BPB_HiddSec; //4 bytes
|
||||
unsigned long BPB_TotSec32; //4 bytes
|
||||
};
|
||||
|
||||
//FAT12 and FAT16 Structure Starting at Offset 36
|
||||
#define BS_DRVNUM 36
|
||||
#define BS_RESERVED1 37
|
||||
#define BS_BOOTSIG 38
|
||||
#define BS_VOLID 39
|
||||
#define BS_VOLLAB 43
|
||||
#define BS_FILSYSTYPE 54
|
||||
|
||||
//FAT32 Structure Starting at Offset 36
|
||||
#define BPB_FATSZ32 36
|
||||
#define BPB_EXTFLAGS 40
|
||||
#define BPB_FSVER 42
|
||||
#define BPB_ROOTCLUS 44
|
||||
#define BPB_FSINFO 48
|
||||
#define BPB_BKBOOTSEC 50
|
||||
#define BPB_RESERVED 52
|
||||
|
||||
#define FAT32_BS_DRVNUM 64
|
||||
#define FAT32_BS_RESERVED1 65
|
||||
#define FAT32_BS_BOOTSIG 66
|
||||
#define FAT32_BS_VOLID 67
|
||||
#define FAT32_BS_VOLLAB 71
|
||||
#define FAT32_BS_FILSYSTYPE 82
|
||||
//End of Boot Sctor and BPB Structure
|
||||
|
||||
struct DirEntry {
|
||||
unsigned char DIR_Name[11]; //8 chars filename
|
||||
unsigned char DIR_Attr; //file attributes RSHA, Longname, Drive Label, Directory
|
||||
unsigned char DIR_NTRes; //set to zero
|
||||
unsigned char DIR_CrtTimeTenth; //creation time part in milliseconds
|
||||
unsigned int DIR_CrtTime; //creation time
|
||||
unsigned int DIR_CrtDate; //creation date
|
||||
unsigned int DIR_LastAccDate; //last access date
|
||||
unsigned int DIR_FstClusHI; //first cluster high word
|
||||
unsigned int DIR_WrtTime; //last write time
|
||||
unsigned int DIR_WrtDate; //last write date
|
||||
unsigned int DIR_FstClusLO; //first cluster low word
|
||||
unsigned long DIR_FileSize;
|
||||
};
|
||||
|
||||
#endif //_FAT_H_
|
||||
@@ -1,92 +0,0 @@
|
||||
/*
|
||||
Copyright: Radig Ulrich mailto: mail@ulrichradig.de
|
||||
Author: Radig Ulrich
|
||||
Remarks:
|
||||
known Problems: none
|
||||
Version: 28.05.2004
|
||||
Description: Dieses Programm dient als Beispiel zur Ansteuerung einer MMC/SD-Memory-Card.
|
||||
Zum Zugriff auf eine MMC/SD-Karte, mu<6D> man nur die Datei mmc.c
|
||||
in sein eigenes Programm einf<6E>gen.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/eeprom.h>
|
||||
|
||||
#include "mmc.h"
|
||||
#include "fat.h"
|
||||
#include "usart.h"
|
||||
|
||||
//Hauptprogramm
|
||||
int main (void)
|
||||
{
|
||||
//SYSCLK defined in usart.h
|
||||
//Initzialisierung der seriellen Schnittstelle
|
||||
usart_init(9600);
|
||||
|
||||
//Initialisierung der MMC/SD-Karte
|
||||
usart_write("System Ready!\r\n");
|
||||
while ( mmc_init() !=0) //ist der R<>ckgabewert ungleich NULL ist ein Fehler aufgetreten
|
||||
{
|
||||
usart_write("** Keine MMC/SD Karte gefunden!! **\n");
|
||||
}
|
||||
usart_write("Karte gefunden!!\n");
|
||||
|
||||
fat_init();//laden Cluster OFFSET und Size
|
||||
//Initialisierung der MMC/SD-Karte ENDE!
|
||||
|
||||
unsigned char Buffer[512];
|
||||
unsigned int tmp;
|
||||
|
||||
mmc_read_csd (Buffer);
|
||||
|
||||
for (tmp = 0;tmp<16;tmp++)
|
||||
{
|
||||
usart_write("%x ",Buffer[tmp]);
|
||||
};
|
||||
|
||||
|
||||
//Ausgabe des Root Directory
|
||||
unsigned int Clustervar;
|
||||
unsigned char Dir_Attrib = 0;
|
||||
unsigned long Size = 0;
|
||||
usart_write("\r\nDirectory\r\n");
|
||||
for (char a = 1;a < 240;a++)
|
||||
{
|
||||
Clustervar = fat_read_dir_ent(0,a,&Size,&Dir_Attrib,Buffer);
|
||||
if (Clustervar == 0xffff)
|
||||
{
|
||||
break;
|
||||
}
|
||||
tmp = (Size & 0x0000FFFF);
|
||||
usart_write("Cluster = %4x DirA = %2x FileName = ",Clustervar,Dir_Attrib);
|
||||
usart_write("%s",Buffer);
|
||||
usart_write("\r\n");
|
||||
}
|
||||
usart_write("\r\nDirectory Ende\r\n");
|
||||
|
||||
//Lade Cluster f<>r das index.htm File in den Speicher
|
||||
Clustervar = 0;//suche im Root Verzeichnis
|
||||
if (fat_search_file((unsigned char *)"mmc.txt",&Clustervar,&Size,&Dir_Attrib,Buffer) == 1)
|
||||
{
|
||||
usart_write("\nFile Found!!\r\n");
|
||||
//Lese File und gibt es auf der seriellen Schnittstelle aus
|
||||
for (int b = 0;b<52;b++)
|
||||
{
|
||||
fat_read_file (Clustervar,Buffer,b);
|
||||
for (int a = 0;a<512;a++)
|
||||
{
|
||||
usart_write("%c",Buffer[a]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
usart_write("FERTIG!!\r\n");
|
||||
//Hauptprogramm l<>uft st<73>ndig in einer schleife und macht nichts
|
||||
while (1)
|
||||
{
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
@@ -1,404 +0,0 @@
|
||||
# WinAVR Sample makefile written by Eric B. Weddington, J<>rg Wunsch, et al.
|
||||
# Released to the Public Domain
|
||||
# Please read the make user manual!
|
||||
#
|
||||
# Additional material for this makefile was submitted by:
|
||||
# Tim Henigan
|
||||
# Peter Fleury
|
||||
# Reiner Patommel
|
||||
# Sander Pool
|
||||
# Frederik Rouleau
|
||||
# Markus Pfaff
|
||||
#
|
||||
# On command line:
|
||||
#
|
||||
# make all = Make software.
|
||||
#
|
||||
# make clean = Clean out built project files.
|
||||
#
|
||||
# make coff = Convert ELF to AVR COFF (for use with AVR Studio 3.x or VMLAB).
|
||||
#
|
||||
# make extcoff = Convert ELF to AVR Extended COFF (for use with AVR Studio
|
||||
# 4.07 or greater).
|
||||
#
|
||||
# make program = Download the hex file to the device, using avrdude. Please
|
||||
# customize the avrdude settings below first!
|
||||
#
|
||||
# make filename.s = Just compile filename.c into the assembler code only
|
||||
#
|
||||
# To rebuild project do "make clean" then "make all".
|
||||
#
|
||||
|
||||
|
||||
# MCU name
|
||||
MCU = atmega32
|
||||
#MCU = atmega644
|
||||
|
||||
# Output format. (can be srec, ihex, binary)
|
||||
FORMAT = ihex
|
||||
|
||||
# Target file name (without extension).
|
||||
TARGET = main
|
||||
|
||||
# Optimization level, can be [0, 1, 2, 3, s]. 0 turns off optimization.
|
||||
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
|
||||
OPT = s
|
||||
|
||||
|
||||
# List C source files here. (C dependencies are automatically generated.)
|
||||
SRC = $(TARGET).c mmc.c fat.c usart.c
|
||||
|
||||
# If there is more than one source file, append them above, or modify and
|
||||
# uncomment the following:
|
||||
#SRC += foo.c bar.c
|
||||
|
||||
# You can also wrap lines by appending a backslash to the end of the line:
|
||||
#SRC += baz.c \
|
||||
#xyzzy.c
|
||||
|
||||
|
||||
|
||||
# List Assembler source files here.
|
||||
# Make them always end in a capital .S. Files ending in a lowercase .s
|
||||
# will not be considered source files but generated files (assembler
|
||||
# output from the compiler), and will be deleted upon "make clean"!
|
||||
# Even though the DOS/Win* filesystem matches both .s and .S the same,
|
||||
# it will preserve the spelling of the filenames, and gcc itself does
|
||||
# care about how the name is spelled on its command-line.
|
||||
ASRC =
|
||||
|
||||
|
||||
# List any extra directories to look for include files here.
|
||||
# Each directory must be seperated by a space.
|
||||
EXTRAINCDIRS =
|
||||
|
||||
|
||||
# Optional compiler flags.
|
||||
# -g: generate debugging information (for GDB, or for COFF conversion)
|
||||
# -O*: optimization level
|
||||
# -f...: tuning, see gcc manual and avr-libc documentation
|
||||
# -Wall...: warning level
|
||||
# -Wa,...: tell GCC to pass this to the assembler.
|
||||
# -ahlms: create assembler listing
|
||||
CFLAGS = -g -O$(OPT) \
|
||||
-funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums \
|
||||
-Wall -Wstrict-prototypes \
|
||||
-Wa,-adhlns=$(<:.c=.lst) \
|
||||
$(patsubst %,-I%,$(EXTRAINCDIRS))
|
||||
|
||||
|
||||
# Set a "language standard" compiler flag.
|
||||
# Unremark just one line below to set the language standard to use.
|
||||
# gnu99 = C99 + GNU extensions. See GCC manual for more information.
|
||||
#CFLAGS += -std=c89
|
||||
#CFLAGS += -std=gnu89
|
||||
#CFLAGS += -std=c99
|
||||
CFLAGS += -std=gnu99
|
||||
|
||||
|
||||
|
||||
# Optional assembler flags.
|
||||
# -Wa,...: tell GCC to pass this to the assembler.
|
||||
# -ahlms: create listing
|
||||
# -gstabs: have the assembler create line number information; note that
|
||||
# for use in COFF files, additional information about filenames
|
||||
# and function names needs to be present in the assembler source
|
||||
# files -- see avr-libc docs [FIXME: not yet described there]
|
||||
ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
|
||||
|
||||
|
||||
|
||||
# Optional linker flags.
|
||||
# -Wl,...: tell GCC to pass this to linker.
|
||||
# -Map: create map file
|
||||
# --cref: add cross reference to map file
|
||||
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
|
||||
|
||||
|
||||
|
||||
# Additional libraries
|
||||
|
||||
# Minimalistic printf version
|
||||
#LDFLAGS += -Wl,-u,vfprintf -lprintf_min
|
||||
|
||||
# Floating point printf version (requires -lm below)
|
||||
#LDFLAGS += -Wl,-u,vfprintf -lprintf_flt
|
||||
|
||||
# -lm = math library
|
||||
LDFLAGS += -lm
|
||||
|
||||
|
||||
|
||||
|
||||
# Programming support using avrdude. Settings and variables.
|
||||
|
||||
# Programming hardware: alf avr910 avrisp bascom bsd
|
||||
# dt006 pavr picoweb pony-stk200 sp12 stk200 stk500
|
||||
#
|
||||
# Type: avrdude -c ?
|
||||
# to get a full listing.
|
||||
#
|
||||
AVRDUDE_PROGRAMMER = stk200
|
||||
|
||||
|
||||
#AVRDUDE_PORT = com1 # programmer connected to serial device
|
||||
AVRDUDE_PORT = lpt1 # programmer connected to parallel port
|
||||
|
||||
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
|
||||
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
|
||||
|
||||
AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
|
||||
|
||||
# Uncomment the following if you want avrdude's erase cycle counter.
|
||||
# Note that this counter needs to be initialized first using -Yn,
|
||||
# see avrdude manual.
|
||||
#AVRDUDE_ERASE += -y
|
||||
|
||||
# Uncomment the following if you do /not/ wish a verification to be
|
||||
# performed after programming the device.
|
||||
#AVRDUDE_FLAGS += -V
|
||||
|
||||
# Increase verbosity level. Please use this when submitting bug
|
||||
# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude>
|
||||
# to submit bug reports.
|
||||
#AVRDUDE_FLAGS += -v -v
|
||||
|
||||
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Define directories, if needed.
|
||||
DIRAVR = c:/winavr
|
||||
DIRAVRBIN = $(DIRAVR)/bin
|
||||
DIRAVRUTILS = $(DIRAVR)/utils/bin
|
||||
DIRINC = .
|
||||
DIRLIB = $(DIRAVR)/avr/lib
|
||||
|
||||
|
||||
# Define programs and commands.
|
||||
SHELL = sh
|
||||
|
||||
CC = avr-gcc
|
||||
|
||||
OBJCOPY = avr-objcopy
|
||||
OBJDUMP = avr-objdump
|
||||
SIZE = avr-size
|
||||
|
||||
|
||||
# Programming support using avrdude.
|
||||
AVRDUDE = avrdude
|
||||
|
||||
|
||||
REMOVE = rm -f
|
||||
COPY = cp
|
||||
|
||||
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
|
||||
ELFSIZE = $(SIZE) -A $(TARGET).elf
|
||||
|
||||
|
||||
|
||||
# Define Messages
|
||||
# English
|
||||
MSG_ERRORS_NONE = Errors: none
|
||||
MSG_BEGIN = -------- begin --------
|
||||
MSG_END = -------- end --------
|
||||
MSG_SIZE_BEFORE = Size before:
|
||||
MSG_SIZE_AFTER = Size after:
|
||||
MSG_COFF = Converting to AVR COFF:
|
||||
MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
|
||||
MSG_FLASH = Creating load file for Flash:
|
||||
MSG_EEPROM = Creating load file for EEPROM:
|
||||
MSG_EXTENDED_LISTING = Creating Extended Listing:
|
||||
MSG_SYMBOL_TABLE = Creating Symbol Table:
|
||||
MSG_LINKING = Linking:
|
||||
MSG_COMPILING = Compiling:
|
||||
MSG_ASSEMBLING = Assembling:
|
||||
MSG_CLEANING = Cleaning project:
|
||||
|
||||
|
||||
|
||||
|
||||
# Define all object files.
|
||||
OBJ = $(SRC:.c=.o) $(ASRC:.S=.o)
|
||||
|
||||
# Define all listing files.
|
||||
LST = $(ASRC:.S=.lst) $(SRC:.c=.lst)
|
||||
|
||||
# Combine all necessary flags and optional flags.
|
||||
# Add target processor to flags.
|
||||
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS)
|
||||
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
|
||||
|
||||
|
||||
|
||||
# Default target.
|
||||
all: begin gccversion sizebefore $(TARGET).elf $(TARGET).hex $(TARGET).eep \
|
||||
$(TARGET).lss $(TARGET).sym sizeafter finished end
|
||||
|
||||
|
||||
# Eye candy.
|
||||
# AVR Studio 3.x does not check make's exit code but relies on
|
||||
# the following magic strings to be generated by the compile job.
|
||||
begin:
|
||||
@echo
|
||||
@echo $(MSG_BEGIN)
|
||||
|
||||
finished:
|
||||
@echo $(MSG_ERRORS_NONE)
|
||||
|
||||
end:
|
||||
@echo $(MSG_END)
|
||||
@echo
|
||||
|
||||
|
||||
# Display size of file.
|
||||
sizebefore:
|
||||
@if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); echo; fi
|
||||
|
||||
sizeafter:
|
||||
@if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); echo; fi
|
||||
|
||||
|
||||
|
||||
# Display compiler version information.
|
||||
gccversion :
|
||||
@$(CC) --version
|
||||
|
||||
|
||||
|
||||
|
||||
# Convert ELF to COFF for use in debugging / simulating in
|
||||
# AVR Studio or VMLAB.
|
||||
COFFCONVERT=$(OBJCOPY) --debugging \
|
||||
--change-section-address .data-0x800000 \
|
||||
--change-section-address .bss-0x800000 \
|
||||
--change-section-address .noinit-0x800000 \
|
||||
--change-section-address .eeprom-0x810000
|
||||
|
||||
|
||||
coff: $(TARGET).elf
|
||||
@echo
|
||||
@echo $(MSG_COFF) $(TARGET).cof
|
||||
$(COFFCONVERT) -O coff-avr $< $(TARGET).cof
|
||||
|
||||
|
||||
extcoff: $(TARGET).elf
|
||||
@echo
|
||||
@echo $(MSG_EXTENDED_COFF) $(TARGET).cof
|
||||
$(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof
|
||||
|
||||
|
||||
|
||||
|
||||
# Program the device.
|
||||
program: $(TARGET).hex $(TARGET).eep
|
||||
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
|
||||
|
||||
|
||||
|
||||
|
||||
# Create final output files (.hex, .eep) from ELF output file.
|
||||
%.hex: %.elf
|
||||
@echo
|
||||
@echo $(MSG_FLASH) $@
|
||||
$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
|
||||
|
||||
%.eep: %.elf
|
||||
@echo
|
||||
@echo $(MSG_EEPROM) $@
|
||||
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
|
||||
--change-section-lma .eeprom=0 -O $(FORMAT) $< $@
|
||||
|
||||
# Create extended listing file from ELF output file.
|
||||
%.lss: %.elf
|
||||
@echo
|
||||
@echo $(MSG_EXTENDED_LISTING) $@
|
||||
$(OBJDUMP) -h -S $< > $@
|
||||
|
||||
# Create a symbol table from ELF output file.
|
||||
%.sym: %.elf
|
||||
@echo
|
||||
@echo $(MSG_SYMBOL_TABLE) $@
|
||||
avr-nm -n $< > $@
|
||||
|
||||
|
||||
|
||||
# Link: create ELF output file from object files.
|
||||
.SECONDARY : $(TARGET).elf
|
||||
.PRECIOUS : $(OBJ)
|
||||
%.elf: $(OBJ)
|
||||
@echo
|
||||
@echo $(MSG_LINKING) $@
|
||||
$(CC) $(ALL_CFLAGS) $(OBJ) --output $@ $(LDFLAGS)
|
||||
|
||||
|
||||
# Compile: create object files from C source files.
|
||||
%.o : %.c
|
||||
@echo
|
||||
@echo $(MSG_COMPILING) $<
|
||||
$(CC) -c $(ALL_CFLAGS) $< -o $@
|
||||
|
||||
|
||||
# Compile: create assembler files from C source files.
|
||||
%.s : %.c
|
||||
$(CC) -S $(ALL_CFLAGS) $< -o $@
|
||||
|
||||
|
||||
# Assemble: create object files from assembler source files.
|
||||
%.o : %.S
|
||||
@echo
|
||||
@echo $(MSG_ASSEMBLING) $<
|
||||
$(CC) -c $(ALL_ASFLAGS) $< -o $@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Target: clean project.
|
||||
clean: begin clean_list finished end
|
||||
|
||||
clean_list :
|
||||
@echo
|
||||
@echo $(MSG_CLEANING)
|
||||
$(REMOVE) $(TARGET).hex
|
||||
$(REMOVE) $(TARGET).eep
|
||||
$(REMOVE) $(TARGET).obj
|
||||
$(REMOVE) $(TARGET).cof
|
||||
$(REMOVE) $(TARGET).elf
|
||||
$(REMOVE) $(TARGET).map
|
||||
$(REMOVE) $(TARGET).obj
|
||||
$(REMOVE) $(TARGET).a90
|
||||
$(REMOVE) $(TARGET).sym
|
||||
$(REMOVE) $(TARGET).lnk
|
||||
$(REMOVE) $(TARGET).lss
|
||||
$(REMOVE) $(OBJ)
|
||||
$(REMOVE) $(LST)
|
||||
$(REMOVE) $(SRC:.c=.s)
|
||||
$(REMOVE) $(SRC:.c=.d)
|
||||
|
||||
|
||||
# Automatically generate C source code dependencies.
|
||||
# (Code originally taken from the GNU make user manual and modified
|
||||
# (See README.txt Credits).)
|
||||
#
|
||||
# Note that this will work with sh (bash) and sed that is shipped with WinAVR
|
||||
# (see the SHELL variable defined above).
|
||||
# This may not work with other shells or other seds.
|
||||
#
|
||||
%.d: %.c
|
||||
set -e; $(CC) -MM $(ALL_CFLAGS) $< \
|
||||
| sed 's,\(.*\)\.o[ :]*,\1.o \1.d : ,g' > $@; \
|
||||
[ -s $@ ] || rm -f $@
|
||||
|
||||
|
||||
# Remove the '-' if you want to see the dependency files generated.
|
||||
-include $(SRC:.c=.d)
|
||||
|
||||
|
||||
|
||||
# Listing of phony targets.
|
||||
.PHONY : all begin finish end sizebefore sizeafter gccversion coff extcoff \
|
||||
clean clean_list program
|
||||
|
||||
@@ -1,324 +0,0 @@
|
||||
/*#######################################################################################
|
||||
Connect AVR to MMC/SD
|
||||
|
||||
Copyright (C) 2004 Ulrich Radig
|
||||
|
||||
Bei Fragen und Verbesserungen wendet euch per EMail an
|
||||
|
||||
mail@ulrichradig.de
|
||||
|
||||
oder im Forum meiner Web Page : www.ulrichradig.de
|
||||
|
||||
Dieses Programm ist freie Software. Sie k<>nnen es unter den Bedingungen der
|
||||
GNU General Public License, wie von der Free Software Foundation ver<65>ffentlicht,
|
||||
weitergeben und/oder modifizieren, entweder gem<65><6D> Version 2 der Lizenz oder
|
||||
(nach Ihrer Option) jeder sp<73>teren Version.
|
||||
|
||||
Die Ver<65>ffentlichung dieses Programms erfolgt in der Hoffnung,
|
||||
da<EFBFBD> es Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE,
|
||||
sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT
|
||||
F<EFBFBD>R EINEN BESTIMMTEN ZWECK. Details finden Sie in der GNU General Public License.
|
||||
|
||||
Sie sollten eine Kopie der GNU General Public License zusammen mit diesem
|
||||
Programm erhalten haben.
|
||||
Falls nicht, schreiben Sie an die Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||||
#######################################################################################*/
|
||||
|
||||
#include "mmc.h"
|
||||
|
||||
//############################################################################
|
||||
//Routine zur Initialisierung der MMC/SD-Karte (SPI-MODE)
|
||||
unsigned char mmc_init ()
|
||||
//############################################################################
|
||||
{
|
||||
unsigned int Timeout = 0;
|
||||
|
||||
//Konfiguration des Ports an der die MMC/SD-Karte angeschlossen wurde
|
||||
MMC_Direction_REG &=~(1<<SPI_DI); //Setzen von Pin MMC_DI auf Input
|
||||
MMC_Direction_REG |= (1<<SPI_Clock); //Setzen von Pin MMC_Clock auf Output
|
||||
MMC_Direction_REG |= (1<<SPI_DO); //Setzen von Pin MMC_DO auf Output
|
||||
MMC_Direction_REG |= (1<<MMC_Chip_Select); //Setzen von Pin MMC_Chip_Select auf Output
|
||||
MMC_Direction_REG |= (1<<SPI_SS);
|
||||
MMC_Write |= (1<<MMC_Chip_Select); //Setzt den Pin MMC_Chip_Select auf High Pegel
|
||||
|
||||
for(unsigned char a=0;a<200;a++){
|
||||
nop();
|
||||
}; //Wartet eine kurze Zeit
|
||||
|
||||
#if SPI_Mode
|
||||
//Aktiviren des SPI - Bus, Clock = Idel LOW
|
||||
//SPI Clock teilen durch 128
|
||||
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPR1); //Enable SPI, SPI in Master Mode
|
||||
SPSR = (0<<SPI2X);
|
||||
#endif
|
||||
|
||||
//Initialisiere MMC/SD-Karte in den SPI-Mode
|
||||
for (unsigned char b = 0;b<0x0f;b++) //Sendet min 74+ Clocks an die MMC/SD-Karte
|
||||
{
|
||||
mmc_write_byte(0xff);
|
||||
}
|
||||
|
||||
//Sendet Commando CMD0 an MMC/SD-Karte
|
||||
unsigned char CMD[] = {0x40,0x00,0x00,0x00,0x00,0x95};
|
||||
while(mmc_write_command (CMD) !=1)
|
||||
{
|
||||
if (Timeout++ > 200)
|
||||
{
|
||||
MMC_Disable();
|
||||
return(1); //Abbruch bei Commando1 (Return Code1)
|
||||
}
|
||||
}
|
||||
//Sendet Commando CMD1 an MMC/SD-Karte
|
||||
Timeout = 0;
|
||||
CMD[0] = 0x41;//Commando 1
|
||||
CMD[5] = 0xFF;
|
||||
while( mmc_write_command (CMD) !=0)
|
||||
{
|
||||
if (Timeout++ > 400)
|
||||
{
|
||||
MMC_Disable();
|
||||
return(2); //Abbruch bei Commando2 (Return Code2)
|
||||
}
|
||||
}
|
||||
#if SPI_Mode
|
||||
//SPI Bus auf max Geschwindigkeit
|
||||
SPCR &= ~((1<<SPR0) | (1<<SPR1));
|
||||
SPSR = SPSR|(1<<SPI2X);
|
||||
#endif
|
||||
|
||||
//set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
|
||||
MMC_Disable();
|
||||
return(0);
|
||||
}
|
||||
|
||||
//############################################################################
|
||||
//Sendet ein Commando an die MMC/SD-Karte
|
||||
unsigned char mmc_write_command (unsigned char *cmd)
|
||||
//############################################################################
|
||||
{
|
||||
unsigned char tmp = 0xff;
|
||||
unsigned int Timeout = 0;
|
||||
|
||||
//set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
|
||||
MMC_Disable();
|
||||
|
||||
//sendet 8 Clock Impulse
|
||||
mmc_write_byte(0xFF);
|
||||
|
||||
//set MMC_Chip_Select to low (MMC/SD-Karte Aktiv)
|
||||
MMC_Enable();
|
||||
|
||||
//sendet 6 Byte Commando
|
||||
for (unsigned char a = 0;a<0x06;a++) //sendet 6 Byte Commando zur MMC/SD-Karte
|
||||
{
|
||||
mmc_write_byte(*cmd++);
|
||||
}
|
||||
|
||||
//Wartet auf ein g<>ltige Antwort von der MMC/SD-Karte
|
||||
while (tmp == 0xff)
|
||||
{
|
||||
tmp = mmc_read_byte();
|
||||
if (Timeout++ > 500)
|
||||
{
|
||||
break; //Abbruch da die MMC/SD-Karte nicht Antwortet
|
||||
}
|
||||
}
|
||||
return(tmp);
|
||||
}
|
||||
|
||||
//############################################################################
|
||||
//Routine zum Empfangen eines Bytes von der MMC-Karte
|
||||
unsigned char mmc_read_byte (void)
|
||||
//############################################################################
|
||||
{
|
||||
unsigned char Byte = 0;
|
||||
#if SPI_Mode //Routine f<>r Hardware SPI
|
||||
SPDR = 0xff;
|
||||
while(!(SPSR & (1<<SPIF))){};
|
||||
Byte = SPDR;
|
||||
|
||||
#else //Routine f<>r Software SPI
|
||||
for (unsigned char a=8; a>0; a--) //das Byte wird Bitweise nacheinander Empangen MSB First
|
||||
{
|
||||
MMC_Write &=~(1<<SPI_Clock); //erzeugt ein Clock Impuls (Low)
|
||||
|
||||
if (bit_is_set(MMC_Read,SPI_DI) > 0) //Lesen des Pegels von MMC_DI
|
||||
{
|
||||
Byte |= (1<<(a-1));
|
||||
}
|
||||
else
|
||||
{
|
||||
Byte &=~(1<<(a-1));
|
||||
}
|
||||
MMC_Write |=(1<<SPI_Clock); //setzt Clock Impuls wieder auf (High)
|
||||
}
|
||||
#endif
|
||||
return (Byte);
|
||||
}
|
||||
|
||||
|
||||
//############################################################################
|
||||
//Routine zum Senden eines Bytes zur MMC-Karte
|
||||
void mmc_write_byte (unsigned char Byte)
|
||||
//############################################################################
|
||||
{
|
||||
#if SPI_Mode //Routine f<>r Hardware SPI
|
||||
SPDR = Byte; //Sendet ein Byte
|
||||
while(!(SPSR & (1<<SPIF))) //Wartet bis Byte gesendet wurde
|
||||
{
|
||||
}
|
||||
#else //Routine f<>r Software SPI
|
||||
for (unsigned char a=8; a>0; a--) //das Byte wird Bitweise nacheinander Gesendet MSB First
|
||||
{
|
||||
if (bit_is_set(Byte,(a-1))>0) //Ist Bit a in Byte gesetzt
|
||||
{
|
||||
MMC_Write |= (1<<SPI_DO); //Set Output High
|
||||
}
|
||||
else
|
||||
{
|
||||
MMC_Write &= ~(1<<SPI_DO); //Set Output Low
|
||||
}
|
||||
MMC_Write &= ~(1<<SPI_Clock); //erzeugt ein Clock Impuls (LOW)
|
||||
|
||||
MMC_Write |= (1<<SPI_Clock); //setzt Clock Impuls wieder auf (High)
|
||||
}
|
||||
MMC_Write |= (1<<SPI_DO); //setzt Output wieder auf High
|
||||
#endif
|
||||
}
|
||||
|
||||
//############################################################################
|
||||
//Routine zum schreiben eines Blocks(512Byte) auf die MMC/SD-Karte
|
||||
unsigned char mmc_write_sector (unsigned long addr,unsigned char *Buffer)
|
||||
//############################################################################
|
||||
{
|
||||
unsigned char tmp;
|
||||
//Commando 24 zum schreiben eines Blocks auf die MMC/SD - Karte
|
||||
unsigned char cmd[] = {0x58,0x00,0x00,0x00,0x00,0xFF};
|
||||
|
||||
/*Die Adressierung der MMC/SD-Karte wird in Bytes angegeben,
|
||||
addr wird von Blocks zu Bytes umgerechnet danach werden
|
||||
diese in das Commando eingef<65>gt*/
|
||||
|
||||
addr = addr << 9; //addr = addr * 512
|
||||
|
||||
cmd[1] = ((addr & 0xFF000000) >>24 );
|
||||
cmd[2] = ((addr & 0x00FF0000) >>16 );
|
||||
cmd[3] = ((addr & 0x0000FF00) >>8 );
|
||||
|
||||
//Sendet Commando cmd24 an MMC/SD-Karte (Write 1 Block/512 Bytes)
|
||||
tmp = mmc_write_command (cmd);
|
||||
if (tmp != 0)
|
||||
{
|
||||
return(tmp);
|
||||
}
|
||||
|
||||
//Wartet einen Moment und sendet einen Clock an die MMC/SD-Karte
|
||||
for (unsigned char a=0;a<100;a++)
|
||||
{
|
||||
mmc_read_byte();
|
||||
}
|
||||
|
||||
//Sendet Start Byte an MMC/SD-Karte
|
||||
mmc_write_byte(0xFE);
|
||||
|
||||
//Schreiben des Bolcks (512Bytes) auf MMC/SD-Karte
|
||||
for (unsigned int a=0;a<512;a++)
|
||||
{
|
||||
mmc_write_byte(*Buffer++);
|
||||
}
|
||||
|
||||
//CRC-Byte schreiben
|
||||
mmc_write_byte(0xFF); //Schreibt Dummy CRC
|
||||
mmc_write_byte(0xFF); //CRC Code wird nicht benutzt
|
||||
|
||||
//Fehler beim schreiben? (Data Response XXX00101 = OK)
|
||||
if((mmc_read_byte()&0x1F) != 0x05) return(1);
|
||||
|
||||
//Wartet auf MMC/SD-Karte Bussy
|
||||
while (mmc_read_byte() != 0xff){};
|
||||
|
||||
//set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
|
||||
MMC_Disable();
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
//############################################################################
|
||||
//Routine zum lesen des CID Registers von der MMC/SD-Karte (16Bytes)
|
||||
void mmc_read_block(unsigned char *cmd,unsigned char *Buffer,unsigned int Bytes)
|
||||
//############################################################################
|
||||
{
|
||||
//Sendet Commando cmd an MMC/SD-Karte
|
||||
if (mmc_write_command (cmd) != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//Wartet auf Start Byte von der MMC/SD-Karte (FEh/Start Byte)
|
||||
|
||||
while (mmc_read_byte() != 0xfe){};
|
||||
|
||||
//Lesen des Bolcks (normal 512Bytes) von MMC/SD-Karte
|
||||
for (unsigned int a=0;a<Bytes;a++)
|
||||
{
|
||||
*Buffer++ = mmc_read_byte();
|
||||
}
|
||||
//CRC-Byte auslesen
|
||||
mmc_read_byte();//CRC - Byte wird nicht ausgewertet
|
||||
mmc_read_byte();//CRC - Byte wird nicht ausgewertet
|
||||
|
||||
//set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
|
||||
MMC_Disable();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//############################################################################
|
||||
//Routine zum lesen eines Blocks(512Byte) von der MMC/SD-Karte
|
||||
unsigned char mmc_read_sector (unsigned long addr,unsigned char *Buffer)
|
||||
//############################################################################
|
||||
{
|
||||
//Commando 16 zum lesen eines Blocks von der MMC/SD - Karte
|
||||
unsigned char cmd[] = {0x51,0x00,0x00,0x00,0x00,0xFF};
|
||||
|
||||
/*Die Adressierung der MMC/SD-Karte wird in Bytes angegeben,
|
||||
addr wird von Blocks zu Bytes umgerechnet danach werden
|
||||
diese in das Commando eingef<65>gt*/
|
||||
|
||||
addr = addr << 9; //addr = addr * 512
|
||||
|
||||
cmd[1] = ((addr & 0xFF000000) >>24 );
|
||||
cmd[2] = ((addr & 0x00FF0000) >>16 );
|
||||
cmd[3] = ((addr & 0x0000FF00) >>8 );
|
||||
|
||||
mmc_read_block(cmd,Buffer,512);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
//############################################################################
|
||||
//Routine zum lesen des CID Registers von der MMC/SD-Karte (16Bytes)
|
||||
unsigned char mmc_read_cid (unsigned char *Buffer)
|
||||
//############################################################################
|
||||
{
|
||||
//Commando zum lesen des CID Registers
|
||||
unsigned char cmd[] = {0x4A,0x00,0x00,0x00,0x00,0xFF};
|
||||
|
||||
mmc_read_block(cmd,Buffer,16);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
//############################################################################
|
||||
//Routine zum lesen des CSD Registers von der MMC/SD-Karte (16Bytes)
|
||||
unsigned char mmc_read_csd (unsigned char *Buffer)
|
||||
//############################################################################
|
||||
{
|
||||
//Commando zum lesen des CSD Registers
|
||||
unsigned char cmd[] = {0x49,0x00,0x00,0x00,0x00,0xFF};
|
||||
|
||||
mmc_read_block(cmd,Buffer,16);
|
||||
|
||||
return(0);
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
/*#######################################################################################
|
||||
Connect ARM to MMC/SD
|
||||
|
||||
Copyright (C) 2004 Ulrich Radig
|
||||
#######################################################################################*/
|
||||
|
||||
#ifndef _MMC_H_
|
||||
#define _MMC_H_
|
||||
|
||||
#include <avr/io.h>
|
||||
|
||||
#define SPI_Mode 1 //1 = Hardware SPI | 0 = Software SPI
|
||||
//#define SPI_Mode 0
|
||||
|
||||
#define MMC_Write PORTB //Port an der die MMC/SD-Karte angeschlossen ist also des SPI
|
||||
#define MMC_Read PINB
|
||||
#define MMC_Direction_REG DDRB
|
||||
|
||||
#if defined (__AVR_ATmega128__)
|
||||
#define SPI_DI 3 //Port Pin an dem Data Output der MMC/SD-Karte angeschlossen ist
|
||||
#define SPI_DO 2 //Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist
|
||||
#define SPI_Clock 1 //Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk)
|
||||
#define MMC_Chip_Select 4 //Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist
|
||||
#define SPI_SS 0 //Nicht Benutz mu<6D> aber definiert werden
|
||||
#endif
|
||||
|
||||
#if defined (__AVR_ATmega32__)
|
||||
#define SPI_DI 6 //Port Pin an dem Data Output der MMC/SD-Karte angeschlossen ist
|
||||
#define SPI_DO 5 //Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist
|
||||
#define SPI_Clock 7 //Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk)
|
||||
#define MMC_Chip_Select 3 //Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist
|
||||
#define SPI_SS 4 //Nicht Benutz mu<6D> aber definiert werden
|
||||
#endif
|
||||
|
||||
#if defined (__AVR_ATmega644__)
|
||||
#define SPI_DI 6 //Port Pin an dem Data Output der MMC/SD-Karte angeschlossen ist
|
||||
#define SPI_DO 5 //Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist
|
||||
#define SPI_Clock 7 //Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk)
|
||||
#define MMC_Chip_Select 1 //Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist
|
||||
#define SPI_SS 4 //Nicht Benutz mu<6D> aber definiert werden
|
||||
#endif
|
||||
|
||||
//Prototypes
|
||||
extern unsigned char mmc_read_byte(void);
|
||||
|
||||
extern void mmc_write_byte(unsigned char);
|
||||
|
||||
extern void mmc_read_block(unsigned char *,unsigned char *,unsigned in);
|
||||
|
||||
extern unsigned char mmc_init(void);
|
||||
|
||||
extern unsigned char mmc_read_sector (unsigned long,unsigned char *);
|
||||
|
||||
extern unsigned char mmc_write_sector (unsigned long,unsigned char *);
|
||||
|
||||
extern unsigned char mmc_write_command (unsigned char *);
|
||||
|
||||
extern unsigned char mmc_read_csd (unsigned char *);
|
||||
|
||||
extern unsigned char mmc_read_cid (unsigned char *);
|
||||
|
||||
//set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
|
||||
#define MMC_Disable() MMC_Write|= (1<<MMC_Chip_Select);
|
||||
|
||||
//set MMC_Chip_Select to low (MMC/SD-Karte Aktiv)
|
||||
#define MMC_Enable() MMC_Write&=~(1<<MMC_Chip_Select);
|
||||
|
||||
#define nop() __asm__ __volatile__ ("nop" ::)
|
||||
|
||||
#endif //_MMC_H_
|
||||
|
||||
|
||||
@@ -1,152 +0,0 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
Copyright: Radig Ulrich mailto: mail@ulrichradig.de
|
||||
Author: Radig Ulrich
|
||||
Remarks:
|
||||
known Problems: none
|
||||
Version: 24.10.2007
|
||||
Description: RS232 Routinen
|
||||
|
||||
Dieses Programm ist freie Software. Sie k<>nnen es unter den Bedingungen der
|
||||
GNU General Public License, wie von der Free Software Foundation ver<65>ffentlicht,
|
||||
weitergeben und/oder modifizieren, entweder gem<65><6D> Version 2 der Lizenz oder
|
||||
(nach Ihrer Option) jeder sp<73>teren Version.
|
||||
|
||||
Die Ver<65>ffentlichung dieses Programms erfolgt in der Hoffnung,
|
||||
da<64> es Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE,
|
||||
sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT
|
||||
F<>R EINEN BESTIMMTEN ZWECK. Details finden Sie in der GNU General Public License.
|
||||
|
||||
Sie sollten eine Kopie der GNU General Public License zusammen mit diesem
|
||||
Programm erhalten haben.
|
||||
Falls nicht, schreiben Sie an die Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||||
------------------------------------------------------------------------------*/
|
||||
#include "usart.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//Init serielle Schnittstelle
|
||||
void usart_init(unsigned long baudrate)
|
||||
{
|
||||
//Serielle Schnittstelle 1
|
||||
//Enable TXEN im Register UCR TX-Data Enable
|
||||
UCR =(1 << TXEN | 1 << RXEN | 1<< RXCIE);
|
||||
// 0 = Parity Mode Disabled
|
||||
// 1 = Parity Mode Enabled, Even Parity
|
||||
// 2 = Parity Mode Enabled, Odd Parity
|
||||
//UCSRC = 0x06 + ((parity+1)<<4);
|
||||
//UCSRC |= (1<<USBS);
|
||||
//Teiler wird gesetzt
|
||||
UBRR=(F_CPU / (baudrate * 16L) - 1);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//Routine f<>r die Serielle Ausgabe eines Zeichens (Schnittstelle0)
|
||||
void usart_write_char(char c)
|
||||
{
|
||||
//Warten solange bis Zeichen gesendet wurde
|
||||
while(!(USR & (1<<UDRE)));
|
||||
//Ausgabe des Zeichens
|
||||
UDR = c;
|
||||
return;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void usart_write_P (const char *Buffer,...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start (ap, Buffer);
|
||||
|
||||
int format_flag;
|
||||
char str_buffer[10];
|
||||
char str_null_buffer[10];
|
||||
char move = 0;
|
||||
char Base = 0;
|
||||
int tmp = 0;
|
||||
char by;
|
||||
char *ptr;
|
||||
|
||||
//Ausgabe der Zeichen
|
||||
for(;;)
|
||||
{
|
||||
by = pgm_read_byte(Buffer++);
|
||||
if(by==0) break; // end of format string
|
||||
|
||||
if (by == '%')
|
||||
{
|
||||
by = pgm_read_byte(Buffer++);
|
||||
if (isdigit(by)>0)
|
||||
{
|
||||
|
||||
str_null_buffer[0] = by;
|
||||
str_null_buffer[1] = '\0';
|
||||
move = atoi(str_null_buffer);
|
||||
by = pgm_read_byte(Buffer++);
|
||||
}
|
||||
|
||||
switch (by)
|
||||
{
|
||||
case 's':
|
||||
ptr = va_arg(ap,char *);
|
||||
while(*ptr) { usart_write_char(*ptr++); }
|
||||
break;
|
||||
case 'b':
|
||||
Base = 2;
|
||||
goto ConversionLoop;
|
||||
case 'c':
|
||||
//Int to char
|
||||
format_flag = va_arg(ap,int);
|
||||
usart_write_char (format_flag++);
|
||||
break;
|
||||
case 'i':
|
||||
Base = 10;
|
||||
goto ConversionLoop;
|
||||
case 'o':
|
||||
Base = 8;
|
||||
goto ConversionLoop;
|
||||
case 'x':
|
||||
Base = 16;
|
||||
//****************************
|
||||
ConversionLoop:
|
||||
//****************************
|
||||
itoa(va_arg(ap,int),str_buffer,Base);
|
||||
int b=0;
|
||||
while (str_buffer[b++] != 0){};
|
||||
b--;
|
||||
if (b<move)
|
||||
{
|
||||
move -=b;
|
||||
for (tmp = 0;tmp<move;tmp++)
|
||||
{
|
||||
str_null_buffer[tmp] = '0';
|
||||
}
|
||||
//tmp ++;
|
||||
str_null_buffer[tmp] = '\0';
|
||||
strcat(str_null_buffer,str_buffer);
|
||||
strcpy(str_buffer,str_null_buffer);
|
||||
}
|
||||
usart_write_str (str_buffer);
|
||||
move =0;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
usart_write_char ( by );
|
||||
}
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//Ausgabe eines Strings
|
||||
void usart_write_str(char *str)
|
||||
{
|
||||
while (*str)
|
||||
{
|
||||
usart_write_char(*str++);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
Copyright: Radig Ulrich mailto: mail@ulrichradig.de
|
||||
Author: Radig Ulrich
|
||||
Remarks:
|
||||
known Problems: none
|
||||
Version: 24.10.2007
|
||||
Description: RS232 Routinen
|
||||
|
||||
Dieses Programm ist freie Software. Sie k<>nnen es unter den Bedingungen der
|
||||
GNU General Public License, wie von der Free Software Foundation ver<65>ffentlicht,
|
||||
weitergeben und/oder modifizieren, entweder gem<65><6D> Version 2 der Lizenz oder
|
||||
(nach Ihrer Option) jeder sp<73>teren Version.
|
||||
|
||||
Die Ver<65>ffentlichung dieses Programms erfolgt in der Hoffnung,
|
||||
da<64> es Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE,
|
||||
sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT
|
||||
F<>R EINEN BESTIMMTEN ZWECK. Details finden Sie in der GNU General Public License.
|
||||
|
||||
Sie sollten eine Kopie der GNU General Public License zusammen mit diesem
|
||||
Programm erhalten haben.
|
||||
Falls nicht, schreiben Sie an die Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||||
------------------------------------------------------------------------------*/
|
||||
#ifndef _UART_H
|
||||
#define _UART_H
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//Die Quarzfrequenz auf dem Board
|
||||
#ifndef F_CPU
|
||||
#define F_CPU 14745600UL
|
||||
#endif //SYSCLK
|
||||
|
||||
//Anpassen der seriellen Schnittstellen Register wenn ein ATMega128 benutzt wird
|
||||
#if defined (__AVR_ATmega128__)
|
||||
#define USR UCSR0A
|
||||
#define UCR UCSR0B
|
||||
#define UDR UDR0
|
||||
#define UBRR UBRR0L
|
||||
#define USART_RX USART0_RX_vect
|
||||
#endif
|
||||
|
||||
#if defined (__AVR_ATmega644__) || defined (__AVR_ATmega644P__)
|
||||
#define USR UCSR0A
|
||||
#define UCR UCSR0B
|
||||
#define UBRR UBRR0L
|
||||
#define EICR EICRB
|
||||
#define TXEN TXEN0
|
||||
#define RXEN RXEN0
|
||||
#define RXCIE RXCIE0
|
||||
#define UDR UDR0
|
||||
#define UDRE UDRE0
|
||||
#define USART_RX USART0_RX_vect
|
||||
#endif
|
||||
|
||||
#if defined (__AVR_ATmega32__)
|
||||
#define USR UCSRA
|
||||
#define UCR UCSRB
|
||||
#define UBRR UBRRL
|
||||
#define EICR EICRB
|
||||
#define USART_RX USART_RXC_vect
|
||||
#endif
|
||||
|
||||
#if defined (__AVR_ATmega8__)
|
||||
#define USR UCSRA
|
||||
#define UCR UCSRB
|
||||
#define UBRR UBRRL
|
||||
#endif
|
||||
|
||||
#if defined (__AVR_ATmega88__)
|
||||
#define USR UCSR0A
|
||||
#define UCR UCSR0B
|
||||
#define UBRR UBRR0L
|
||||
#define TXEN TXEN0
|
||||
#define UDR UDR0
|
||||
#define UDRE UDRE0
|
||||
#endif
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void usart_init(unsigned long baudrate);
|
||||
void usart_write_char(char c);
|
||||
void usart_write_str(char *str);
|
||||
|
||||
void usart_write_P (const char *Buffer,...);
|
||||
#define usart_write(format, args...) usart_write_P(PSTR(format) , ## args)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#endif //_UART_H
|
||||
@@ -1,406 +0,0 @@
|
||||
# Hey Emacs, this is a -*- makefile -*-
|
||||
#
|
||||
# WinAVR makefile written by Eric B. Weddington, J<>rg Wunsch, et al.
|
||||
# Released to the Public Domain
|
||||
# Please read the make user manual!
|
||||
#
|
||||
# Additional material for this makefile was submitted by:
|
||||
# Tim Henigan
|
||||
# Peter Fleury
|
||||
# Reiner Patommel
|
||||
# Sander Pool
|
||||
# Frederik Rouleau
|
||||
# Markus Pfaff
|
||||
#
|
||||
# On command line:
|
||||
#
|
||||
# make all = Make software.
|
||||
#
|
||||
# make clean = Clean out built project files.
|
||||
#
|
||||
# make coff = Convert ELF to AVR COFF (for use with AVR Studio 3.x or VMLAB).
|
||||
#
|
||||
# make extcoff = Convert ELF to AVR Extended COFF (for use with AVR Studio
|
||||
# 4.07 or greater).
|
||||
#
|
||||
# make program = Download the hex file to the device, using avrdude. Please
|
||||
# customize the avrdude settings below first!
|
||||
#
|
||||
# make filename.s = Just compile filename.c into the assembler code only
|
||||
#
|
||||
# To rebuild project do "make clean" then "make all".
|
||||
#
|
||||
|
||||
# mth 2004/09
|
||||
# Differences from WinAVR 20040720 sample:
|
||||
# - DEPFLAGS according to Eric Weddingtion's fix (avrfreaks/gcc-forum)
|
||||
# - F_OSC Define in CFLAGS and AFLAGS
|
||||
|
||||
|
||||
# MCU name
|
||||
MCU = atmega168
|
||||
#MCU = atmega8
|
||||
#MCU = atmega32
|
||||
|
||||
# Main Oscillator Frequency
|
||||
# This is only used to define F_OSC in all assembler and c-sources.
|
||||
#F_OSC = 3686400
|
||||
|
||||
# Output format. (can be srec, ihex, binary)
|
||||
FORMAT = ihex
|
||||
|
||||
# Target file name (without extension).
|
||||
TARGET = main
|
||||
#TARGET = main_spi
|
||||
|
||||
# List C source files here. (C dependencies are automatically generated.)
|
||||
SRC =$(TARGET).c command.c uart.c fat.c file.c mmc.c
|
||||
#SRC =$(TARGET).c
|
||||
|
||||
|
||||
# List Assembler source files here.
|
||||
# Make them always end in a capital .S. Files ending in a lowercase .s
|
||||
# will not be considered source files but generated files (assembler
|
||||
# output from the compiler), and will be deleted upon "make clean"!
|
||||
# Even though the DOS/Win* filesystem matches both .s and .S the same,
|
||||
# it will preserve the spelling of the filenames, and gcc itself does
|
||||
# care about how the name is spelled on its command-line.
|
||||
ASRC =
|
||||
|
||||
|
||||
|
||||
# Optimization level, can be [0, 1, 2, 3, s].
|
||||
# 0 = turn off optimization. s = optimize for size.
|
||||
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
|
||||
OPT = 2
|
||||
|
||||
# Debugging format.
|
||||
# Native formats for AVR-GCC's -g are stabs [default], or dwarf-2.
|
||||
# AVR (extended) COFF requires stabs, plus an avr-objcopy run.
|
||||
#DEBUG = stabs
|
||||
DEBUG = dwarf-2
|
||||
|
||||
# List any extra directories to look for include files here.
|
||||
# Each directory must be seperated by a space.
|
||||
EXTRAINCDIRS =
|
||||
|
||||
|
||||
# Compiler flag to set the C Standard level.
|
||||
# c89 - "ANSI" C
|
||||
# gnu89 - c89 plus GCC extensions
|
||||
# c99 - ISO C99 standard (not yet fully implemented)
|
||||
# gnu99 - c99 plus GCC extensions
|
||||
CSTANDARD = -std=gnu89
|
||||
|
||||
# Place -D or -U options here
|
||||
CDEFS =
|
||||
|
||||
# Place -I options here
|
||||
CINCS =
|
||||
|
||||
|
||||
# Compiler flags.
|
||||
# -g*: generate debugging information
|
||||
# -O*: optimization level
|
||||
# -f...: tuning, see GCC manual and avr-libc documentation
|
||||
# -Wall...: warning level
|
||||
# -Wa,...: tell GCC to pass this to the assembler.
|
||||
# -adhlns...: create assembler listing
|
||||
CFLAGS = -g$(DEBUG)
|
||||
CFLAGS += $(CDEFS) $(CINCS)
|
||||
CFLAGS += -O$(OPT)
|
||||
#********************************************************************************************** -mcall-prologues
|
||||
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -mcall-prologues -ffreestanding
|
||||
#-fsplit-wide-types
|
||||
CFLAGS += -Wall -Wstrict-prototypes
|
||||
CFLAGS += -Wa,-adhlns=$(<:.c=.lst)
|
||||
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
|
||||
CFLAGS += $(CSTANDARD)
|
||||
CFLAGS += -DF_OSC=$(F_OSC)
|
||||
|
||||
|
||||
|
||||
# Assembler flags.
|
||||
# -Wa,...: tell GCC to pass this to the assembler.
|
||||
# -ahlms: create listing
|
||||
# -gstabs: have the assembler create line number information; note that
|
||||
# for use in COFF files, additional information about filenames
|
||||
# and function names needs to be present in the assembler source
|
||||
# files -- see avr-libc docs [FIXME: not yet described there]
|
||||
ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
|
||||
ASFLAGS += -DF_OSC=$(F_OSC)
|
||||
|
||||
|
||||
#Additional libraries.
|
||||
|
||||
# Minimalistic printf version
|
||||
#PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
|
||||
|
||||
# Floating point printf version (requires MATH_LIB = -lm below)
|
||||
#PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt
|
||||
|
||||
#PRINTF_LIB =
|
||||
|
||||
# Minimalistic scanf version
|
||||
#SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min
|
||||
|
||||
# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
|
||||
#SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt
|
||||
|
||||
#SCANF_LIB =
|
||||
|
||||
MATH_LIB = -lm
|
||||
|
||||
# External memory options
|
||||
|
||||
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
|
||||
# used for variables (.data/.bss) and heap (malloc()).
|
||||
#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff
|
||||
|
||||
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
|
||||
# only used for heap (malloc()).
|
||||
#EXTMEMOPTS = -Wl,--defsym=__heap_start=0x801100,--defsym=__heap_end=0x80ffff
|
||||
#********************************************************************************************************* -Wl
|
||||
#EXTMEMOPTS = -Wl,--section-start=bar=0x80002B,--defsym=bazz=0x80002A
|
||||
#EXTMEMOPTS = -Wl,--defsym=bytesOfSec=0x80004A
|
||||
|
||||
# Linker flags.
|
||||
# -Wl,...: tell GCC to pass this to linker.
|
||||
# -Map: create map file
|
||||
# --cref: add cross reference to map file
|
||||
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref --relax --combine -fwhole-program
|
||||
LDFLAGS += $(EXTMEMOPTS)
|
||||
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Define directories, if needed.
|
||||
#DIRAVR = c:/winavr
|
||||
#DIRAVRBIN = $(DIRAVR)/bin
|
||||
#DIRAVRUTILS = $(DIRAVR)/utils/bin
|
||||
#DIRINC = .
|
||||
#DIRLIB = $(DIRAVR)/avr/lib
|
||||
|
||||
|
||||
# Define programs and commands.
|
||||
SHELL = sh
|
||||
CC = /opt/cross/bin/avr-gcc
|
||||
OBJCOPY = /opt/cross/bin/avr-objcopy
|
||||
OBJDUMP = /opt/cross/bin/avr-objdump
|
||||
SIZE = /opt/cross/bin/avr-size
|
||||
NM = /opt/cross/bin/avr-nm
|
||||
AVRDUDE = avrdude
|
||||
REMOVE = rm -f
|
||||
COPY = cp
|
||||
|
||||
|
||||
|
||||
|
||||
# Define Messages
|
||||
# English
|
||||
MSG_ERRORS_NONE = Errors: none
|
||||
MSG_BEGIN = -------- begin --------
|
||||
MSG_END = -------- end --------
|
||||
MSG_SIZE_BEFORE = Size before:
|
||||
MSG_SIZE_AFTER = Size after:
|
||||
MSG_COFF = Converting to AVR COFF:
|
||||
MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
|
||||
MSG_FLASH = Creating load file for Flash:
|
||||
MSG_EEPROM = Creating load file for EEPROM:
|
||||
MSG_EXTENDED_LISTING = Creating Extended Listing:
|
||||
MSG_SYMBOL_TABLE = Creating Symbol Table:
|
||||
MSG_LINKING = Linking:
|
||||
MSG_COMPILING = Compiling:
|
||||
MSG_ASSEMBLING = Assembling:
|
||||
MSG_CLEANING = Cleaning project:
|
||||
|
||||
|
||||
|
||||
|
||||
# Define all object files.
|
||||
OBJ = $(SRC:.c=.o) $(ASRC:.S=.o)
|
||||
|
||||
# Define all listing files.
|
||||
LST = $(ASRC:.S=.lst) $(SRC:.c=.lst)
|
||||
|
||||
|
||||
# Compiler flags to generate dependency files.
|
||||
### GENDEPFLAGS = -Wp,-M,-MP,-MT,$(*F).o,-MF,.dep/$(@F).d
|
||||
GENDEPFLAGS = -MD -MP -MF .dep/$(@F).d
|
||||
|
||||
# Combine all necessary flags and optional flags.
|
||||
# Add target processor to flags.
|
||||
|
||||
# ******************************************************************************* -mtiny-stack begrenzt stack auf 256 bytes -fno-inline
|
||||
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
|
||||
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp -mtiny-stack $(ASFLAGS)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Default target.
|
||||
all: begin gccversion sizebefore build sizeafter finished end
|
||||
|
||||
build: elf hex eep lss sym
|
||||
|
||||
elf: $(TARGET).elf
|
||||
hex: $(TARGET).hex
|
||||
eep: $(TARGET).eep
|
||||
lss: $(TARGET).lss
|
||||
sym: $(TARGET).sym
|
||||
|
||||
|
||||
|
||||
# Eye candy.
|
||||
# AVR Studio 3.x does not check make's exit code but relies on
|
||||
# the following magic strings to be generated by the compile job.
|
||||
begin:
|
||||
@echo
|
||||
@echo $(MSG_BEGIN)
|
||||
|
||||
finished:
|
||||
@echo $(MSG_ERRORS_NONE)
|
||||
|
||||
end:
|
||||
@echo $(MSG_END)
|
||||
@echo
|
||||
|
||||
|
||||
# Display size of file.
|
||||
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
|
||||
ELFSIZE = $(SIZE) -A $(TARGET).elf
|
||||
sizebefore:
|
||||
@if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); echo; fi
|
||||
|
||||
sizeafter:
|
||||
@if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); echo; fi
|
||||
|
||||
|
||||
|
||||
# Display compiler version information.
|
||||
gccversion :
|
||||
@$(CC) --version
|
||||
|
||||
|
||||
|
||||
# Program the device.
|
||||
program: $(TARGET).hex $(TARGET).eep
|
||||
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
|
||||
|
||||
|
||||
|
||||
|
||||
# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
|
||||
COFFCONVERT=$(OBJCOPY) --debugging \
|
||||
--change-section-address .data-0x800000 \
|
||||
--change-section-address .bss-0x800000 \
|
||||
--change-section-address .noinit-0x800000 \
|
||||
--change-section-address .eeprom-0x810000
|
||||
|
||||
|
||||
coff: $(TARGET).elf
|
||||
@echo
|
||||
@echo $(MSG_COFF) $(TARGET).cof
|
||||
$(COFFCONVERT) -O coff-avr $< $(TARGET).cof
|
||||
|
||||
|
||||
extcoff: $(TARGET).elf
|
||||
@echo
|
||||
@echo $(MSG_EXTENDED_COFF) $(TARGET).cof
|
||||
$(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof
|
||||
|
||||
|
||||
|
||||
# Create final output files (.hex, .eep) from ELF output file.
|
||||
%.hex: %.elf
|
||||
@echo
|
||||
@echo $(MSG_FLASH) $@
|
||||
$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
|
||||
|
||||
%.eep: %.elf
|
||||
@echo
|
||||
@echo $(MSG_EEPROM) $@
|
||||
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
|
||||
--change-section-lma .eeprom=0 -O $(FORMAT) $< $@
|
||||
|
||||
# Create extended listing file from ELF output file.
|
||||
%.lss: %.elf
|
||||
@echo
|
||||
@echo $(MSG_EXTENDED_LISTING) $@
|
||||
$(OBJDUMP) -h -S $< > $@
|
||||
|
||||
# Create a symbol table from ELF output file.
|
||||
%.sym: %.elf
|
||||
@echo
|
||||
@echo $(MSG_SYMBOL_TABLE) $@
|
||||
$(NM) -n $< > $@
|
||||
|
||||
|
||||
|
||||
# Link: create ELF output file from object files.
|
||||
.SECONDARY : $(TARGET).elf
|
||||
.PRECIOUS : $(OBJ)
|
||||
%.elf: $(OBJ)
|
||||
@echo
|
||||
@echo $(MSG_LINKING) $@
|
||||
$(CC) $(ALL_CFLAGS) $(OBJ) --output $@ $(LDFLAGS)
|
||||
|
||||
|
||||
# Compile: create object files from C source files.
|
||||
%.o : %.c
|
||||
@echo
|
||||
@echo $(MSG_COMPILING) $<
|
||||
$(CC) -c $(ALL_CFLAGS) $< -o $@
|
||||
|
||||
|
||||
# Compile: create assembler files from C source files.
|
||||
%.s : %.c
|
||||
$(CC) -S $(ALL_CFLAGS) $< -o $@
|
||||
|
||||
|
||||
# Assemble: create object files from assembler source files.
|
||||
%.o : %.S
|
||||
@echo
|
||||
@echo $(MSG_ASSEMBLING) $<
|
||||
$(CC) -c $(ALL_ASFLAGS) $< -o $@
|
||||
|
||||
|
||||
# Target: clean project.
|
||||
clean: begin clean_list finished end
|
||||
|
||||
clean_list :
|
||||
@echo
|
||||
@echo $(MSG_CLEANING)
|
||||
$(REMOVE) $(TARGET).hex
|
||||
$(REMOVE) $(TARGET).eep
|
||||
$(REMOVE) $(TARGET).obj
|
||||
$(REMOVE) $(TARGET).cof
|
||||
$(REMOVE) $(TARGET).elf
|
||||
$(REMOVE) $(TARGET).map
|
||||
$(REMOVE) $(TARGET).obj
|
||||
$(REMOVE) $(TARGET).a90
|
||||
$(REMOVE) $(TARGET).sym
|
||||
$(REMOVE) $(TARGET).lnk
|
||||
$(REMOVE) $(TARGET).lss
|
||||
$(REMOVE) $(OBJ)
|
||||
$(REMOVE) $(LST)
|
||||
$(REMOVE) $(SRC:.c=.s)
|
||||
$(REMOVE) $(SRC:.c=.d)
|
||||
$(REMOVE) .dep/*
|
||||
|
||||
|
||||
|
||||
# Include the dependency files.
|
||||
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
|
||||
|
||||
|
||||
# Listing of phony targets.
|
||||
.PHONY : all begin finish end sizebefore sizeafter gccversion \
|
||||
build elf hex eep lss sym coff extcoff \
|
||||
clean clean_list program
|
||||
|
||||
@@ -1,608 +0,0 @@
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "fat.h"
|
||||
#include "file.h"
|
||||
#include "hardware.h"
|
||||
|
||||
struct Fat fat; // wichtige daten/variablen der fat
|
||||
struct File file; // wichtige dateibezogene daten/variablen
|
||||
|
||||
|
||||
#if (WRITE==1)
|
||||
|
||||
//***************************************************************************************************************
|
||||
// schreibt sektor nummer:sec auf die karte (puffer:sector) !!
|
||||
// setzt bufferFlag=0 da puffer nicht dirty sein kann nach schreiben !
|
||||
//***************************************************************************************************************
|
||||
unsigned char fat_writeSector(unsigned long int sec){
|
||||
|
||||
fat.bufferDirty=0; // buffer kann nicht dirty sein weil wird geschrieben
|
||||
return(mmc_write_sector(sec,fat.sector)); // schreiben von sektor puffer
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// ***************************************************************************************************************
|
||||
// umrechnung cluster auf 1.sektor des clusters (möglicherweise mehrere sektoren/cluster) !
|
||||
// ***************************************************************************************************************
|
||||
unsigned long int fat_clustToSec(unsigned long int clust){
|
||||
|
||||
return (fat.dataDirSec+2+((clust-2) * fat.secPerClust)); // errechnet den 1. sektor der sektoren des clusters
|
||||
}
|
||||
|
||||
// ***************************************************************************************************************
|
||||
// umrechnung sektor auf cluster (nicht die position im cluster selber!!)
|
||||
// ***************************************************************************************************************
|
||||
unsigned long int fat_secToClust(unsigned long int sec){
|
||||
|
||||
return ((sec-fat.dataDirSec-2+2*fat.secPerClust)/fat.secPerClust); // umkerhrfunktion von fat_clustToSec
|
||||
}
|
||||
|
||||
|
||||
//***************************************************************************************************************
|
||||
// läd sektor:sec auf puffer:sector zum bearbeiten im ram !
|
||||
// setzt currentSectorNr auf richtigen wert (also den sektor der gepuffert ist). es wird geprüft
|
||||
// ob der gepufferte sektor geändert wurde, wenn ja muss erst geschrieben werden, um diese daten nicht zu verlieren !
|
||||
//***************************************************************************************************************
|
||||
unsigned char fat_loadSector(unsigned long int sec){
|
||||
|
||||
if(sec!=fat.currentSectorNr){ // nachladen nötig
|
||||
#if (WRITE==1)
|
||||
if(fat.bufferDirty==1) fat_writeSector(fat.currentSectorNr); // puffer diry, also vorher schreiben
|
||||
#endif
|
||||
mmc_read_sector(sec,fat.sector); // neuen sektor laden
|
||||
fat.currentSectorNr=sec; // aktualisiert sektor nummer (nummer des gepufferten sektors)
|
||||
return(0);
|
||||
}
|
||||
|
||||
else return(0); // alles ok, daten sind schon da (sec==fat.currentSectorNr)
|
||||
|
||||
return(1); // fehler
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// datei lesen funktionen:
|
||||
|
||||
// fat_loadSector -> fat_loadRowOfSector -> fat_loadFileDataFromCluster -> fat_loadFileDataFromDir -> fat_loadFileDataFromDir -> fat_cd "daten chain"
|
||||
|
||||
//***************************************************************************************************************
|
||||
// läd die reihe:row des gepufferten sektors auf das struct:file. dort stehen dann
|
||||
// alle wichgigen daten wie: 1.cluster,länge bei dateien, name des eintrags, reihen nummer (im sektor), attribut use...
|
||||
//***************************************************************************************************************
|
||||
unsigned char fat_loadRowOfSector(unsigned int row){
|
||||
|
||||
unsigned char i;
|
||||
row=row<<5; // multipliziert mit 32 um immer auf zeilen anfang zu kommen (zeile 0=0,zeile 1=32,zeile 2=62 usw).
|
||||
|
||||
void *vsector; // void, damit man schoen umbiegen kann :)
|
||||
|
||||
for(i=0;i<11;i++)
|
||||
file.name[i]=fat.sector[row+i]; // datei name, ersten 10 bytes vom 32 byte eintrag.
|
||||
|
||||
file.attrib=fat.sector[row+11]; // datei attribut, byte 11.
|
||||
|
||||
vsector=&fat.sector[row+26]; // low word von fist.cluster
|
||||
file.firstCluster=*(unsigned short*)vsector;
|
||||
|
||||
vsector=&fat.sector[row+20]; // high word von first.cluster
|
||||
file.firstCluster|=(*(unsigned short*)vsector)<<16;
|
||||
|
||||
vsector=&fat.sector[row+28]; // 4 byte von file.length
|
||||
file.length=*(unsigned long int*)vsector;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
//***************************************************************************************************************
|
||||
// geht reihen weise durch sektoren des clusters mit dem startsektor:sec, und sucht nach der datei mit dem
|
||||
// namen:name. es werden die einzelnen sektoren nachgeladen auf puffer:sector vor dem bearbeiten.
|
||||
// wird die datei in dem cluster gefunden ist return 0 , sonst return1.
|
||||
//***************************************************************************************************************
|
||||
unsigned char fat_loadFileDataFromCluster(unsigned long int sec , char name[]){
|
||||
|
||||
unsigned char r;
|
||||
unsigned char s=0;
|
||||
|
||||
do{ // sektoren des clusters prüfen
|
||||
r=0; // neuer sektor, dann reihen von 0 an.
|
||||
mmc_read_sector(sec+s,fat.sector); // läd den sektor sec auf den puffer fat.sector
|
||||
fat.currentSectorNr=sec+s; // setzen des aktuellen sektors
|
||||
do{ // reihen des sektors prüfen
|
||||
fat_loadRowOfSector(r); // zeile 0-15 auf struct file laden
|
||||
if(file.name[0]==0){ // wenn man auf erste 0 stößt müsste der rest auch leer sein!
|
||||
file.row=r; // zeile sichern.
|
||||
return(1);
|
||||
}
|
||||
if(0==strncmp((char*)file.name,name,10)){ // zeile r ist gesuchte
|
||||
file.row=r; // zeile sichern.
|
||||
return(0);
|
||||
}
|
||||
r++;
|
||||
}while(r<16); // zählt zeilennummer (16(zeilen) * 32(spalten) == 512 bytes des sektors)
|
||||
s++;
|
||||
}while(s<fat.secPerClust); // geht durch sektoren des clusters
|
||||
|
||||
return (1); // fehler (datei nicht gefunden, oder fehler beim lesen)
|
||||
}
|
||||
|
||||
|
||||
//***************************************************************************************************************
|
||||
// wenn dir == 0 dann wird das root direktory durchsucht, wenn nicht wird der ordner cluster-chain gefolgt, um
|
||||
// die datei zu finden. es wird das komplette directory in dem man sich befindet durchsucht.
|
||||
// bei fat16 wird der rootDir berreich durchsucht, bei fat32 die cluster chain des rootDir.
|
||||
//***************************************************************************************************************
|
||||
unsigned char fat_loadFileDataFromDir(char name[]){
|
||||
|
||||
unsigned int s;
|
||||
|
||||
if(fat.dir==0 && fat.fatType==16){ // IM ROOTDIR. fat16
|
||||
for(s=0;s<(unsigned int)(fat.dataDirSec+2-fat.rootDir);s++){ // zählt durch RootDir sektoren (errechnet anzahl rootDir sektoren).
|
||||
if(0==fat_loadFileDataFromCluster(fat.rootDir+s,name))return(0);// sucht die datei, wenn da, läd daten (1.cluster usw)
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
unsigned long int i;
|
||||
if(fat.dir==0 && fat.fatType==32)i=fat.rootDir; // IM ROOTDIR. fat32
|
||||
else i=fat.dir; // NICHT ROOTDIR
|
||||
while(!((i==0xfffffff&&fat.fatType==32)||(i==0xffff&&fat.fatType==16))){ // prüft ob weitere sektoren zum lesen da sind (fat32||fat16)
|
||||
if(0==fat_loadFileDataFromCluster(fat_clustToSec(i),name))return(0); // lät die daten der datei auf struct:file. datei gefunden (umrechnung auf absoluten sektor)
|
||||
i=fat_getNextCluster(i); // liest nächsten cluster des dir-eintrags (unterverzeichniss größer 16 einträge)
|
||||
}
|
||||
}
|
||||
|
||||
return(1); // datei/verzeichniss nicht gefunden
|
||||
}
|
||||
|
||||
|
||||
#if (SMALL_FILE_SYSTEM==0)
|
||||
|
||||
//***************************************************************************************************************
|
||||
// start immer im root Dir. start in root dir (dir==0).
|
||||
// es MUSS in das direktory gewechselt werden, in dem die datei zum lesen/anhängen ist (außer root, da startet mann)!
|
||||
//***************************************************************************************************************
|
||||
unsigned char fat_cd(char name[]){
|
||||
|
||||
if(name[0]==0){ // ZUM ROOTDIR FAT16/32
|
||||
fat.dir=0; // root dir
|
||||
return(0);
|
||||
}
|
||||
|
||||
if(0==fat_loadFileDataFromDir(name)){ // NICHT ROOTDIR (fat16/32)
|
||||
fat.dir=file.firstCluster; // zeigt auf 1.cluster des dir (fat16/32)
|
||||
return(0);
|
||||
}
|
||||
|
||||
return(1); // dir nicht gewechselt (nicht da?) !!
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#if (WRITE==1)
|
||||
|
||||
// datei anlegen funktionen :
|
||||
|
||||
// ***************************************************************************************************************
|
||||
// sucht leeren eintrag (zeile) im cluster mit dem startsektor:secStart.
|
||||
// wird dort kein freier eintrag gefunden ist return (1).
|
||||
// wird ein freier eintrag gefunden, ist die position der freien reihe auf file.row abzulesen und return (0).
|
||||
// der sektor mit der freien reihe ist auf dem puffer:sector gepuffert.
|
||||
// ****************************************************************************************************************
|
||||
unsigned char fat_getFreeRowOfCluster(unsigned long secStart){
|
||||
|
||||
unsigned int b; // zum durchgenen der sektor bytes
|
||||
unsigned char s=0; // sektoren des clusters.
|
||||
|
||||
do{
|
||||
file.row=0; // neuer sektor(oder 1.sektor), reihen von vorne.
|
||||
if(0==fat_loadSector(secStart+s)){ // laed sektor auf puffer fat.sector
|
||||
for(b=0;b<512;b=b+32){ // zaehlt durch zeilen (0-15).
|
||||
if(fat.sector[b]==0x00||fat.sector[b]==0xE5)return(0); // prueft auf freihen eintrag (leer oder geloescht == OK!).
|
||||
file.row++; // zählt reihe hoch (nächste reihe im sektor).
|
||||
}
|
||||
}
|
||||
s++; // sektoren des clusters ++ weil einen geprüft.
|
||||
}while(s<fat.secPerClust); // geht die sektoren des clusters durch (moeglicherweise auch nur 1. sektor).
|
||||
return (1); // nicht gefunden in diesem cluster (== nicht OK!).
|
||||
}
|
||||
|
||||
|
||||
// ***************************************************************************************************************
|
||||
// sucht leeren eintrag (zeile) im directory mit dem startcluster:dir.
|
||||
// geht die cluster chain des direktories durch. dabei werden auch alle sektoren der cluster geprüft.
|
||||
// wird dort kein freier eintrag gefunden, wird ein neuer leerer cluster gesucht, verkettet und der
|
||||
// 1. sektor des freien clusters geladen. die reihe wird auf den ersten eintrag gesetzt, da frei.
|
||||
// anhand der reihe kann man nun den direktory eintrag vornehmen, und auf die karte schreiben.
|
||||
// ****************************************************************************************************************
|
||||
void fat_getFreeRowOfDir(unsigned long int dir){
|
||||
|
||||
unsigned long int start=dir;
|
||||
|
||||
// solange bis ende cluster chain.
|
||||
while( !((dir==0xfffffff&&fat.fatType==32)||(dir==0xffff&&fat.fatType==16)) ){
|
||||
if(0==fat_getFreeRowOfCluster(fat_clustToSec(dir)))return; // freien eintrag in clustern, des dir gefunden !!
|
||||
start=dir;
|
||||
dir=fat_getNextCluster(dir);
|
||||
} // wenn aus schleife raus, kein freier eintrag da -> neuer cluster nötig.
|
||||
|
||||
dir=fat_secToClust(fat.startSectors); // dir ist jetzt neuer cluster zum verketten !
|
||||
fat_setCluster(start,dir); // cluster-chain mit neuem cluster verketten
|
||||
fat_setCluster(dir,0x0fffffff); // cluster-chain ende markieren
|
||||
|
||||
//es muessen neue gesucht werden, weil der bekannte aus file.c ja grade verkettet wurden. datei eintrag passte nicht mehr ins dir...
|
||||
fat_getFreeClustersInRow(2); // neue freie cluster suchen, für datei.
|
||||
file.firstCluster=fat_secToClust(fat.startSectors); // 1. cluster der datei
|
||||
file.lastCluster=fat_secToClust(fat.endSectors); // letzter bekannter cluster der datei
|
||||
|
||||
fat.currentSectorNr=fat_clustToSec(dir); // setzen des richtigen sektors, also auf den 1. der neu verketteten
|
||||
|
||||
unsigned int j=511;
|
||||
do{
|
||||
fat.sector[j]=0x00; //schreibt puffer fat.sector voll mit 0x00==leer
|
||||
}while(j--);
|
||||
|
||||
unsigned char i=1; // ab 1 weil der 1.sektor des clusters eh noch beschrieben wird...
|
||||
do{
|
||||
fat_writeSector(fat.currentSectorNr+i); // löschen des cluster (überschreibt mit 0x00), wichtig bei ffls,
|
||||
i++;
|
||||
}while(i<fat.secPerClust);
|
||||
|
||||
file.row=0; // erste reihe frei, weil grad neuen cluster verkettet !
|
||||
}
|
||||
|
||||
|
||||
//***************************************************************************************************************
|
||||
// erstellt 32 byte eintrag einer datei, oder verzeichnisses im puffer:sector.
|
||||
// erstellt eintrag in reihe:row, mit namen:name usw... !!
|
||||
// muss noch auf die karte geschrieben werden ! nicht optimiert auf geschwindigkeit.
|
||||
//***************************************************************************************************************
|
||||
void fat_makeRowDataEntry(unsigned int row,char name[],unsigned char attrib,unsigned long int cluster,unsigned long int length){
|
||||
|
||||
fat.bufferDirty=1; // puffer beschrieben, also neue daten darin(vor lesen muss geschrieben werden)
|
||||
|
||||
row=row<<5; // multipliziert mit 32 um immer auf zeilen anfang zu kommen (zeile 0=0,zeile 1=32,zeile 2=62 ... zeile 15=480)
|
||||
|
||||
unsigned char i; // byte zähler in reihe von sektor (32byte eintrag)
|
||||
unsigned char *bytesOfSec=&fat.sector[row]; // zeiger auf sector bytes
|
||||
void *vsector;
|
||||
|
||||
for(i=0;i<11;i++) *bytesOfSec++=name[i]; // namen schreiben
|
||||
|
||||
*bytesOfSec++=attrib; // attrib schreiben
|
||||
|
||||
vsector=&fat.sector[row+12];
|
||||
*(unsigned long int*)vsector++=0x01010101; // unnoetige felder beschreiben
|
||||
*(unsigned long int*)vsector=0x01010101;
|
||||
|
||||
vsector=&fat.sector[row+20];
|
||||
*(unsigned short*)vsector=(cluster&0xffff0000)>>16;// low word von cluster
|
||||
|
||||
vsector=&fat.sector[row+22];
|
||||
*(unsigned long int*)vsector=0x01010101; // unnoetige felder beschreiben
|
||||
|
||||
vsector=&fat.sector[row+26];
|
||||
*(unsigned short*)vsector=(cluster&0x0000ffff); // high word von cluster
|
||||
|
||||
vsector=&fat.sector[row+28];
|
||||
*(unsigned long int*)vsector=length; // laenge
|
||||
}
|
||||
|
||||
|
||||
//***************************************************************************************************************
|
||||
// macht den datei eintrag im jetzigen verzeichniss (fat.dir).
|
||||
// file.row enthält die reihen nummer des leeren eintrags, der vorher gesucht wurde, auf puffer:sector ist der gewünschte
|
||||
// sektor gepuffert. für fat16 im root dir muss andere funktion genutzt werden, als fat_getFreeRowOfDir (durchsucht nur dirs).
|
||||
// fat.rootDir enthält bei fat32 den start cluster des directory, bei fat16 den 1. sektor des rootDir bereichs!
|
||||
//***************************************************************************************************************
|
||||
void fat_makeFileEntry(char name[],unsigned char attrib,unsigned long int length){
|
||||
|
||||
unsigned int s; // zähler für root dir sektoren fat16
|
||||
|
||||
if(fat.dir==0&&fat.fatType==32)fat_getFreeRowOfDir(fat.rootDir); // IM ROOT DIR (fat32)
|
||||
|
||||
else if(fat.dir==0 && fat.fatType==16){ // IM ROOT DIR (fat16)
|
||||
for(s=0;s<(unsigned int)(fat.dataDirSec+2-fat.rootDir);s++){ // zählt durch RootDir sektoren (errechnet anzahl rootDir sektoren).
|
||||
if(0==fat_getFreeRowOfCluster(fat.rootDir+s))break; // geht durch sektoren des root dir.
|
||||
}
|
||||
}
|
||||
|
||||
else fat_getFreeRowOfDir(fat.dir); // NICHT ROOT DIR fat32/fat16
|
||||
|
||||
fat_makeRowDataEntry(file.row,name,attrib,file.firstCluster,length); // schreibt file eintrag auf puffer
|
||||
fat_writeSector(fat.currentSectorNr); // schreibt puffer auf karte
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// fat funktionen:
|
||||
|
||||
//***************************************************************************************************************
|
||||
// sucht nötige folge Cluster aus der fat !
|
||||
// erster daten cluster = 2, ende einer cluster chain 0xFFFF (fat16) oder 0xFFFFFFF, 0xFFFFFF8 (fat32),
|
||||
// stelle des clusters in der fat, hat als wert, den nächsten cluster. (1:1 gemapt)!
|
||||
//***************************************************************************************************************
|
||||
unsigned long int fat_getNextCluster(unsigned long int oneCluster){
|
||||
|
||||
// FAT 16**************FAT 16
|
||||
if(fat.fatType==16){
|
||||
unsigned long int i=oneCluster>>8;; // (i=oneCluster/256)errechnet den sektor der fat in dem oneCluster ist (rundet immer ab)
|
||||
unsigned long int j=(oneCluster<<1)-(i<<9); // (j=(oneCluster-256*i)*2 == 2*oneCluster-512*i)errechnet das low byte von oneCluster
|
||||
|
||||
if(0==fat_loadSector(i+fat.fatSec)){ // ob neu laden nötig, wird von fat_loadSector geprüft
|
||||
void *bytesOfSec=&fat.sector[j]; // zeiger auf puffer
|
||||
return *(unsigned short*)bytesOfSec; // da der ram auch little endian ist, kann einfach gecastet werden und gut :)
|
||||
}
|
||||
}
|
||||
|
||||
// FAT 32**************FAT 32
|
||||
else{
|
||||
unsigned long int i=oneCluster>>7; // (i=oneCluster/128)errechnet den sektor der fat in dem oneCluster ist (rundet immer ab)
|
||||
unsigned long int j=(oneCluster<<2)-(i<<9); // (j=(oneCluster-128*i)*4 == oneCluster*4-512*i)errechnet das low byte von oneCluster
|
||||
|
||||
if(0==fat_loadSector(i+fat.fatSec)){ // ob neu laden nötig wird von fat_loadSector geprüft
|
||||
void *bytesOfSec=&fat.sector[j]; // zeiger auf puffer
|
||||
return *(unsigned long int*)bytesOfSec; // da der ram auch little endian ist, kann einfach gecastet werden und gut :)
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
//***************************************************************************************************************
|
||||
// sucht verkettete cluster einer datei, die in einer reihe liegen. worst case: nur ein cluster.
|
||||
// sieht in der fat ab dem cluster offsetCluster nach. sucht die anzahl von MAX_CLUSTERS_IN_ROW,
|
||||
// am stück,falls möglich. prüft ob der cluster neben offsetCluster dazu gehört...
|
||||
// setzt dann fat.endSectors und fat.startSectors. das -1 weil z.b. [95,98] = {95,96,97,98} = 4 sektoren
|
||||
//***************************************************************************************************************
|
||||
void fat_getFatChainClustersInRow(unsigned long int offsetCluster){
|
||||
|
||||
unsigned int i=0;
|
||||
fat.startSectors=fat_clustToSec(offsetCluster); // setzen des 1. sektors der datei
|
||||
fat.endSectors=fat.startSectors;
|
||||
do{
|
||||
if( (offsetCluster+1+i)==fat_getNextCluster(offsetCluster+i) ) fat.endSectors+=fat.secPerClust; // zählen der zusammenhängenden sektoren
|
||||
else {
|
||||
file.lastCluster=offsetCluster+i; // cluster daneben gehört nicht dazu, somit ist offset+i der letzte bekannte
|
||||
break;
|
||||
}
|
||||
}while(i++<MAX_CLUSTERS_IN_ROW);
|
||||
fat.endSectors+=fat.secPerClust-1;
|
||||
}
|
||||
|
||||
|
||||
#if (WRITE==1)
|
||||
|
||||
//***************************************************************************************************************
|
||||
// sucht freie zusammenhängende cluster aus der fat. maximal MAX_CLUSTERS_IN_ROW am stück.
|
||||
// erst wir der erste frei cluster gesucht, ab offsetCluster(iklusive) und dann wird geschaut, ob der
|
||||
// daneben auch frei ist. setzt dann fat.endSectors und fat.startSectors. das -1 weil z.b. [95,98] = {95,96,97,98} = 4 sektoren
|
||||
//***************************************************************************************************************
|
||||
void fat_getFreeClustersInRow(unsigned long int offsetCluster){
|
||||
|
||||
unsigned int i=1; // variable für anzahl der zu suchenden sektoren
|
||||
while(fat_getNextCluster(offsetCluster)) offsetCluster++; // suche des 1. freien clusters
|
||||
|
||||
fat.startSectors=fat_clustToSec(offsetCluster); // setzen des startsektors der freien sektoren (umrechnen von cluster zu sektoren)
|
||||
fat.endSectors=fat.startSectors;
|
||||
|
||||
do{ // suche der nächsten freien
|
||||
if(0==fat_getNextCluster(offsetCluster+i) ) fat.endSectors+=fat.secPerClust; // zählen der zusammenhängenden sektoren
|
||||
else break; // cluster daneben ist nicht frei
|
||||
}while(i++<MAX_CLUSTERS_IN_ROW);
|
||||
|
||||
fat.endSectors+=fat.secPerClust-1; // -1 weil der erste sektor schon mit zählt z.b. [95,98] = 4 sektoren
|
||||
}
|
||||
|
||||
|
||||
//***************************************************************************************************************
|
||||
// verkettet ab startCluster bis einschließlich endCluster. verkettet auch den letzten bekannten mit den neu übergebenen !
|
||||
// es ist wegen der fragmentierung der fat nötig, sich den letzten bekannten cluster zu merken,
|
||||
// damit man bei weiteren cluster in einer reihe die alten cluster noch dazu verketten kann (so sind lücken im verketten möglich).
|
||||
//***************************************************************************************************************
|
||||
void fat_setClusterChain(unsigned long int startCluster,unsigned int endCluster){
|
||||
|
||||
fat_setCluster(file.lastCluster,startCluster); // ende der chain setzen, bzw verketten der ketten
|
||||
|
||||
while(startCluster!=endCluster){
|
||||
startCluster++;
|
||||
fat_setCluster( startCluster-1 ,startCluster ); // verketten der cluster der neuen kette
|
||||
}
|
||||
|
||||
fat_setCluster(startCluster,0xfffffff); // ende der chain setzen
|
||||
file.lastCluster=endCluster; // ende cluster der kette updaten
|
||||
fat_writeSector(fat.currentSectorNr); // schreiben des fat sektors auf die karte
|
||||
|
||||
}
|
||||
|
||||
|
||||
//***************************************************************************************************************
|
||||
// setzt den cluster inhalt. errechnet den sektor der fat in dem cluster ist, errechnet das low byte von
|
||||
// cluster und setzt dann byteweise den inhalt:content.
|
||||
// prüft ob buffer dirty (zu setztender cluster nicht in jetzt gepuffertem).
|
||||
// prüfung erfolgt in fat_loadSector, dann wird alter vorher geschrieben, sonst gehen dort daten verloren !!
|
||||
//***************************************************************************************************************
|
||||
void fat_setCluster(unsigned long int cluster, unsigned long int content){
|
||||
|
||||
// FAT 16**************FAT 16
|
||||
if(fat.fatType==16){
|
||||
unsigned long int i=cluster>>8; // (i=cluster/256)errechnet den sektor der fat in dem cluster ist (rundet immer ab)
|
||||
unsigned long int j=(cluster<<1)-(i<<9); // (j=(cluster-256*i)*2 == 2*cluster-512*i)errechnet das low byte von cluster
|
||||
|
||||
if(0==fat_loadSector(i+fat.fatSec)){ // neu laden (fat_loadSector prüft ob schon gepuffert)
|
||||
void *bytesOfSec=&fat.sector[j]; // init des zeigers auf unterste adresse
|
||||
*(unsigned short*)bytesOfSec=content;// weil ram auch little endian geht das so :)
|
||||
fat.bufferDirty=1; // zeigt an, dass im aktuellen sector geschrieben wurde
|
||||
}
|
||||
}
|
||||
|
||||
// FAT 32**************FAT 32
|
||||
else{
|
||||
unsigned long int i=cluster>>7; // (i=cluster/128)errechnet den sektor der fat in dem cluster ist (rundet immer ab)
|
||||
unsigned long int j=(cluster<<2)-(i<<9); //(j=(cluster-128*i)*4 == cluster*4-512*i)errechnet das low byte von cluster
|
||||
|
||||
if(0==fat_loadSector(i+fat.fatSec)){ // neu laden (fat_loadSector prüft ob schon gepuffert)
|
||||
void *bytesOfSec=&fat.sector[j]; // init des zeigers auf unterste adresse
|
||||
*(unsigned long int*)bytesOfSec=content; // weil ram auch little endian geht das so :)
|
||||
fat.bufferDirty=1; // zeigt an, dass im aktuellen sector geschrieben wurde
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//***************************************************************************************************************
|
||||
// löscht cluster chain, beginnend ab dem startCluster.
|
||||
// sucht cluster, setzt inhalt usw.. abschließend noch den cluster-chain ende markierten cluster löschen.
|
||||
//***************************************************************************************************************
|
||||
void fat_delClusterChain(unsigned long int startCluster){
|
||||
|
||||
unsigned long int nextCluster=startCluster; // tmp variable, wegen verketteter cluster..
|
||||
|
||||
do{
|
||||
startCluster=nextCluster;
|
||||
nextCluster=fat_getNextCluster(startCluster);
|
||||
fat_setCluster(startCluster,0x00000000);
|
||||
}while(!((nextCluster==0xfffffff&&fat.fatType==32)||(nextCluster==0xffff&&fat.fatType==16)));
|
||||
fat_writeSector(fat.currentSectorNr);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
//***************************************************************************************************************
|
||||
// Initialisiert die Fat(16/32) daten, wie: root directory sektor, daten sektor, fat sektor...
|
||||
// siehe auch Fatgen103.pdf. ist NICHT auf performance optimiert!
|
||||
// byte/sector, byte/cluster, anzahl der fats, sector/fat ... (halt alle wichtigen daten zum lesen ders datei systems!)
|
||||
//*****************************************************************<**********************************************
|
||||
unsigned char fat_loadFatData(unsigned long int sec){
|
||||
|
||||
// offset,size
|
||||
unsigned int rootEntCnt; // 17,2 größe die eine fat belegt
|
||||
unsigned int fatSz16; // 22,2 sectors occupied by one fat16
|
||||
unsigned long int fatSz32; // 36,4 sectors occupied by one fat32
|
||||
|
||||
void *vsector;
|
||||
|
||||
if(0==mmc_read_sector(sec,fat.sector)){ // lesen von fat sector und bestimmen der wichtigen berreiche
|
||||
|
||||
fat.bufferDirty = 0; // init wert des flags
|
||||
|
||||
fat.secPerClust=fat.sector[13]; // fat.secPerClust, 13 only (power of 2)
|
||||
|
||||
vsector=&fat.sector[14];
|
||||
fat.fatSec=*(unsigned short*)vsector;
|
||||
|
||||
vsector=&fat.sector[17];
|
||||
rootEntCnt=*(unsigned short*)vsector;
|
||||
|
||||
vsector=&fat.sector[22];
|
||||
fatSz16=*(unsigned short*)vsector;
|
||||
|
||||
fat.rootDir = (((rootEntCnt <<5) + 512) /512)-1; // ist 0 bei fat 32, sonst der root dir sektor
|
||||
|
||||
if(fat.rootDir==0){ // FAT32 spezifisch (die prüfung so, ist nicht spezifikation konform !).
|
||||
|
||||
vsector=&fat.sector[36];
|
||||
fatSz32=*(unsigned long int *)vsector;
|
||||
|
||||
vsector=&fat.sector[44];
|
||||
fat.rootDir=*(unsigned long int *)vsector;
|
||||
|
||||
fat.dataDirSec = fat.fatSec + (fatSz32 * fat.sector[16]); // data sector (beginnt mit cluster 2)
|
||||
fat.fatType=32; // fat typ
|
||||
}
|
||||
|
||||
else{ // FAT16 spezifisch
|
||||
fat.dataDirSec = fat.fatSec + (fatSz16 * fat.sector[16]) + fat.rootDir; // data sektor (beginnt mit cluster 2)
|
||||
fat.rootDir=fat.dataDirSec-fat.rootDir; // root dir sektor, da nicht im datenbereich (cluster)
|
||||
fat.rootDir+=sec; // addiert den startsektor auf "
|
||||
fat.fatType=16; // fat typ
|
||||
}
|
||||
|
||||
fat.fatSec+=sec; // addiert den startsektor auf
|
||||
fat.dataDirSec+=sec; // addiert den startsektor auf (umrechnung von absolut auf real)
|
||||
fat.dataDirSec-=2; // zeigt auf 1. cluster
|
||||
fat.dir=0; // dir auf '0'==root dir, sonst 1.Cluster des dir
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
return (1); // sector nicht gelesen, fat nicht initialisiert!!
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************************************<<***************
|
||||
// int fat sucht den 1. cluster des dateisystems (fat16/32) auch VBR genannt,
|
||||
//************************************************************************************************<<***************
|
||||
unsigned char fat_initfat(void){
|
||||
|
||||
unsigned long int secOfFirstPartition=0; // ist 1. sektor der 1. partition aus dem MBR
|
||||
|
||||
if(0==mmc_read_sector(0,fat.sector)){
|
||||
|
||||
void *vsector=&fat.sector[454]; //startsektor bestimmen
|
||||
secOfFirstPartition=*(unsigned long int*)vsector;
|
||||
|
||||
//prüfung ob man schon im VBR gelesen hat (0x6964654d = "Medi")
|
||||
if(secOfFirstPartition==0x6964654d) return fat_loadFatData(0); //ist superfloppy
|
||||
|
||||
else {return fat_loadFatData(secOfFirstPartition);} // ist partitioniert...
|
||||
}
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
||||
#if (SMALL_FILE_SYSTEM==0)
|
||||
|
||||
// *****************************************************************************************************************
|
||||
// bereitet str so auf, dass man es auf die mmc/sd karte schreiben kann.
|
||||
// wandelt z.b. "t.txt" -> "T TXT" oder "main.c" in "MAIN C " => also immer 8.3 und upper case letter
|
||||
// VORSICHT es werden keine Prüfungen gemacht !
|
||||
// *****************************************************************************************************************
|
||||
char * fat_str(char *str){
|
||||
|
||||
unsigned char i;
|
||||
unsigned char j=0;
|
||||
unsigned char c;
|
||||
char tmp[12]; // tmp string zum einfacheren umwandeln
|
||||
|
||||
strcpy(tmp,str);
|
||||
|
||||
for(i=0;i<11;i++)str[i]=' '; // als vorbereitung alles mit leerzeichen füllen
|
||||
str[11]='\0';
|
||||
|
||||
i=0;
|
||||
|
||||
do{
|
||||
c=toupper(tmp[j]);
|
||||
if(c=='\0')return str;
|
||||
if(c!='.')str[i]=c;
|
||||
else i=7;
|
||||
i++;
|
||||
j++;
|
||||
}while(i<12);
|
||||
|
||||
return str;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
|
||||
#ifndef _FAT_H
|
||||
|
||||
#define _FAT_H
|
||||
|
||||
// **************************************************************************************************************************
|
||||
// WICHTIGE SCHLATER: -> hier kann die code größe angepasst werden, zu lasten der funktionalität !
|
||||
#define SMALL_FILE_SYSTEM 0 // wenn 1 dann ist kleines file system, wenn 0 dann komplette file unterstützung !
|
||||
#define WRITE 1 // wenn 1 dann ist write an, wenn 0 dann read only !
|
||||
#define OVER_WRITE 1 // wenn 1 dann kann ffwrite dateien überschreiben (nicht performant), wenn 0 dann nur normales schreiben !
|
||||
#define MAX_CLUSTERS_IN_ROW 256 // gibt an wie viele cluster am stück ohne fat lookup geschrieben bzw gelesen werden können, wenn die fat nicht fragmentiert ist !
|
||||
|
||||
// 1. fat_getFreeRowOfCluster -> fat_getFreeRowOfDir -> fat_makeRowDataEntry -> fat_makeFileEntry -> fat_writeSector "eintrag gemacht !!"
|
||||
// 2. fat_loadSector -> fat_loadRowOfSector -> fat_loadFileDataFromCluster -> fat_loadFileDataFromDir (-> fat_cd) "daten chain"
|
||||
|
||||
// **************************************************************************************************************************
|
||||
// funktionen
|
||||
|
||||
extern unsigned long int fat_clustToSec(unsigned long int); // rechnet cluster zu 1. sektor des clusters um
|
||||
extern unsigned long int fat_secToClust(unsigned long int sec); // rechnet sektor zu cluster um!
|
||||
extern unsigned long int fat_getNextCluster(unsigned long int oneCluster); // fat auf nächsten, verketteten cluster durchsuchen
|
||||
extern unsigned char fat_initfat(void); // initalisierung (durchsucht MBR oder nicht)
|
||||
extern unsigned char fat_writeSector(unsigned long int sec); // schreibt sektor auf karte
|
||||
extern void fat_setCluster(unsigned long int cluster, unsigned long int content); // setzt cluster inhalt in der fat
|
||||
extern void fat_delClusterChain(unsigned long int startCluster); // löscht cluster-chain in der fat
|
||||
extern void fat_getFreeRowOfDir(unsigned long int dir); // durchsucht directory nach feiem eintrag
|
||||
extern void fat_makeFileEntry(char name[],unsigned char attrib,unsigned long int length);
|
||||
extern unsigned char fat_loadSector(unsigned long int sec); // läd übergebenen absoluten sektor
|
||||
extern unsigned char fat_loadFileDataFromDir(char name[]); // durchsucht das aktuelle directory
|
||||
extern unsigned char fat_cd(char *); // wechselt directory (start im rootDir)
|
||||
extern unsigned char fat_loadFatData(unsigned long int); // läd fat daten
|
||||
extern unsigned char fat_getFreeRowOfCluster(unsigned long secStart);// durchsucht cluster nach freiem eintrag
|
||||
extern void fat_getFreeClustersInRow(unsigned long int offsetCluster); // sucht zusammenhängende freie cluster aus der fat
|
||||
extern void fat_getFatChainClustersInRow(unsigned long int offsetCluster); // sucht fat-chain cluster die zusammenhängen
|
||||
extern void fat_makeRowDataEntry(unsigned int row,char name[],unsigned char attrib,unsigned long int cluster,unsigned long int length);
|
||||
extern unsigned char fat_loadRowOfSector(unsigned int); // läd reihe des geladen sektors auf struct:file
|
||||
extern unsigned char fat_loadFileDataFromCluster(unsigned long int sec , char name[]); // durchsucht die reihen des geladenen sektors
|
||||
extern void fat_setClusterChain(unsigned long int newOffsetCluster,unsigned int length);
|
||||
extern char *fat_str(char *str); // wandelt einen string so, dass er der fat konvention entspricht !
|
||||
|
||||
|
||||
// **************************************************************************************************************************
|
||||
// variablen
|
||||
|
||||
extern struct Fat{ // fat daten (1.cluster, root-dir, dir usw.)
|
||||
unsigned char sector[512]; // der puffer für sektoren !
|
||||
unsigned char bufferDirty; // puffer wurde beschrieben, sector muss geschrieben werden bevor er neu geladen wird
|
||||
unsigned long int currentSectorNr;// aktuell geladener Sektor (in sector) //beschleunigt wenn z.b 2* 512 byte puffer vorhanden, oder bei fat operationen im gleichen sektor
|
||||
unsigned long int dir; // Direktory zeiger rootDir=='0' sonst(1.Cluster des dir; start auf root)
|
||||
unsigned long int rootDir; // Sektor(f16)/Cluster(f32) nr root directory
|
||||
unsigned long int dataDirSec; // Sektor nr data area
|
||||
unsigned long int fatSec; // Sektor nr fat area
|
||||
unsigned long int startSectors; // der erste sektor in einer reihe (freie oder verkettete)
|
||||
unsigned long int endSectors;
|
||||
unsigned char secPerClust; // anzahl der sektoren pro cluster
|
||||
unsigned char fatType; // fat16 oder fat32 (16 oder 32)
|
||||
}fat;
|
||||
|
||||
extern struct File{ // datei infos
|
||||
unsigned int cntOfBytes; // -nicht direkt aus dem dateisystem- zäht geschriebene bytes eines sektors
|
||||
unsigned char name[13]; // 0,10 datei Name.ext (8.3 = max 11)(MUSS unsigned char weil E5)
|
||||
unsigned char attrib; // 11,1 datei Attribut: 8=value name, 32=datei, 16=Verzeichniss, 15=linux kleingeschrieben eintrag
|
||||
unsigned char row; // reihe im sektor in der die datei infos stehen (reihe 0-15)
|
||||
unsigned long int firstCluster; // 20,2 /26,2 datei 1.cluster hi,low(möglicherweise der einzige) (4-byte)
|
||||
unsigned long int length; // 28,4 datei Länge (4-byte)
|
||||
unsigned long int lastCluster; // -nicht direkt aus dem dateisystem- letzter cluster der ersten kette
|
||||
unsigned long int seek; // schreib position in der datei
|
||||
}file;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,469 +0,0 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "main.h"
|
||||
#include "hardware.h"
|
||||
#include "fat.h"
|
||||
#include "file.h"
|
||||
|
||||
|
||||
|
||||
//*******************************************************************************************************************************
|
||||
// 2 möglichkeiten beim öffnen, datei existiert(return 1) oder muss angelegt werden(return 2)
|
||||
// zuerst wird geprüft ob es die datei im verzeichniss gibt. danach wird entschieden, ob die datei geöffnet wird oder angelegt.
|
||||
// -beim offnen werden die bekannten cluster gesucht maximal MAX_CLUSTERS_IN_ROW in reihe. dann wird der 1. sektor der datei auf
|
||||
// den puffer fat.sector geladen. jetzt kann man ffread lesen...
|
||||
// -beim anlegen werden freie cluster gesucht, maximal MAX_CLUSTERS_IN_ROW in reihe. dann wird das struct file gefüllt.
|
||||
// danach wird der dateieintrag gemacht(auf karte). dort wird auch geprüft ob genügend platz im aktuellen verzeichniss existiert.
|
||||
// möglicherweise wird der 1. cluster der datei nochmal geändert. jetzt ist der erste frei sektor bekannt und es kann geschrieben werden.
|
||||
//*******************************************************************************************************************************
|
||||
unsigned char ffopen(char name[]){
|
||||
|
||||
unsigned char file_flag=fat_loadFileDataFromDir(name); //prüfung ob datei vorhanden und evetuelles laden des file struct
|
||||
|
||||
if( file_flag==0 ){ /** Datei existiert, anlegen nicht nötig! **/
|
||||
fat_getFatChainClustersInRow( file.firstCluster ); // verkettete cluster aus der fat-chain suchen.
|
||||
fat_loadSector( fat_clustToSec(file.firstCluster) ); // lät die ersten 512 bytes der datei auf puffer:sector.
|
||||
file.lastCluster=fat_secToClust(fat.endSectors); // letzter bekannter cluster der datei
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if (WRITE==1) // anlegen ist schreiben !
|
||||
else{ /** Datei existiert nicht, also anlegen ! (nur wenn schreiben option an ist)**/
|
||||
fat_getFreeClustersInRow(2); // leere cluster suchen, ab cluster 2.
|
||||
strcpy((char*)file.name,(char*)name); // --- füllen des file struct, zum abschließenden schreiben.
|
||||
file.firstCluster=fat_secToClust(fat.startSectors); // 1. cluster der datei
|
||||
file.lastCluster=file.firstCluster;//fat_secToClust(fat.endSectors); // letzter bekannter cluster der datei
|
||||
file.attrib=32; // --- file.row wird in der funktion fat_getFreeRowOfDir geschrieben !!
|
||||
file.length=0; // damit da nix drin steht ^^
|
||||
fat_makeFileEntry((char *)file.name,file.attrib,0); // DATEI ANLEGEN auf karte
|
||||
fat.currentSectorNr=fat_clustToSec(file.firstCluster); // setzen des ersten sektors
|
||||
return 2;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//*******************************************************************************************************************************
|
||||
// schließt die datei operation ab. eigentlich nur nötig wenn geschrieben wurde. es gibt 2 möglichkeiten :
|
||||
// 1. die datei wird geschlossen und es wurde über die alte datei länge hinaus geschrieben.
|
||||
// 2. die datei wird geschlossen und man war innerhalb der datei größe, dann muss nur der aktuelle sektor geschrieben werden.
|
||||
// der erste fall ist komplizierter, weil ermittelt werden muss wie viele sektoren neu beschrieben wurden um diese zu verketten
|
||||
// und die neue datei länge muss ermitt weden. abschließend wird entweder (fall 2) nur der aktuelle sektor geschrieben, oder
|
||||
// der aktuallisierte datei eintrag und die cluster (diese werden verkettet, siehe fileUpdate() ).
|
||||
//*******************************************************************************************************************************
|
||||
unsigned char ffclose(void){
|
||||
|
||||
#if (WRITE==1) /** 2 möglichkeiten beim schließen !! (lesend spielt keine rolle, nichts muss geupdatet werden) **/
|
||||
|
||||
if( file.length < (file.seek+file.cntOfBytes) ) fileUpdate(); /** 1.) es wurde über die alte datei größe hinaus geschrieben **/
|
||||
|
||||
else if( fat.bufferDirty==1) fat_writeSector( fat.currentSectorNr ); /** 2.) nicht über alte datei länge hinaus **/
|
||||
|
||||
#endif
|
||||
|
||||
file.cntOfBytes=0; // init werte der nötigen zähler
|
||||
file.seek=0;
|
||||
return(0);
|
||||
}
|
||||
|
||||
// *******************************************************************************************************************************
|
||||
// updatet datei eintrag auf der karte und verkettet die dazugehörigen fat cluster.
|
||||
// füllt den aktuell beschriebenen sektor mit 0x00, da sonst die datei nicht richtig angezeigt wird.
|
||||
// darf nur während schreibe operationen aufgerufen werden !
|
||||
// *******************************************************************************************************************************
|
||||
void fileUpdate(void){
|
||||
|
||||
unsigned int comp_cntOfBytes=file.cntOfBytes; // sicher nötig wegen schleife...
|
||||
while( comp_cntOfBytes < 512 ){ // sektor ist beschrieben worden, daher nötigenfalls mit 00 füllen
|
||||
fat.sector[comp_cntOfBytes]=0x00; // beschreibt ungenutzte bytes mit 0x00
|
||||
comp_cntOfBytes++;
|
||||
}
|
||||
char name[13]; // zum sichern des dateinamens
|
||||
unsigned long int save_length = file.cntOfBytes + file.seek; // muss gesichert werden, wird sonst von der karte geladen und verändert !
|
||||
strcpy(name,(char *)file.name); // muss gesichert werden, wird sonst von der karte geladen und verändert !
|
||||
|
||||
fat_setClusterChain(fat_secToClust(fat.startSectors),fat_secToClust(fat.currentSectorNr)); // verketten der geschriebenen cluster
|
||||
fat_loadFileDataFromDir(name); // läd sektor, des datei eintrags, und läd daten von karte auf struct file!
|
||||
fat_makeRowDataEntry(file.row,name,32,file.firstCluster,save_length); // macht eintrag im puffer
|
||||
|
||||
fat_writeSector(fat.currentSectorNr);
|
||||
}
|
||||
|
||||
|
||||
// *******************************************************************************************************************************
|
||||
// offset byte wird übergeben. es wird durch die sektoren der datei gespult (gerechnet), bis der sektor mit dem offset byte erreicht
|
||||
// ist, dann wird der sektor geladen und der zähler für die bytes eines sektors gesetzt. wenn das byte nicht in den sektoren ist,
|
||||
// die "vorgesucht" wurden, müssen noch weitere sektoren der datei gesucht werden (sec > fat.endSectors).
|
||||
// *******************************************************************************************************************************
|
||||
void ffseek(unsigned long int offset){
|
||||
|
||||
#if (OVER_WRITE==1) // man muss den dateieintrag updaten, um die daten zu retten !!
|
||||
if( file.seek > file.length ) fileUpdate(); // fat verketten und datei update auf der karte !
|
||||
#endif
|
||||
|
||||
fat_getFatChainClustersInRow(file.firstCluster); // suchen von anfang der cluster chain aus !
|
||||
unsigned long int sec=fat.startSectors; // sektor variable zum durchgehen durch die sektoren
|
||||
file.seek=0; // weil auch von anfang an der chain gesucht wird mit 0 initialisiert
|
||||
|
||||
while(offset>=512){ /** suchen des sektors in dem offset ist **/
|
||||
sec++; // da byte nicht in diesem sektor ist, muss hochgezählt werden
|
||||
offset-=512; // ein sektor weniger in dem das byte sein kann
|
||||
file.seek+=512; // file.seek update, damit bei ffclose() die richtige file.length herauskommt
|
||||
if ( sec > fat.endSectors ){ // es müssen mehr sektoren der datei gesucht werden
|
||||
fat_getFatChainClustersInRow(fat_getNextCluster( file.lastCluster ) ); // nachladen von clustern in der chain
|
||||
sec=fat.startSectors; // setzen des 1. sektors der neu geladenen, zum weitersuchen !
|
||||
}
|
||||
}
|
||||
file.lastCluster=fat_secToClust(fat.endSectors); // letzter bekannter cluster der datei
|
||||
fat_loadSector(sec); // sektor mit offset byte laden
|
||||
file.cntOfBytes = offset; // setzen des lese zählers
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#if (SMALL_FILE_SYSTEM==0)
|
||||
|
||||
// *******************************************************************************************************************************
|
||||
// wechselt verzeichniss. start immer im root Dir.
|
||||
// MUSS in das direktory gewechselt werden, in dem die datei zum lesen/schreiben ist !
|
||||
// *******************************************************************************************************************************
|
||||
unsigned char ffcd(char name[]){
|
||||
return(fat_cd(name));
|
||||
}
|
||||
|
||||
|
||||
// *******************************************************************************************************************************
|
||||
// zeigt reihen eines clusters an, wird für ffls benötigt !
|
||||
// es wird ab dem start sektor start_sec, der dazugehörige cluster angezeigt. geprüft wird ob es ein richtiger
|
||||
// eintrag in der reihe ist (nicht gelöscht, nicht frei usw). die sektoren des clusters werden nachgeladen.
|
||||
// die dateien werden mit namen und datei größe angezeigt.
|
||||
// *******************************************************************************************************************************
|
||||
void lsRowsOfClust (unsigned long int start_sec){
|
||||
|
||||
unsigned char row; // reihen
|
||||
unsigned char sec=0; // sektoren
|
||||
unsigned char tmp[12]; // tmp string zur umwandlung
|
||||
|
||||
do{
|
||||
fat_loadSector(start_sec + sec); // sektoren des clusters laden
|
||||
for(row=0;row<16;row++){ // geht durch reihen des sektors
|
||||
fat_loadRowOfSector(row); // reihe eines sektors (auf dem puffer) laden
|
||||
if( (file.attrib==0x20||file.attrib==0x10) && (file.name[0]!=0xE5 && file.name[0]!=0x00) ){
|
||||
uputs(file.name);
|
||||
uputc(' ');
|
||||
ultoa(file.length,(char*)tmp,10);
|
||||
uputs(tmp);
|
||||
uputc('\n');
|
||||
}
|
||||
}
|
||||
}while(++sec<fat.secPerClust);
|
||||
}
|
||||
|
||||
|
||||
// *******************************************************************************************************************************
|
||||
// zeigt inhalt eines direktory an.
|
||||
// unterscheidung ob man sich im rootDir befindet nötig, weil bei fat16 im root dir eine bestimmt anzahl sektoren durchsucht
|
||||
// werden müssen und bei fat32 ab einem start cluster ! ruft lsRowsOfClust auf um cluster/sektoren anzuzeigen.
|
||||
// *******************************************************************************************************************************
|
||||
void ffls(void){
|
||||
|
||||
unsigned long int clust; // cluster
|
||||
unsigned int s; // fat16 root dir sektoren
|
||||
|
||||
if(fat.dir==0 && fat.fatType==16){ // IM ROOTDIR. fat16
|
||||
for(s=0;s<(unsigned int)(fat.dataDirSec+2-fat.rootDir);s++){ // zählt durch RootDir sektoren (errechnet anzahl rootDir sektoren).
|
||||
lsRowsOfClust(fat.rootDir+s); // zeigt reihen eines root dir clust an
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
if(fat.dir==0 && fat.fatType==32)clust=fat.rootDir; // IM ROOTDIR. fat32
|
||||
else clust=fat.dir; // NICHT ROOT DIR
|
||||
while( !((clust==0xfffffff&&fat.fatType==32)||(clust==0xffff&&fat.fatType==16)) ){ // prüft ob weitere sektoren zum lesen da sind (fat32||fat16)
|
||||
lsRowsOfClust(fat_clustToSec(clust)); // zeigt reihen des clusters an
|
||||
clust=fat_getNextCluster(clust); // liest nächsten cluster des dir-eintrags
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//*******************************************************************************************************************************
|
||||
// wechselt in das parent verzeichniss (ein verzeichniss zurück !)
|
||||
// die variable fat.dir enthält den start cluster des direktory in dem man sich grade befindet, anhand diesem,
|
||||
// kann der "." bzw ".." eintrag im ersten sektor des direktory ausgelesen und das parent direktory bestimmt werden.
|
||||
//*******************************************************************************************************************************
|
||||
unsigned char ffcdLower(void){
|
||||
|
||||
if(fat.dir==0)return(1); // im root dir, man kann nicht höher !
|
||||
|
||||
fat_loadSector(fat_clustToSec(fat.dir)); // läd 1. sektor des aktuellen direktory.
|
||||
fat_loadRowOfSector(1); // ".." eintrag (parent dir) ist 0 wenn parent == root
|
||||
fat.dir=file.firstCluster; // dir setzen
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
#ifndef __AVR_ATmega8__
|
||||
|
||||
// *******************************************************************************************************************************
|
||||
// erstellt einen dir eintrag im aktuellen verzeichniss.
|
||||
// prüft ob es den den dir-namen schon gibt, dann wird nichts angelegt.
|
||||
// wenn ok, dann wird ein freier cluster gesucht, als ende markiert, der eintrag ins dir geschrieben.
|
||||
// dann wird der cluster des dirs aufbereitet. der erste sektor des clusters enthält den "." und ".." eintrag.
|
||||
// der "." hat den 1. cluster des eigenen dirs. der ".." eintrag ist der 1. cluster des parent dirs.
|
||||
// ein dir wird immer mit 0x00 initialisiert ! also alle einträge der sektoren des clusters ( bis auf . und .. einträge)!
|
||||
// *******************************************************************************************************************************
|
||||
void ffmkdir(char name[]){
|
||||
|
||||
unsigned char i;
|
||||
unsigned int j;
|
||||
|
||||
if(0==fat_loadFileDataFromDir(name))return ; // prüft ob dirname im dir schon vorhanden, wenn ja, abbruch !
|
||||
|
||||
// cluster in fat setzen, und ordner eintrg im aktuellen verzeichniss machen.
|
||||
fat_getFreeClustersInRow(2); // holt neue freie cluster, ab cluster 2 ...
|
||||
fat_setCluster(fat_secToClust(fat.startSectors),0x0fffffff); // fat16/32 cluster chain ende setzen. (neuer ordner in fat)
|
||||
file.firstCluster=fat_secToClust(fat.startSectors); // dammit fat_makeFileEntry den cluster richtig setzen kann
|
||||
fat_makeFileEntry(name,0x10,0); // macht dir eintrag im aktuellen verzeichniss (legt ordner im partent verzeichniss an)
|
||||
|
||||
// aufbereiten des puffers
|
||||
j=511;
|
||||
do{
|
||||
fat.sector[j]=0x00; //schreibt puffer fat.sector voll mit 0x00==leer
|
||||
}while(j--);
|
||||
|
||||
// aufbereiten des clusters
|
||||
for(i=1;i<fat.secPerClust;i++){ // ein dir cluster muss mit 0x00 initialisiert werden !
|
||||
fat_writeSector(fat.startSectors+i); // löschen des cluster (überschreibt mit 0x00), wichtig bei ffls!
|
||||
}
|
||||
|
||||
// aufbereiten des neuen dir sektors mit "." und ".." eintraegen !
|
||||
fat_makeRowDataEntry(0,". ",0x10,file.firstCluster,0); // macht "." eintrag des dirs
|
||||
fat_makeRowDataEntry(1,".. ",0x10,fat.dir,0); // macht ".." eintrag des dirs
|
||||
fat_writeSector(fat_clustToSec(file.firstCluster)); // schreibt einträge auf karte !
|
||||
}
|
||||
|
||||
#endif // ffmkdir wegen atmega8
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if (WRITE==1)
|
||||
|
||||
//*******************************************************************************************************************************
|
||||
// löscht datei/ordner aus aktuellem verzeichniss, wenn es die datei gibt.
|
||||
// löscht dateien und ordner rekursiv !
|
||||
//*******************************************************************************************************************************
|
||||
unsigned char ffrm(char name[]){
|
||||
|
||||
if(0==fat_loadFileDataFromDir(name)){ // datei oder ordner ist vorhanden, nur dann lösch operation
|
||||
|
||||
if(file.attrib!=0x10){ // ist datei.
|
||||
fat.sector[file.row<<5]=0xE5; // datei gelöscht markieren (file.row*32, damit man auf reihen anfang kommt)
|
||||
if((file.row-1)>=0){ // gibt es einen eintrag davor ?
|
||||
if(fat.sector[(file.row<<5)-21]==0x0f)fat.sector[(file.row<<5)-32]=0xE5; // langer datei eintag auch gelöscht.
|
||||
}
|
||||
fat.bufferDirty=1; // eintrag in puffer gemacht.
|
||||
if(0==fat_getNextCluster(file.firstCluster)) return(0); // 1.cluster ist leer ?!?
|
||||
fat_delClusterChain(file.firstCluster); // löscht die zu der datei gehörige cluster-chain aus der fat.
|
||||
return(0);
|
||||
}
|
||||
|
||||
//TODO noch nicht optimal. zu viele schreib vorgänge beim löschen von datei einträgen. max bis zu 16/sektor !
|
||||
else{ // ist ordner, dann rekursiv löschen !!
|
||||
#ifndef __AVR_ATmega8__ // mega8 zu klein für die funktionalität....
|
||||
unsigned long int parent;
|
||||
unsigned long int own;
|
||||
unsigned long int clustsOfDir; // um durch die cluster chain eines dirs zu gehen.
|
||||
unsigned char cntSecOfClust=0;
|
||||
unsigned char i=0;
|
||||
|
||||
fat.sector[file.row<<5]=0xE5; // löscht dir eintrag
|
||||
if((file.row-1)>=0){ // gibt es einen eintrag davor (langer datei eintrag)?
|
||||
if(fat.sector[(file.row<<5)-21]==0x0f)fat.sector[(file.row<<5)-32]=0xE5; // langer datei eintag auch gelöscht
|
||||
}
|
||||
fat.bufferDirty=1; // puffer eintrag gemacht
|
||||
|
||||
parent=fat.dir; // der ordner in dem der zu löschende ordner ist.
|
||||
own=file.firstCluster; // der 1. cluster des ordners der zu löschen ist.
|
||||
clustsOfDir=file.firstCluster; // die "cluster" des zu löschenden ordners
|
||||
|
||||
do{ // geht durch cluster des dirs
|
||||
fat_loadSector(fat_clustToSec(clustsOfDir)); // sektor des dirs laden
|
||||
do{ // geht durch sektoren des clusters
|
||||
do{ // geht durch reihen des sektors
|
||||
fat_loadRowOfSector(i);
|
||||
|
||||
if(file.attrib!=0x10 && file.attrib!=0x00 && file.name[0]!=0xE5){ // ist kein ordner,noch nicht gelöscht, kein freier eintrag
|
||||
fat.sector[i<<5]=0xE5; // erster eintrag der reihe als gelöscht markiert
|
||||
fat.bufferDirty=1; // puffer eintrag gemacht
|
||||
if(file.attrib==0x20){ // ist datei!
|
||||
fat_delClusterChain(file.firstCluster); // ist datei, dann cluster-chain der datei löschen
|
||||
fat_loadSector(fat_clustToSec(clustsOfDir)+cntSecOfClust); // sektor neu laden, weil löschen der chain, den puffer nutzt.
|
||||
}
|
||||
}
|
||||
|
||||
if(file.attrib==0x10 && file.name[0]=='.'){ // "." oder ".." eintrag erkannt, löschen !
|
||||
fat.sector[i<<5]=0xE5; // eintrag als gelöscht markiert
|
||||
fat.bufferDirty=1; // puffer eintrag gemacht
|
||||
}
|
||||
|
||||
if(file.attrib==0x10 && file.name[0]!='.' && file.name[0]!=0xE5 && file.name[0]!=0){ // ordner erkannt !
|
||||
fat.sector[i<<5]=0xE5; // dir eintrag als gelöscht markiert
|
||||
fat.bufferDirty=1; // puffer eintrag gemacht
|
||||
fat_loadSector(fat_clustToSec(file.firstCluster)); // sektor des dirs laden
|
||||
clustsOfDir=file.firstCluster; // eigenes dir ist file.firstCluster
|
||||
own=file.firstCluster; // eigener start cluster/dir
|
||||
fat_loadRowOfSector(1); // ".." laden um parent zu bestimmen
|
||||
parent=file.firstCluster; // parent sichern.
|
||||
cntSecOfClust=0; // init von gelesenen sektoren und reihen !
|
||||
i=0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(file.name[0]==0x00){ // ende des dirs erreicht, wenn nicht voll !!
|
||||
if(parent==fat.dir){ // erfolgreich alles gelöscht
|
||||
fat_delClusterChain(own); // cluster chain des ordners löschen
|
||||
return(0);
|
||||
}
|
||||
fat_delClusterChain(own); // cluster chain des ordners löschen
|
||||
clustsOfDir=parent; // parent ist jetzt wieder arbeisverzeichniss.
|
||||
own=parent; // arbeitsverzeichniss setzten
|
||||
fat_loadSector(fat_clustToSec(own)); // sektor des dirs laden
|
||||
fat_loadRowOfSector(1); // ".." laden um parent zu bestimmen
|
||||
parent=file.firstCluster; // parent sichern.
|
||||
cntSecOfClust=0; // init von gelesenen sektoren und reihen !
|
||||
i=0;
|
||||
continue;
|
||||
}
|
||||
|
||||
i++;
|
||||
}while(i<16); // geht durch reihen des sektors.
|
||||
|
||||
i=0; // neuer sektor -> reihen von vorne.
|
||||
cntSecOfClust++;
|
||||
fat_loadSector(fat_clustToSec(clustsOfDir)+cntSecOfClust); // läd sektoren des clusters nach
|
||||
}while(cntSecOfClust<fat.secPerClust); // geht durch sektoren des clusters.
|
||||
|
||||
cntSecOfClust=0; // neuer cluster -> sektoren von vorne.
|
||||
clustsOfDir=fat_getNextCluster(clustsOfDir); // sucht neuen cluster der cluster-chain.
|
||||
}while( !((clustsOfDir==0xfffffff && fat.fatType==32) || (clustsOfDir==0xffff && fat.fatType==16)) ); // geht durch cluster des dirs.
|
||||
fat_delClusterChain(own); // hier landet man, wenn der ordner voll war (auf cluster "ebene")!!
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
return(1); // fehler, nicht gefunden?
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
//*******************************************************************************************************************************
|
||||
// liest 512 bytes aus dem puffer fat.sector. dann werden neue 512 bytes der datei geladen, sind nicht genügend verkettete
|
||||
// sektoren in einer reihe bekannt, wird in der fat nachgeschaut. dann werden weiter bekannte nachgeladen...
|
||||
//*******************************************************************************************************************************
|
||||
inline unsigned char ffread(void){
|
||||
|
||||
if(file.cntOfBytes==512){ /** EINEN SEKTOR GLESEN (ab hier 2 möglichkeiten !) **/
|
||||
file.cntOfBytes=0; // byte zähler zurück setzen
|
||||
if( fat.currentSectorNr == fat.endSectors ){ /** 1.) nötig mehr sektoren der chain zu laden (mit ein bisschen glück nur alle 512*MAX_CLUSTERS_IN_ROW bytes)**/
|
||||
fat_getFatChainClustersInRow(fat_getNextCluster(fat_secToClust( fat.endSectors) )); // nachladen von clustern in der chain
|
||||
fat.currentSectorNr=fat.startSectors-1; // setzen des nächsten sektors um weiter lesen zu können..
|
||||
}
|
||||
fat_loadSector(fat.currentSectorNr+1); /** 2.) die bekannten in einer reihe reichen noch.(nur alle 512 bytes)**/
|
||||
}
|
||||
|
||||
return fat.sector[file.cntOfBytes++]; // rückgabe, byte des sektors (NACH rückgabe erhöhen von zähler ! )
|
||||
}
|
||||
|
||||
|
||||
#if (WRITE==1)
|
||||
#if (OVER_WRITE==0) // nicht überschreibende write funktion
|
||||
|
||||
//*******************************************************************************************************************************
|
||||
// schreibt 512 byte blöcke auf den puffer fat.sector. dann wird dieser auf die karte geschrieben. wenn genügend feie
|
||||
// sektoren zum beschreiben bekannt sind(datenmenge zu groß), muss nicht in der fat nachgeschaut werden. sollten nicht genügend
|
||||
// zusammenhängende sektoren bekannt sein, werden die alten verkettet und neue gesucht. es ist nötig sich den letzten bekannten
|
||||
// einer kette zu merken -> file.lastCluster, um auch nicht zusammenhängende cluster verketten zu können (fat_setClusterChain macht das)!
|
||||
//*******************************************************************************************************************************
|
||||
inline void ffwrite(unsigned char c){
|
||||
|
||||
fat.sector[file.cntOfBytes++]=c; // schreiben des chars auf den puffer sector und zähler erhöhen (pre-increment)
|
||||
fat.bufferDirty=1; // puffer dirty weil geschrieben und noch nicht auf karte.
|
||||
|
||||
if( file.cntOfBytes==512 ){ /** SEKTOR VOLL ( 2 möglichkeiten ab hier !) **/
|
||||
file.cntOfBytes=0; // rücksetzen des sektor byte zählers
|
||||
mmc_write_sector(fat.currentSectorNr,fat.sector); /** 1.) vollen sektor auf karte schreiben **/
|
||||
fat.bufferDirty=0; // puffer jetzt clear, weil grade alles geschrieben.
|
||||
file.seek+=512; // position in der datei erhöhen, weil grade 512 bytes geschrieben
|
||||
if( fat.currentSectorNr==fat.endSectors ){ /** 2.) es ist nötig, neue freie zu suchen und die alten zu verketten (mit ein bischen glück nur alle 512*MAX_CLUSTERS_IN_ROW bytes) **/
|
||||
fat_setClusterChain( fat_secToClust(fat.startSectors) , fat_secToClust(fat.endSectors) ); // verketten der beschriebenen
|
||||
fat_getFreeClustersInRow(file.lastCluster); // suchen von leeren sektoren.
|
||||
fat.currentSectorNr=fat.startSectors-1; // setzen des 1. sektors der neuen reihe zum schreiben.
|
||||
}
|
||||
fat.currentSectorNr++; // nächsten sektor zum beschreiben.
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if (OVER_WRITE==1) // überschreibende write funktion, nicht performant, weil immer auch noch ein sektor geladen werden muss
|
||||
|
||||
//*******************************************************************************************************************************
|
||||
// schreibt 512 byte blöcke auf den puffer fat.sector. dann wird dieser auf die karte geschrieben. wenn genügend feie
|
||||
// sektoren zum beschreiben bekannt sind, muss nicht in der fat nachgeschaut werden. sollten nicht genügend zusammenhängende
|
||||
// sektoren bekannt sein(datenmenge zu groß), werden die alten verkettet und neue gesucht. es ist nötig sich den letzten bekannten einer
|
||||
// kette zu merken -> file.lastCluster, um auch nicht zusammenhängende cluster verketten zu können (fat_setClusterChain macht das)!
|
||||
// es ist beim überschreiben nötig, die schon beschriebenen sektoren der datei zu laden, damit man die richtigen daten
|
||||
// hat. das ist blöd, weil so ein daten overhead von 50% entsteht. da lesen aber schneller als schreiben geht, verliert man nicht 50% an geschwindigkeit.
|
||||
//*******************************************************************************************************************************
|
||||
inline void ffwrite(unsigned char c){
|
||||
|
||||
fat.sector[file.cntOfBytes++]=c; // schreiben des chars auf den puffer sector und zähler erhöhen (pre-increment)
|
||||
fat.bufferDirty=1; // puffer dirty weil geschrieben und noch nicht auf karte.
|
||||
|
||||
if( file.cntOfBytes==512 ){ /** SEKTOR VOLL ( 2 möglichkeiten ab hier !) **/
|
||||
file.cntOfBytes=0; // rücksetzen des sektor byte zählers.
|
||||
mmc_write_sector(fat.currentSectorNr,fat.sector); /** 1.) vollen sektor auf karte schreiben**/
|
||||
fat.bufferDirty=0; // puffer jetzt clear, weil grade alles geschrieben.
|
||||
file.seek+=512; // position in der datei erhöhen, weil grade 512 bytes geschrieben.
|
||||
if( fat.currentSectorNr==fat.endSectors ){ /** 2.) es ist nötig, neue freie zu suchen und die alten zu verketten (mit ein bischen glück nur alle 512*MAX_CLUSTERS_IN_ROW bytes) **/
|
||||
if( file.seek > file.length ){ // außerhalb der datei !!
|
||||
fat_setClusterChain( fat_secToClust(fat.startSectors) , fat_secToClust(fat.endSectors) ); // verketten der beschriebenen.
|
||||
fat_getFreeClustersInRow( file.lastCluster ); // neue leere sektoren benötigt, also suchen.
|
||||
}
|
||||
else {
|
||||
fat_getFatChainClustersInRow( fat_getNextCluster(file.lastCluster) ); // noch innerhalb der datei, deshlab verkettete suchen.
|
||||
}
|
||||
fat.currentSectorNr=fat.startSectors-1; // setzen des 1. sektors der neuen reihe zum schreiben.
|
||||
}
|
||||
fat.currentSectorNr++; // nächsten sektor zum beschreiben.
|
||||
mmc_read_sector(fat.currentSectorNr,fat.sector); // wegen überschreiben, muss der zu beschreibende sektor geladen werden...
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// *******************************************************************************************************************************
|
||||
// schreibt string auf karte, siehe ffwrite()
|
||||
// *******************************************************************************************************************************
|
||||
inline void ffwrites(const char *s ){
|
||||
while (*s) ffwrite(*s++);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
|
||||
|
||||
|
||||
#ifndef _FILE_H
|
||||
|
||||
#define _FILE_H
|
||||
|
||||
// **************************************************************************************************************************
|
||||
// funktionen
|
||||
|
||||
extern inline unsigned char ffread(void); // liest byte-weise aus der datei (puffert immer 512 bytes zwischen)
|
||||
extern inline void ffwrite(unsigned char c); // schreibt ein byte in die geöffnete datei
|
||||
extern inline void ffwrites(const char *s ); // schreibt string auf karte
|
||||
|
||||
extern unsigned char ffopen(char name[]); // kann immer nur 1 datei bearbeiten.
|
||||
extern unsigned char ffclose(void); // muss aufgerufen werden bevor neue datei bearbeitet wird.
|
||||
|
||||
extern void ffseek(unsigned long int offset); // setzt zeiger:bytesOfSec auf position in der geöffneten datei.
|
||||
extern unsigned char ffcd(char name[]); // wechselt direktory
|
||||
extern void ffls(void); // zeigt direktory inhalt an
|
||||
extern unsigned char ffcdLower(void); // geht ein direktory zurück, also cd.. (parent direktory)
|
||||
extern unsigned char ffrm(char name[]); // löscht datei aus aktuellem verzeichniss.
|
||||
extern void ffmkdir(char name[]); // legt ordner in aktuellem verzeichniss an.
|
||||
void lsRowsOfClust (unsigned long int start_sec); // zeigt reihen eines clusters an, ab start_sec
|
||||
void fileUpdate(void); // updatet datei eintrag auf karte
|
||||
|
||||
// **************************************************************************************************************************// #######################################################################################################################
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
|
||||
#ifndef _HARDWARE_H
|
||||
/*
|
||||
hier sind die beiden hardware abhängigen bibliotheken zu includen !
|
||||
welchen umfang diese haben müssen (an funktionen), muss man in den bibliotheken nachsehen.
|
||||
*/
|
||||
#define _HARDWARE_H
|
||||
#include "uart.h"
|
||||
#include "mmc.h"
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <avr/io.h>
|
||||
|
||||
#include "main.h"
|
||||
#include "file.h"
|
||||
#include "fat.h"
|
||||
#include "hardware.h"
|
||||
|
||||
|
||||
//*****************************************************************************************************************
|
||||
|
||||
void main(void){
|
||||
|
||||
uinit(); // uart initialisierung
|
||||
|
||||
|
||||
uputs((unsigned char*)"\nBoot");
|
||||
|
||||
while (mmc_init() !=0){ //ist der Rückgabewert ungleich NULL ist ein Fehler aufgetreten
|
||||
;
|
||||
}
|
||||
|
||||
uputs((unsigned char*)"... ");
|
||||
|
||||
if(0==fat_initfat()){ //ist der Rückgabewert ungleich NULL ist ein Fehler aufgetreten
|
||||
|
||||
uputs((unsigned char*)"Ok\n"); // wenn auf dem terminal "Boot... OK" zu lesen ist, ist init ok. jetzt kann man schreiben/lesen
|
||||
|
||||
beispiele();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// *****************************************************************************************************************
|
||||
void beispiele(void){
|
||||
|
||||
char datei[12]="TEST TXT"; // hier muss platz für 11 zeichen sein (8.3), da fat_str diesen string benutzt !!
|
||||
fat_str(datei); // wandelt "test.txt" in das fat format 8.3 der form: "TEST TXT" muss immer dieses Format haben, auch ordner !!
|
||||
|
||||
// 0.) ______________löschen von dateien/ordnern (ordner rekursiv)____________________________________________
|
||||
ffrm( datei ); // löschen der datei/ordner falls vorhanden
|
||||
|
||||
// 1.) ______________anlegen und schreiben____________________________________________________________________
|
||||
// öffnet datei, wenn nicht vorhanden, legt ffopen datei an (rückgabewert = 1 datei existiert, also nur öffnen, 2 = angelegt).
|
||||
ffopen( datei );
|
||||
|
||||
// schreibt string
|
||||
ffwrites((char*)"Hallo Datei :)");
|
||||
// neue zeile in der datei
|
||||
ffwrite(0x0D);
|
||||
ffwrite(0x0A);
|
||||
|
||||
// schließt datei
|
||||
ffclose();
|
||||
|
||||
// 2.)________________ändern von vorhandenen daten in dateien__________________________________________________
|
||||
ffopen( datei ); // siehe oben...
|
||||
ffseek(12); // spult in datei auf position 12 vor (fängt immer bei 0 an zu zählen !)
|
||||
ffwrite(';'); // schreibt dann ab position 12 (überschreibt daten der datei, hier nur 1 zeichen)
|
||||
ffclose(); // schließt datei
|
||||
|
||||
// 3.)________________lesen von dateien_________________________________________________________________________
|
||||
ffopen( datei ); // siehe oben...
|
||||
unsigned long int seek=file.length; // eine variable setzen und runterzählen bis 0 geht am schnellsten !
|
||||
do{
|
||||
uputc(ffread()); // liest ein zeichen und gibt es über uart aus !
|
||||
}while(--seek); // liest solange bytes da sind (von datei länge bis 0)
|
||||
ffclose(); // schließt datei
|
||||
|
||||
uputc('\n'); // neue zeile weil neue unteraufgabe
|
||||
|
||||
// 4.)________________anhängen von daten an datei_______________________________________________________________
|
||||
ffopen( datei); // siehe oben...
|
||||
ffseek(file.length); // spult in datei ans ende
|
||||
ffwrites((char*)"Dies ist ein Test..."); // siehe oben
|
||||
// neue zeile in der datei
|
||||
ffwrite(0x0D);
|
||||
ffwrite(0x0A);
|
||||
ffclose(); // schließt datei
|
||||
|
||||
// 3.)________________lesen von dateien_________________________________________________________________________
|
||||
ffopen( datei ); // siehe oben...
|
||||
seek=file.length; // eine variable setzen und runterzählen bis 0 geht am schnellsten !
|
||||
do{
|
||||
uputc(ffread()); // liest ein zeichen und gibt es über uart aus !
|
||||
}while(--seek); // liest solange bytes da sind (von datei länge bis 0)
|
||||
ffclose(); // schließt datei
|
||||
|
||||
}
|
||||
|
||||
// *****************************************************************************************************************
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <avr/io.h>
|
||||
|
||||
|
||||
#ifndef _MAIN_H
|
||||
|
||||
#define _MAIN_H
|
||||
|
||||
#define F_CPU 16000000
|
||||
|
||||
#endif
|
||||
@@ -1,272 +0,0 @@
|
||||
/*#######################################################################################
|
||||
Connect AVR to MMC/SD
|
||||
|
||||
Copyright (C) 2004 Ulrich Radig
|
||||
|
||||
Bei Fragen und Verbesserungen wendet euch per EMail an
|
||||
|
||||
mail@ulrichradig.de
|
||||
|
||||
oder im Forum meiner Web Page : www.ulrichradig.de
|
||||
|
||||
Dieses Programm ist freie Software. Sie k<>nnen es unter den Bedingungen der
|
||||
GNU General Public License, wie von der Free Software Foundation ver<65>ffentlicht,
|
||||
weitergeben und/oder modifizieren, entweder gem<65><6D> Version 2 der Lizenz oder
|
||||
(nach Ihrer Option) jeder sp<73>teren Version.
|
||||
|
||||
Die Ver<65>ffentlichung dieses Programms erfolgt in der Hoffnung,
|
||||
da<EFBFBD> es Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE,
|
||||
sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT
|
||||
F<EFBFBD>R EINEN BESTIMMTEN ZWECK. Details finden Sie in der GNU General Public License.
|
||||
|
||||
Sie sollten eine Kopie der GNU General Public License zusammen mit diesem
|
||||
Programm erhalten haben.
|
||||
Falls nicht, schreiben Sie an die Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||||
#######################################################################################*/
|
||||
|
||||
#include <avr/io.h>
|
||||
|
||||
#include "mmc.h"
|
||||
|
||||
|
||||
//############################################################################
|
||||
//Routine zur Initialisierung der MMC/SD-Karte (SPI-MODE)
|
||||
unsigned char mmc_init (void){
|
||||
|
||||
unsigned char a;
|
||||
unsigned int Timeout = 0;
|
||||
|
||||
//Konfiguration des Ports an der die MMC/SD-Karte angeschlossen wurde
|
||||
MMC_Direction_REG &=~(1<<SPI_DI); //Setzen von Pin MMC_DI auf Input
|
||||
MMC_Direction_REG |= (1<<SPI_Clock); //Setzen von Pin MMC_Clock auf Output
|
||||
MMC_Direction_REG |= (1<<SPI_DO); //Setzen von Pin MMC_DO auf Output
|
||||
MMC_Direction_REG |= (1<<MMC_Chip_Select);//Setzen von Pin MMC_Chip_Select auf Output
|
||||
MMC_Direction_REG |= (1<<SPI_SS);
|
||||
MMC_Write |= (1<<MMC_Chip_Select); //Setzt den Pin MMC_Chip_Select auf High Pegel
|
||||
|
||||
for(a=0;a<200;a++){
|
||||
nop();
|
||||
}; //Wartet eine kurze Zeit
|
||||
|
||||
//Aktiviren des SPI - Bus, Clock = Idel LOW
|
||||
//SPI Clock teilen durch 128
|
||||
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPR1); //Enable SPI, SPI in Master Mode
|
||||
|
||||
//Initialisiere MMC/SD-Karte in den SPI-Mode
|
||||
for (a = 0;a<0x0f;a++){ //Sendet min 74+ Clocks an die MMC/SD-Karte
|
||||
mmc_write_byte(0xff);
|
||||
}
|
||||
|
||||
//Sendet Commando CMD0 an MMC/SD-Karte
|
||||
unsigned char CMD[] = {0x40,0x00,0x00,0x00,0x00,0x95};
|
||||
while(mmc_write_command (CMD) !=1){
|
||||
if (Timeout++ > 200){
|
||||
MMC_Disable();
|
||||
return(1); //Abbruch bei Commando1 (Return Code1)
|
||||
}
|
||||
}
|
||||
//Sendet Commando CMD1 an MMC/SD-Karte
|
||||
Timeout = 0;
|
||||
CMD[0] = 0x41;//Commando 1
|
||||
CMD[5] = 0xFF;
|
||||
while( mmc_write_command (CMD) !=0){
|
||||
if (Timeout++ > 400){
|
||||
MMC_Disable();
|
||||
return(2); //Abbruch bei Commando2 (Return Code2)
|
||||
}
|
||||
}
|
||||
|
||||
//SPI Bus auf max Geschwindigkeit
|
||||
SPCR &= ~((1<<SPR0) | (1<<SPR1));
|
||||
SPSR = SPSR|(1<<SPI2X);
|
||||
|
||||
//set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
|
||||
MMC_Disable();
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
//############################################################################
|
||||
//Sendet ein Commando an die MMC/SD-Karte
|
||||
unsigned char mmc_write_command (unsigned char *cmd){
|
||||
unsigned char a;
|
||||
unsigned char tmp = 0xff;
|
||||
unsigned int Timeout = 0;
|
||||
|
||||
//set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
|
||||
MMC_Disable();
|
||||
|
||||
//sendet 8 Clock Impulse
|
||||
mmc_write_byte(0xFF);
|
||||
|
||||
//set MMC_Chip_Select to low (MMC/SD-Karte Aktiv)
|
||||
MMC_Enable();
|
||||
|
||||
//sendet 6 Byte Commando
|
||||
for (a = 0;a<0x06;a++){
|
||||
mmc_write_byte(*cmd++);
|
||||
}
|
||||
|
||||
//Wartet auf ein gültige Antwort von der MMC/SD-Karte
|
||||
while (tmp == 0xff){
|
||||
tmp = mmc_read_byte();
|
||||
if (Timeout++ > 500){
|
||||
break; //Abbruch da die MMC/SD-Karte nicht Antwortet
|
||||
}
|
||||
}
|
||||
return(tmp);
|
||||
}
|
||||
|
||||
//############################################################################
|
||||
//Routine zum Empfangen eines Bytes von der MMC-Karte
|
||||
unsigned char mmc_read_byte (void){
|
||||
SPDR = 0xff;
|
||||
while(!(SPSR & (1<<SPIF))){};
|
||||
return (SPDR);
|
||||
}
|
||||
|
||||
//############################################################################
|
||||
//Routine zum Senden eines Bytes zur MMC-Karte
|
||||
void mmc_write_byte (unsigned char Byte){
|
||||
SPDR = Byte; //Sendet ein Byte
|
||||
while(!(SPSR & (1<<SPIF))){ ; //Wartet bis Byte gesendet wurde
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//############################################################################
|
||||
//Routine zum schreiben eines Blocks(512Byte) auf die MMC/SD-Karte
|
||||
unsigned char mmc_write_sector (unsigned long addr,unsigned char *Buffer){
|
||||
unsigned char tmp;
|
||||
unsigned int a;
|
||||
unsigned char b;
|
||||
|
||||
//Commando 24 zum schreiben eines Blocks auf die MMC/SD - Karte
|
||||
unsigned char cmd[] = {0x58,0x00,0x00,0x00,0x00,0xFF};
|
||||
|
||||
/*Die Adressierung der MMC/SD-Karte wird in Bytes angegeben,
|
||||
addr wird von Blocks zu Bytes umgerechnet danach werden
|
||||
diese in das Commando eingefuegt*/
|
||||
|
||||
addr = addr << 9; //addr = addr * 512
|
||||
|
||||
cmd[1] = ((addr & 0xFF000000) >>24 );
|
||||
cmd[2] = ((addr & 0x00FF0000) >>16 );
|
||||
cmd[3] = ((addr & 0x0000FF00) >>8 );
|
||||
|
||||
//Sendet Commando cmd24 an MMC/SD-Karte (Write 1 Block/512 Bytes)
|
||||
tmp = mmc_write_command (cmd);
|
||||
|
||||
if (tmp != 0) return(tmp);
|
||||
|
||||
//Wartet einen Moment und sendet einen Clock an die MMC/SD-Karte
|
||||
for (b=0;b<100;b++)
|
||||
{
|
||||
mmc_read_byte();
|
||||
}
|
||||
|
||||
//Sendet Start Byte an MMC/SD-Karte
|
||||
mmc_write_byte(0xFE);
|
||||
|
||||
//Schreiben des Bolcks (512Bytes) auf MMC/SD-Karte
|
||||
a=511; // do while konstrukt weils schneller geht
|
||||
tmp=*Buffer++; // holt neues byte aus ram in register
|
||||
do{
|
||||
SPDR = tmp; //Sendet ein Byte
|
||||
tmp=*Buffer++; // holt schonmal neues aus ram in register
|
||||
while( !(SPSR & (1<<SPIF)) ){ ;}//Wartet bis Byte gesendet wurde
|
||||
}while(a--);
|
||||
|
||||
//CRC-Byte schreiben
|
||||
mmc_write_byte(0xFF); //Schreibt Dummy CRC
|
||||
mmc_write_byte(0xFF); //CRC Code wird nicht benutzt
|
||||
|
||||
//Fehler beim schreiben? (Data Response XXX00101 = OK)
|
||||
if((mmc_read_byte()&0x1F) != 0x05) return(1);
|
||||
|
||||
//Wartet auf MMC/SD-Karte Bussy
|
||||
while (mmc_read_byte() != 0xff){};
|
||||
|
||||
//set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
|
||||
MMC_Disable();
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
//############################################################################
|
||||
//Routine zum lesen des CID Registers von der MMC/SD-Karte (16Bytes)
|
||||
void mmc_read_block(unsigned char *cmd,unsigned char *Buffer,unsigned int Bytes){
|
||||
|
||||
unsigned int a;
|
||||
|
||||
//Sendet Commando cmd an MMC/SD-Karte
|
||||
if (mmc_write_command (cmd) != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//Wartet auf Start Byte von der MMC/SD-Karte (FEh/Start Byte)
|
||||
|
||||
while (mmc_read_byte() != 0xfe){};
|
||||
|
||||
//Lesen des Bolcks (normal 512Bytes) von MMC/SD-Karte
|
||||
for (a=0;a<Bytes;a++)
|
||||
{
|
||||
*Buffer++ = mmc_read_byte();
|
||||
}
|
||||
//CRC-Byte auslesen
|
||||
mmc_read_byte();//CRC - Byte wird nicht ausgewertet
|
||||
mmc_read_byte();//CRC - Byte wird nicht ausgewertet
|
||||
|
||||
//set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
|
||||
MMC_Disable();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//############################################################################
|
||||
//Routine zum lesen eines Blocks(512Byte) von der MMC/SD-Karte
|
||||
unsigned char mmc_read_sector (unsigned long addr,unsigned char *Buffer){
|
||||
//Commando 16 zum lesen eines Blocks von der MMC/SD - Karte
|
||||
unsigned char cmd[] = {0x51,0x00,0x00,0x00,0x00,0xFF};
|
||||
|
||||
/*Die Adressierung der MMC/SD-Karte wird in Bytes angegeben,
|
||||
addr wird von Blocks zu Bytes umgerechnet danach werden
|
||||
diese in das Commando eingef<65>gt*/
|
||||
|
||||
addr = addr << 9; //addr = addr * 512
|
||||
|
||||
cmd[1] = ((addr & 0xFF000000) >>24 );
|
||||
cmd[2] = ((addr & 0x00FF0000) >>16 );
|
||||
cmd[3] = ((addr & 0x0000FF00) >>8 );
|
||||
|
||||
mmc_read_block(cmd,Buffer,512);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
//############################################################################
|
||||
//Routine zum lesen des CID Registers von der MMC/SD-Karte (16Bytes)
|
||||
unsigned char mmc_read_cid (unsigned char *Buffer){
|
||||
//Commando zum lesen des CID Registers
|
||||
unsigned char cmd[] = {0x4A,0x00,0x00,0x00,0x00,0xFF};
|
||||
|
||||
mmc_read_block(cmd,Buffer,16);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
//############################################################################
|
||||
//Routine zum lesen des CSD Registers von der MMC/SD-Karte (16Bytes)
|
||||
unsigned char mmc_read_csd (unsigned char *Buffer){
|
||||
//Commando zum lesen des CSD Registers
|
||||
unsigned char cmd[] = {0x49,0x00,0x00,0x00,0x00,0xFF};
|
||||
|
||||
mmc_read_block(cmd,Buffer,16);
|
||||
|
||||
return(0);
|
||||
}
|
||||
*/
|
||||
@@ -1,74 +0,0 @@
|
||||
/*#######################################################################################
|
||||
Connect ARM to MMC/SD
|
||||
|
||||
Copyright (C) 2004 Ulrich Radig
|
||||
#######################################################################################*/
|
||||
|
||||
|
||||
#ifndef _MMC_H
|
||||
#define _MMC_H
|
||||
|
||||
#define MMC_Write PORTB //Port an der die MMC/SD-Karte angeschlossen ist also des SPI
|
||||
#define MMC_Read PINB
|
||||
#define MMC_Direction_REG DDRB
|
||||
|
||||
#if defined (__AVR_ATmega128__)
|
||||
#define SPI_DI 3 //Port Pin an dem Data Output der MMC/SD-Karte angeschlossen ist
|
||||
#define SPI_DO 2 //Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist
|
||||
#define SPI_Clock 1 //Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk)
|
||||
#define MMC_Chip_Select 4 //Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist
|
||||
#define SPI_SS 0 //Nicht Benutz mu<6D> aber definiert werden
|
||||
#endif
|
||||
|
||||
#if defined (__AVR_ATmega32__)
|
||||
#define SPI_DI 6 //Port Pin an dem Data Output der MMC/SD-Karte angeschlossen ist
|
||||
#define SPI_DO 5 //Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist
|
||||
#define SPI_Clock 7 //Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk)
|
||||
#define MMC_Chip_Select 3 //Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist
|
||||
#define SPI_SS 4 //Nicht Benutz mu<6D> aber definiert werden
|
||||
#endif
|
||||
|
||||
#if defined (__AVR_ATmega168__)
|
||||
#define SPI_DI 4 //Port Pin an dem Data Output der MMC/SD-Karte angeschlossen ist
|
||||
#define SPI_DO 3 //Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist
|
||||
#define SPI_Clock 5 //Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk)
|
||||
#define MMC_Chip_Select 1 //Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist
|
||||
#define SPI_SS 2 //Nicht Benutz mu<6D> aber definiert werden
|
||||
#endif
|
||||
|
||||
#if defined (__AVR_ATmega644__)
|
||||
#define SPI_DI 6 //Port Pin an dem Data Output der MMC/SD-Karte angeschlossen ist
|
||||
#define SPI_DO 5 //Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist
|
||||
#define SPI_Clock 7 //Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk)
|
||||
#define MMC_Chip_Select 1 //Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist
|
||||
#define SPI_SS 4 //Nicht Benutz mu<6D> aber definiert werden
|
||||
#endif
|
||||
|
||||
#if defined (__AVR_ATmega8__)
|
||||
#define SPI_DI 4 //Port Pin an dem Data Output der MMC/SD-Karte angeschlossen ist
|
||||
#define SPI_DO 3 //Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist
|
||||
#define SPI_Clock 5 //Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk)
|
||||
#define MMC_Chip_Select 1 //Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist
|
||||
#define SPI_SS 2 //Nicht Benutz mu<6D> aber definiert werden
|
||||
#endif
|
||||
|
||||
//Prototypes
|
||||
extern unsigned char mmc_read_byte(void);
|
||||
extern void mmc_write_byte(unsigned char);
|
||||
extern void mmc_read_block(unsigned char *,unsigned char *,unsigned in);
|
||||
extern unsigned char mmc_init(void);
|
||||
extern unsigned char mmc_read_sector (unsigned long,unsigned char *);
|
||||
extern unsigned char mmc_write_sector (unsigned long,unsigned char *);
|
||||
extern unsigned char mmc_write_command (unsigned char *);
|
||||
//extern unsigned char mmc_read_csd (unsigned char *);
|
||||
//extern unsigned char mmc_read_cid (unsigned char *);
|
||||
|
||||
//set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
|
||||
#define MMC_Disable() MMC_Write|= (1<<MMC_Chip_Select);
|
||||
|
||||
//set MMC_Chip_Select to low (MMC/SD-Karte Aktiv)
|
||||
#define MMC_Enable() MMC_Write&=~(1<<MMC_Chip_Select);
|
||||
|
||||
#define nop() __asm__ __volatile__ ("nop" ::)
|
||||
|
||||
#endif
|
||||
@@ -1,58 +0,0 @@
|
||||
|
||||
#include <avr/io.h>
|
||||
|
||||
#include "uart.h"
|
||||
|
||||
|
||||
//***********************Funktionen**********************************
|
||||
void uputc(unsigned char c){ //zeichen senden
|
||||
|
||||
while(!(UCSRA & (1<<UDRE))){;} //buffer voll, solange warten bis platz f<>r zeichen !!
|
||||
UDR=c; //zeichen schreiben
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
void uputs (unsigned char *s){ //string senden
|
||||
|
||||
while(*s) uputc(*s++); //sendet zeichenkette, bis ende.. '\0'
|
||||
|
||||
}
|
||||
|
||||
|
||||
// *******************************************************************
|
||||
unsigned char ugetc(void){ //zeichen holen
|
||||
|
||||
while (!(UCSRA & (1<<RXC))) {;} // warten bis Zeichen verfuegbar
|
||||
|
||||
return UDR; // Zeichen aus UDR an Aufrufer zurueckgeben
|
||||
}
|
||||
/*
|
||||
|
||||
// *******************************************************************
|
||||
void ugets(char* Buffer, unsigned char MaxLen){
|
||||
unsigned char NextChar;
|
||||
unsigned char StringLen = 0;
|
||||
|
||||
NextChar = ugetc(); // Warte auf und empfange das nächste Zeichen
|
||||
|
||||
while( NextChar != '\n' && StringLen < MaxLen - 1 ) { //string ende oder puffer voll
|
||||
*Buffer++ = NextChar;
|
||||
StringLen++;
|
||||
NextChar = ugetc();
|
||||
}
|
||||
|
||||
*Buffer = '\0'; //string abschluss
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
//*******************************************************************
|
||||
void uinit (void){ //init usart Tx, 8n1 ,UDRE interupt enable
|
||||
|
||||
UCSRC |= (3<<UCSZ0); // URSEL = 1 dann wird UCSRC benutzt sonst UBRRH ; UCSZ0=data register- 8bit; USBS stop bit 1
|
||||
//Baudrate (high und low byte)
|
||||
UBRRH = (unsigned char)(UBRR_VAL>>8);
|
||||
UBRRL = (unsigned char)UBRR_VAL;
|
||||
UCSRB |= (1<<TXEN)|(1<<RXEN); // UART TX,RX einschalten, data register empty interrupt enable,
|
||||
}
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
//*********************defs**********************************************
|
||||
|
||||
#ifndef _UART_H
|
||||
#define _UART_H
|
||||
#define F_CPU 16000000
|
||||
#define BAUD 9600l
|
||||
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) // clever runden
|
||||
|
||||
|
||||
#if defined (__AVR_ATmega168__)
|
||||
#define UDR UDR0
|
||||
#define UCSRA UCSR0A
|
||||
#define UDRE UDRE0
|
||||
#define UCSRB UCSR0B
|
||||
#define RXC RXC0
|
||||
#define UCSRC UCSR0C
|
||||
#define UCSZ0 UCSZ00
|
||||
#define RXEN RXEN0
|
||||
#define TXEN TXEN0
|
||||
#define UBRRH UBRR0H
|
||||
#define UBRRL UBRR0L
|
||||
#endif
|
||||
|
||||
//#######################################################################################################################
|
||||
// funktionen
|
||||
extern void uinit(void); //Initialisiert uart
|
||||
extern void uputc(unsigned char);
|
||||
extern void uputs (unsigned char *s);
|
||||
//extern void ugets( char*,unsigned char);
|
||||
extern unsigned char ugetc(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
Terminal VT100 zeichen
|
||||
|
||||
uputc(0x1B); //steuer zeichen ESC (hex 0x1B, dez 27) Achtung, wird erst gesendet wenn danach ein string gesendet wird !! siehe uputs uputc
|
||||
|
||||
uputs("[1K"); //links vom cursor zeile löschen
|
||||
uputs("[K"); //rechts vom cursor zeile löschen
|
||||
uputs("[2J"); //vom cursor abwärts schirm löschen
|
||||
uputs("[J"); //vom cursor aufwärts schirm löschen
|
||||
|
||||
uputs("[01;01H"); //position cursor zeile 1, spalte 1
|
||||
|
||||
* die Zeilennummer 1-24
|
||||
* die Spalternummer 1-80 oder 1-132
|
||||
|
||||
|
||||
<ESC>[paramm '-(das ist ein kleines "m" am Schluß)-'
|
||||
|
||||
Mögliche "param" sind:
|
||||
|
||||
* 0 = Normal
|
||||
* 1 = Heller (bold)
|
||||
* 4 = Unterstrichen
|
||||
* 5 = Blinkend
|
||||
* 7 = Reverse (dunkel auf hell bzw. umgekehrt)
|
||||
|
||||
Dabei können mehrere Attribute angegeben werden, dann aber mit Semikolon getrennt:
|
||||
|
||||
<ESC>[param1;param2;param3m
|
||||
*/
|
||||
@@ -1,11 +0,0 @@
|
||||
.:_______________________/\ucon64.sf.net
|
||||
__/ _____/ __ /_/ / /__ \ /____ ___/\
|
||||
_/_/ / / /__/ \ / / \ / / / /\_\/
|
||||
\ \_____/______/______/__/___/_____/__/ / .
|
||||
\/_____\______\______\__\___\_____\__\/ .
|
||||
. :
|
||||
: uCON64 2.0.0 |
|
||||
| |
|
||||
|Back To Wipe Away All Bullshit/Proprietary|
|
||||
|Console Tools w/o Sources, Style And Love!|
|
||||
`-------[UNIX/Windows/DOS/BeOS/Amiga/Mac]--'
|
||||
@@ -1 +0,0 @@
|
||||
2.0.0
|
||||
@@ -1,783 +0,0 @@
|
||||
<html><head>
|
||||
<link rel="icon" href="images/icon.png" type="image/png">
|
||||
<title>uCON64 - Changes</title></head><body bgcolor="#ffffff"><tt><br>
|
||||
The original uCON for SNES and Genesis was written by Chicken & chp in
|
||||
1993-1995<br>
|
||||
<br>
|
||||
<p>
|
||||
<a name="190">1.9.0</a><br>
|
||||
- completely re-written<br>
|
||||
- this is the first real version with support for the most consoles<br>
|
||||
<p>
|
||||
<a name="191">1.9.1</a><br>
|
||||
- bug fixes<br>
|
||||
- fixed the -xv64 routine for receive and emulation on N64<br>
|
||||
- cosmetical changes<br>
|
||||
- removed the stupid curses GUI<br>
|
||||
- optimized noisette.h for speed<br>
|
||||
- added more OPTIONS and CONSOLE SYSTEMS<br>
|
||||
<p>
|
||||
<a name="192">1.9.2</a><br>
|
||||
- started to add missing Sega System16(A/B)/System 18/dual 68000 support<br>
|
||||
- -xv64 shows now the filename on the Doctor instead of "UCON64" (sorry)<br>
|
||||
- removed -xmp3 option for SongBoy (latest information says that it will
|
||||
be a USB device with copyprotected MPE standard instead of MP3.. HAHAHAHA!!!)<br>
|
||||
- TODO: -xmp3 send MP3 file(s) to SongBoy (MP3 player for Game Boy)<br>
|
||||
- removed options which were added by mistake (like parallel transfer for Z64)<br>
|
||||
- added -ispad (looks for repeating bytes at the end of a probably padded ROM)<br>
|
||||
- added -rn (some people might find it useful)<br>
|
||||
- added -mg, -bin and 'show ROM' support for PC-Engine<br>
|
||||
- added -usms for Jos Kwanten's ultraSMS an Sega Master System/Game Gear
|
||||
emulator for the Nintendo64<br>
|
||||
- fixed aps (GRRNNNNN!!!)<br>
|
||||
- added an universal frontend (in Java) for all platforms and all programs that
|
||||
need a filename<br>
|
||||
- added CD32, CD-i and Real 3DO support<br>
|
||||
- added -bin and -ffe option for Sega Master System/Game Gear<br>
|
||||
- added database for NES roms (that enlarged the ucon64 executable by 190kb
|
||||
grnnn...) "You gotta do what you gotta do." (Futurama)<br>
|
||||
- added -db and -dbv database commands... now everyone can check if the
|
||||
uCON64 version he uses has new database entries for a console system<br>
|
||||
<p>
|
||||
<a name="193">1.9.3</a><br>
|
||||
- added -mka create APS patch support<br>
|
||||
- added -na change APS description<br>
|
||||
- added -hd, -nhd switches for SMS/Game Gear<br>
|
||||
- added auto-detection and some information for Jaguar ROMs<br>
|
||||
- added -ssc convert to Super Smart Card (Game Boy)<br>
|
||||
- fixed/added -chk fix checksum (Game Boy)<br>
|
||||
- added -gg Game Genie support for SNES<br>
|
||||
- cleaned up the usage output<br>
|
||||
- added -chk fix checksum for Super NES/Super Famicom<br>
|
||||
- removed most CDROM based consoles from usage since uCON64 could support
|
||||
them only by showing some informations about the CDROM itself (option -cdrom)<br>
|
||||
- added -gd3 convert to Professor SF(2) Game Doctor SF3/6/7 (autojoin)<br>
|
||||
- added -gdf fix Professor SF(2) Game Doctor SF3/6/7 savegame problems<br>
|
||||
<p>
|
||||
<a name="194">1.9.4</a><br>
|
||||
- included all databases for every console system that has ROMs without a
|
||||
header with text<br>
|
||||
- added 324 entries to SMS database<br>
|
||||
- added -sam convert SAM/M.A.M.E. sound to WAV; --rom=SAMFILE<br>
|
||||
- added -b2i convert BIN/RAW(2352)/Mode2(2336) to ISO; --rom=BIN_IMAGE<br>
|
||||
- added -ppf apply PPF patch (<=2.0); --rom=ISO_IMAGE --file=PATCHFILE<br>
|
||||
- added -nppf change PPF description; --rom=PATCHFILE --file=DESCRIPTION<br>
|
||||
- added -mkppf create PPF patch; --rom=ISO_IMAGE --file=CHANGED_IMAGE<br>
|
||||
- added -ip extract ip0000.bin (GD-ROM header/256 bytes); --rom=/dev/<cdrom><br>
|
||||
- added -fds convert Famicom Disk System file (diskimage) from FAM to FDS<br>
|
||||
- changed the FAQ a bit<br>
|
||||
- overworked the whole tool to make it easier to develop<br>
|
||||
- searched a new site for it (<a href="http://ucon64.sourceforge.net" target="_blank">http://ucon64.sourceforge.net</a>)<br>
|
||||
<p>
|
||||
<a name="195">1.9.5</a><br>
|
||||
- after the update release of 1.9.4 I had a closer look at my sources
|
||||
and realized that my style heavily changed since 1.9.3 the result is
|
||||
that I had to make more changes in the source starting from ucon64.c<br>
|
||||
- Gilligan wrote a nice routine to read out NeoGeo Pocket roms (added)<br>
|
||||
- reorganized the whole source<br>
|
||||
- added Game Boy Advance support<br>
|
||||
- added (GBA) -n change ROM name; --file=NEWNAME<br>
|
||||
- added (GBA) -logo restore ROM logo character data 0x04-0x9F<br>
|
||||
- added (GBA) -chk fix ROM checksum<br>
|
||||
- added (GB/Game Gear/NES) -gg apply Game Genie code (permanent)<br>
|
||||
- added (GB/Game Gear/NES/GEN/SNES) -gge encode Game Genie code<br>
|
||||
- added (GB/Game Gear/NES/GEN/SNES) -ggd decode Game Genie code<br>
|
||||
- added (LYNX) -lyx convert to LYX/RAW (strip 64 Bytes LNX header)<br>
|
||||
- added (LYNX) -lnx convert to LNX (uses default values for the header)<br>
|
||||
- added (LYNX) -n change ROM name (LNX only); --file=NEWNAME<br>
|
||||
- added (LYNX) -nrot set no rotation (LNX only)<br>
|
||||
- added (LYNX) -rotl set rotation left (LNX only)<br>
|
||||
- added (LYNX) -rotr set rotation right (LNX only)<br>
|
||||
- added (LYNX) -b0 change Bank0 kBytes size (LNX only); --file={0,64,128,256,512}<br>
|
||||
- added (LYNX) -b1 change Bank1 kBytes size (LNX only); --file={0,64,128,256,512}<br>
|
||||
- added -idppf change PPF FILE_ID.DIZ (2.0); --rom=PATCHFILE --file=FILE_ID.DIZ<br>
|
||||
- added -strip strip Bytes from end of ROM; --file=VALUE<br>
|
||||
- added -e emulate/run ROM (check INSTALL and $HOME/.ucon64rc for more)<br>
|
||||
- added (GBA) -sram patch ROM for SRAM saving<br>
|
||||
- added (GBA) -crp slow down Flash Advance Linker access for ROM (crash patch)<br>
|
||||
- added (GBA) -strip strip Bytes from end of ROM (use -ispad before); --file=VALUE<br>
|
||||
- added (GBA) -xfal send/receive to/from Flash Advance Linker; --file=PORT<br>
|
||||
<p>
|
||||
<a name="196">1.9.6</a><br>
|
||||
- this release brings you full support for the Super Wild Card<br>
|
||||
- added (SNES) -xswc send/receive to/from Super Wild Card*/(all)SWC; --file=PORT
|
||||
(by dbjh)<br>
|
||||
- added (SNES) -xswcs send/receive SRAM to/from Super Wild Card*/(all)SWC;
|
||||
--file=PORT (by dbjh)<br>
|
||||
- added (GB) -sgb convert from GB Xchanger/GB/GBC to Super Backup Card/GX/GBX
|
||||
(by NoisyB)<br>
|
||||
- added (GB) -gbx convert from Super Backup Card/GX/GBX to GB Xchanger/GB/GBC
|
||||
(by NoisyB)<br>
|
||||
- made a few small bug fixes and code cleanups (by NoisyB; thanks to dbjh)<br>
|
||||
- DOS port of uCON64 available (by dbjh)<br>
|
||||
- BeOS port of uCON64 available (by dbjh)<br>
|
||||
- added wildcard support to -find find string in ROM (by NoisyB)<br>
|
||||
- added (SNES) some new NTSC/PAL and SlowROM fix codes (by NoisyB)<br>
|
||||
- added (SNES) -swcs convert emulator *.srm to Super Wild Card*/(all)SWC (by
|
||||
NoisyB)<br>
|
||||
<p>
|
||||
<a name="197">1.9.7</a><br>
|
||||
- added (NES) -fdsl list Famicom Disk System/FDS (diskimage) contents (by
|
||||
NoisyB)<br>
|
||||
- updated (GBA) -xfal send/receive ROM to/from Flash Advance Linker; --file=PORT
|
||||
(by dbjh)<br>
|
||||
- added (GBA) -xfalc<n> specify chip size in Mbits of ROM in Flash
|
||||
Advance Linker when receiving (by dbjh)<br>
|
||||
- added (GBA) -xfalm use SPP mode, default is EPP (by dbjh)<br>
|
||||
- added (Neo Geo) -bios convert NeoCD Bios to work with NeoCD emulator (by
|
||||
NoisyB; thanks to Caz)<br>
|
||||
- changed the whole internal ROM database code (by NoisyB)<br>
|
||||
- added -dbs search ROM database (all entries) by CRC32; --rom=0xCRC32 (by
|
||||
NoisyB)<br>
|
||||
- added (Virtual Boy) show info (by NoisyB)<br>
|
||||
- added (WonderSwan) show info (by NoisyB)<br>
|
||||
- added (ColecoVision) show info (by NoisyB)<br>
|
||||
- added (Vectrex) show info (by NoisyB)<br>
|
||||
- added ROMs to database for Virtual Boy, WonderSwan, ColecoVision and Vectrex
|
||||
(by NoisyB)<br>
|
||||
- added (Intellivision) show info (by NoisyB)<br>
|
||||
- made the internal ROM Database optional; compiled without DB uCON64 will be
|
||||
only ~250kB in size! (by NoisyB)<br>
|
||||
- updated (all) fixed -cs (file compare) (by dbjh)<br>
|
||||
- updated (SNES) fixed dumping of `special' SNES cartridges (for the meaning of
|
||||
special, see src/backup/swc.c) (by dbjh; thanks to Caz)<br>
|
||||
- updated (SNES) fixed -k (crack) (by dbjh)<br>
|
||||
- updated (SNES) fixed -f (NTSC/PAL fix) (by dbjh)<br>
|
||||
- uCON64 will recognize *ANY* kind of ROM or Console System via DB now...<br>
|
||||
give it a Atari2600 ROM and it will just recognize it :) (by NoisyB)<br>
|
||||
- updated the internal DB; it can recognize 12387 different ROMs (by NoisyB)<br>
|
||||
- updated (SNES) fixed -s (split ROM) (by dbjh)<br>
|
||||
- updated (Genesis) fixed -s (by NoisyB)<br>
|
||||
- updated (all) fixed -swc & -ins (and others) for files with a size a
|
||||
multiple of 32kB (by dbjh)<br>
|
||||
- updated (SNES) fixed -swc when ROM file has a name that already has the
|
||||
extension .swc fixed the same problem for -smc and -fig (by dbjh)<br>
|
||||
- added -lsv like -ls but more verbose; --rom=DIRECTORY (by NoisyB)<br>
|
||||
- updated (SNES) fixed checksum output (by NoisyB)<br>
|
||||
- updated (SNES) fixed -j (join multi files) (by dbjh)<br>
|
||||
- updated (SNES) fixed checksum output for Broadcast Satellaview ROMs (by dbjh;
|
||||
thanks to Cowering)<br>
|
||||
- added (SNES) -figs convert emulator *.srm (SRAM) to *Pro Fighter*/(all)FIG (by
|
||||
dbjh; thanks to Caz)<br>
|
||||
- added (SNES) -ufos convert emulator *.srm (SRAM) to Super UFO (by dbjh; thanks
|
||||
to Caz)<br>
|
||||
- added (SNES) -int, -int2 & -nint force ROM is (not) in interleaved format
|
||||
(2) (by dbjh)<br>
|
||||
- added (SNES) -dint convert ROM to non-interleaved format (by dbjh)<br>
|
||||
- added 2830 new ROMs to internal ROM database (by NoisyB)<br>
|
||||
- added (Genesis) -xsmd send/receive ROM to/from Super Magic Drive/SMD;
|
||||
--file=PORT (by NoisyB)<br>
|
||||
- added (Genesis) -xsmds send/receive SRAM to/from Super Magic Drive/SMD;
|
||||
--file=PORT (by NoisyB)<br>
|
||||
- added support for CD based consoles again; uCON64 now uses cdrdao as burn
|
||||
engine (by NoisyB)<br>
|
||||
- added Dreamcast, PSX (one), PS2, Real3DO, CD-i, CD32 and Saturn support (by
|
||||
NoisyB)<br>
|
||||
- added (Genesis) -smds convert emulator (*.srm) SRAM to Super Magic Drive/SMD
|
||||
(by NoisyB)<br>
|
||||
- added -r2i convert RAW to ISO9660; --rom=RAW_IMAGE (by NoisyB)<br>
|
||||
<p>
|
||||
<a name="198-1">1.9.8-1</a><br>
|
||||
- added more verbose WonderSwan ROM info (by NoisyB; thanks to dox)<br>
|
||||
- updated (GBA) used Jeff Frohwein's Flash Advance Linker code V1.72 (by dbjh)<br>
|
||||
- added (GBA) -xfals send/receive SRAM to/from Flash Advance Linker; --file=PORT
|
||||
(by dbjh)<br>
|
||||
- added (GBA) -xfalb<n> send/receive SRAM to/from Flash Advance Linker
|
||||
bank n; --file=PORT (by dbjh)<br>
|
||||
- removed (GBA) -xfalm (use SPP mode), because it is not needed anymore (by
|
||||
dbjh)<br>
|
||||
- updated (SNES) fixed checksum function for Far East of Eden Zero (J) (by dbjh)<br>
|
||||
- added (GBA) -multi{1,2,3} make multirom for Flash Advance Linker (by dbjh)<br>
|
||||
- updated/added (SNES) Game Doctor ROM file support (-gd3 & -s) (by John
|
||||
Weidman)<br>
|
||||
- updated (all) fixed DOS specific bug in IPS code (by dbjh)<br>
|
||||
- updated (SNES) fixed DOS specific problem for -swc, -fig and -smc (by dbjh)<br>
|
||||
- updated (all) fixed DOS specific bug in -ins code (by dbjh)<br>
|
||||
- introducing config file updates without overwrites of old values for more
|
||||
comfort (by NoisyB)<br>
|
||||
- added (WS/WSC) -chk fix ROM checksum (for WonderSwan(Color)) (by NoisyB;
|
||||
thanks to dox)<br>
|
||||
- updated (SNES) changed -swcs, -figs and -ufos to always create a file of 32.5
|
||||
kB. This solves some problems where SRAM files created with an emulator would
|
||||
not work on a copier (by dbjh; thanks to Caz for investigating the problem and
|
||||
providing a solution)<br>
|
||||
- added -mkcue generate CUE file; --rom=CD_IMAGE --file=TRACK_MODE (by NoisyB)<br>
|
||||
- ported the whole project to FreeBSD (by NoisyB)<br>
|
||||
<!-- beta2 -->
|
||||
- updated (GBA) changed -xfalb<n> to -xfalb <n> (space between
|
||||
option and argument) (by dbjh). Did the same thing for -xfalc<n><br>
|
||||
- updated (GB) changed -xgbxb<n> to -xgbxb <n> (space between
|
||||
option and argument) (by dbjh)<br>
|
||||
- switched internal workflow to getopt() and made numerous cosmetical
|
||||
changes/clean ups (by NoisyB)<br>
|
||||
- added -hdn=BYTES force ROM has backup unit/emulator header with BYTES size (by
|
||||
NoisyB)<br>
|
||||
detects the correct TRACK_MODE of IMAGES w/o *.cue file<br>
|
||||
- added --rrom rename all ROMs in DIR to their internal names; --rom=DIR (by
|
||||
NoisyB)<br>
|
||||
- added --rr83 like --rrom but with 8.3 filenames; --rom=DIR (by NoisyB)<br>
|
||||
- added --stpn=N strip N Bytes from ROM beginning (by NoisyB)<br>
|
||||
- added --insn=N insert N Bytes (0x00) before ROM (by NoisyB)<br>
|
||||
- added --xmccl send/receive BYTES to/from Mad Catz Camera Link (experimental)
|
||||
(by NoisyB)<br>
|
||||
- speed --rrom, --rr83 and --ls have been sped up significantly<br>
|
||||
- updated (N64) added 512 Mb ROM support for transfers to Doctor V64 Junior
|
||||
(by NoisyB; thanks to TenOfTen (tenoften@jahej.com))<br>
|
||||
- updated (SNES) fixed -fig to give the same output as a Super Pro Fighter (by
|
||||
dbjh; thanks to JohnDie for the information)<br>
|
||||
- updated (all) parallel port is only accessed for copier I/O (by dbjh)<br>
|
||||
- added (SNES) -bs & -nbs force ROM is a Broadcast Satellaview dump/regular
|
||||
cartridge dump (by dbjh)<br>
|
||||
- added (NES) -unif convert to UNIF format/UNF {iNES, UNIF}->UNIF (by dbjh)<br>
|
||||
- updated (NES) -ines convert to iNES format {iNES, UNIF, Pasofami}->iNES (by
|
||||
dbjh)<br>
|
||||
- added (NES) -dint convert ROM to non-interleaved format (by dbjh)<br>
|
||||
- added (NES) -pasofami convert to Pasofami format iNES->Pasofami (by dbjh)<br>
|
||||
- updated (NES) ROM information for iNES, UNIF, FFE and Pasofami (by dbjh)<br>
|
||||
- updated (NES) fixed -j so that it converts properly from Pasofami to iNES (by
|
||||
dbjh)<br>
|
||||
- updated (NES) fixed -s so that it converts properly from iNES to Pasofami (by
|
||||
dbjh)<br>
|
||||
- updated (NES) fixed -ineshd (extract iNES header to .hdr file) (by dbjh)<br>
|
||||
- added (NES) -ctrl set controller type for ROM (UNIF only) (by dbjh)<br>
|
||||
- added (NES) -ntsc set TV compatibility to NTSC (UNIF only) (by dbjh)<br>
|
||||
- added (NES) -pal set TV compatibility to PAL (UNIF only) (by dbjh)<br>
|
||||
- added (NES) -bat set battery backup (by dbjh)<br>
|
||||
- added (NES) -nbat set no battery backup (by dbjh)<br>
|
||||
- added (NES) -vram set VRAM override (UNIF only) (by dbjh)<br>
|
||||
- added (NES) -nvram set no VRAM override (UNIF only) (by dbjh)<br>
|
||||
- added (NES) -mirr set mirroring type (by dbjh)<br>
|
||||
- added (NES) -n change internal ROM name (UNIF only) (by dbjh)<br>
|
||||
- added (NES) -mapr=NAME specify board name or mapper number for conversion
|
||||
options (by dbjh)<br>
|
||||
- added (NES) -dumpinfo use dumper info when converting to UNIF (by dbjh)<br>
|
||||
<!-- beta3 -->
|
||||
- updated (NES) UNIF code works also on big endian machines (by dbjh)<br>
|
||||
- updated (GBA) changed meaning of -xfalc. In order to dump N megabits of a
|
||||
cartridge specifying -xfalc=N <filename> is enough (by dbjh)<br>
|
||||
- updated (NES) fixed some minor format conversion problems (by dbjh)<br>
|
||||
- updated (LYNX) fixed some problems with endianess (by dbjh)<br>
|
||||
- added (LYNX) --lynxit send/receive ROM to/from Lynxit interface (by NoisyB)<br>
|
||||
- updated (SNES) fixed checksum function for Momotaro Dentetsu Happy (J) (by
|
||||
dbjh)<br>
|
||||
- updated (SNES) fixed SNES info for Dai Kaiju Monogatari 2 (J) (by dbjh)<br>
|
||||
- updated (SNES) improved SNES chip type info (by dbjh)<br>
|
||||
- added gzip support (by dbjh)<br>
|
||||
- updated (Genesis) fixed several bugs (header is correct after -j/-s, correct
|
||||
behaviour if switch -nbak is active, -smd/-mgd if already in SMD/MGD format,
|
||||
-lsv) (by dbjh)<br>
|
||||
- added --padn=N pad ROM to N Bytes (put Bytes with value 0x00 after end) (by
|
||||
dbjh)<br>
|
||||
<!-- beta4 -->
|
||||
- updated (NES) FDS images are recognized without -fdsl (by dbjh)<br>
|
||||
- added (GBA) -xfalmulti send multiple ROMs to Flash Advance Linker (by dbjh)<br>
|
||||
- updated (GBA) changed -multi so that it takes a size argument (by dbjh)<br>
|
||||
- removed (GBA) -multi{1,2,3}, -multi can be used instead (by dbjh)<br>
|
||||
- some code clean ups (by NoisyB)<br>
|
||||
- added read-only zip support (by dbjh) Note that only the first file inside the
|
||||
zip archive will be looked at. Use -ls{v} to see info about all files in the
|
||||
zip archive<br>
|
||||
- added (SNES) NSRT header support (by dbjh)<br>
|
||||
- updated (SNES) fixed an SWC problem for HiROM games without SRAM (by dbjh)<br>
|
||||
- updated (SNES) -k also cracks Killer Instinct (by dbjh)<br>
|
||||
- updated (SNES) -smc writes a correct SMC header (by dbjh)<br>
|
||||
- added (SNES) -ctrl{2} specify type of controller in port 1/2 for emu when
|
||||
converting (by dbjh)<br>
|
||||
- updated (Genesis) replaced Charles MacDonald's SMD code with our own (by dbjh)<br>
|
||||
- added experimental (PSX/N64) --xdex send/receive BLOCK N to/from DexDrive (by
|
||||
NoisyB)<br>
|
||||
- added 664 new ROMs to the internal database (by NoisyB)<br>
|
||||
- updated (SNES) replaced Cowering's BS detection code with John Weidman's (by
|
||||
dbjh)<br>
|
||||
<!-- beta5 -->
|
||||
- updated (all) fixed two bugs in IPS creation code (by dbjh)<br>
|
||||
- updated (all) -mki generates RLE compressed IPS files (by dbjh)<br>
|
||||
- updated (SNES) fixed split file detection for SWC and FIG dumps (by dbjh)<br>
|
||||
- updated (Genesis) fixed -s for RAW images (by dbjh)<br>
|
||||
- updated (SNES) added crack for Donkey Kong Country, Diddy's Kong Quest &
|
||||
Mega Man X (by dbjh; many thanks to CL of NSRT)<br>
|
||||
- updated (SNES) fixed bug in Game Genie code (by dbjh)<br>
|
||||
- updated (all) fixed subtle bug in function that is used for -k, -f, -l &
|
||||
-crp (by dbjh)<br>
|
||||
- updated (SNES) added crack for BS The Legend of Zelda Remix & Demon's
|
||||
Crest (by dbjh, based on info of John Weidman)<br>
|
||||
<!-- beta6 -->
|
||||
- updated (SNES) added crack for at least the following games: Breath of Fire II,
|
||||
Kirby's Dream Course (many thanks to John Weidman), Lufia II - Rise of the
|
||||
Sinistrals and Earthbound (thanks to CL) (by dbjh)<br>
|
||||
- updated (SNES) crack for Mega Man X should work (better) (by dbjh)<br>
|
||||
- updated (SNES) added NTSC/PAL fix for at least the following games:
|
||||
Final Fight Guy, Gokujyou Parodius, Kirby No Kira Kizzu, Robotrek and
|
||||
Seiken Densetsu 3 (by dbjh)<br>
|
||||
- updated (SNES) added crack for Uniracers/Unirally and NTSC/PAL fix for
|
||||
Seiken Densetsu 2 and Secret of Mana (by dbjh; thanks to John Weidman)<br>
|
||||
- updated (all) fixed problem with reading environment variables under DOS and
|
||||
Windows (by dbjh)<br>
|
||||
- updated (all) environment variables take precedence over configuration file
|
||||
variables (by dbjh)<br>
|
||||
- updated (SNES) fixed some problems with joining GD3 files (by dbjh)<br>
|
||||
- added (SNES) -xgd3 send ROM to Game Doctor SF3(SF6/SF7); --file=PORT
|
||||
(by John Weidman and dbjh)<br>
|
||||
- added (SNES) -dbuh display backup unit header and see if it matches with what
|
||||
uCON64 found while analyzing the ROM data (by dbjh, based on an idea by
|
||||
JohnDie)<br>
|
||||
- removed (SNES) -gdf (fix Game Doctor savegame problems), because -gd3 already
|
||||
provides this functionality (by dbjh)<br>
|
||||
- updated (SNES) fixed some -xgd3 problems, uppercase filenames sent to unit,
|
||||
buffer data correct for all files, transfer file size fixed (by John)<br>
|
||||
- updated (SNES) checksums and deinterleaves for HiROM 24 Mbit Game Doctor
|
||||
format should work (by John)<br>
|
||||
- added (SNES) -xswc2 send ROM to Super Wild Card and enable Real Time Save
|
||||
mode (by dbjh)<br>
|
||||
- updated (SNES) added NTSC/PAL fix for Live-a-Live (by dbjh)<br>
|
||||
- updated (all) added full wildcard support ("ucon64 -fig *.swc"). Don't forget
|
||||
to read the FAQ (by dbjh)<br>
|
||||
- added (all) -q be quiet (don't show ROM info) (by dbjh)<br>
|
||||
- updated (all) uCON64 handles multiple options on the same command line (by
|
||||
dbjh)<br>
|
||||
- added (SNES) --ssize=SIZE specify split part size in Mbit (not for Game
|
||||
Doctor SF3) (by dbjh)<br>
|
||||
<!-- beta 7 -->
|
||||
- updated (SNES) added NTSC/PAL fix for Terranigma (by dbjh; thanks to John)<br>
|
||||
- added (all) full support for all existing DAT files (GoodXXXX, RomCenter)
|
||||
they'll be used to identify (test) or rename your ROMs or any other purpose
|
||||
you might need a ROM manager for (by NoisyB)<br>
|
||||
- updated (SNES) fixed BS ROM detection affecting BS Zootte Mahjong! IVT (by
|
||||
John)<br>
|
||||
- added (all) --lsd to list all ROMs using RomCenter or GoodXXXX DAT files (by
|
||||
NoisyB)<br>
|
||||
- updated (all) improved support for zip files that contain more than one file
|
||||
(by dbjh)<br>
|
||||
- updated (SNES) added NTSC/PAL fix and crack for Mario no Super Picross (by
|
||||
dbjh; thanks to John)<br>
|
||||
- renamed (N64) --sram to --lsram (by NoisyB)<br>
|
||||
- replaced --file with option arguments for the following options: --strip,
|
||||
--find, -c, --cs, --dbs, -b, -i, --mki, -a, --mka, --na, --ppf, --mkppf,
|
||||
--nppf, --idppf, --crp, -n, --bot, --lsram, --usms, --n2, --n2gb, --b0, --b1,
|
||||
--sam, --bios and --dumpinfo (by NoisyB)<br>
|
||||
- updated (PSX) PPF code works correctly and generates correct patches on
|
||||
big-endian machines (by dbjh)<br>
|
||||
- added (patch) --patch option to specify the patch file for APS, IPS, BSL and
|
||||
PPF (by NoisyB)<br>
|
||||
- updated (SNES) added NTSC/PAL fix for Dual Orb 2 (thanks to John), Dr. Mario,
|
||||
Dragon - The Bruce Lee Story (U) and Wolfenstein 3D (U) (by dbjh)<br>
|
||||
- updated (N64) APS code works correctly and generates correct patches on
|
||||
big-endian machines (by dbjh)<br>
|
||||
- added (all) -o specify output directory. Note that now uCON64 by default
|
||||
writes its output files to the current directory (by NoisyB and dbjh)<br>
|
||||
- added (all) --poke=OFF:V change byte at file offset OFF to value V (by dbjh)<br>
|
||||
<!--
|
||||
- tested (Genesis) -xsmd and -xsmds with my "new" Super Magic Drive and they
|
||||
worked as we expected (by NoisyB; thanks to dbjh)<br>
|
||||
Of course we test things... Should be put in a file like testsdone.html ;-) (dbjh)
|
||||
-->
|
||||
- updated (SNES) fixed problem where it was necessary to run uCON64 twice on a
|
||||
ROM with the option -chk, before the checksum was really fixed (by dbjh)<br>
|
||||
- added (all) --rename (by NoisyB and dbjh)<br>
|
||||
- added (all) --scan like: GoodXXXX scan ... (by NoisyB)<br>
|
||||
- added (SNES) uCON64 is able to use an "addendum file" for the options -k
|
||||
(snescopy.txt), -f (snesntsc.txt or snespal.txt) and -l (snesslow.txt). You
|
||||
can add new search patterns to those files if the latest binary doesn't
|
||||
support them yet. See the FAQ for a more elaborate explanation (by dbjh)<br>
|
||||
- added Visual C++ build support (including libdiscmage) (by dbjh)<br>
|
||||
- updated (GBA) fixed a bug that would crash FAL code on compressed files (by
|
||||
dbjh)<br>
|
||||
- (re)added (GBA) -xfalm (try to enable EPP mode). Note that the meaning is
|
||||
reversed. Enabling EPP mode only when this switch is specified makes it
|
||||
possible to use the Windows versions of uCON64 under Windows XP (NT/2000)
|
||||
(by dbjh)<br>
|
||||
- added support for the I/O port driver inpout32.dll to the Windows ports. See
|
||||
the FAQ for more information (by dbjh)<br>
|
||||
- uCON64 can also be compiled with g++; configure with "CC=g++ ./configure"
|
||||
(by dbjh)<br>
|
||||
- updated (SNES) uCON64 uses one maker/publisher list for all SNES games (by
|
||||
dbjh; thanks to FluBBa for the help)<br>
|
||||
- updated (GB & GBA) fixed maker info (by dbjh; thanks to FluBBa for the
|
||||
info)<br>
|
||||
- updated (SNES, GB & GBA) fixed huge mistake in the way the Nintendo
|
||||
publisher list was used (resulting in incorrect maker info) (by dbjh)<br>
|
||||
- updated (SNES) fixed problem with splitting HiROM Game Doctor files smaller
|
||||
than or equal to 8 Mbit (by dbjh)<br>
|
||||
- replaced internal handling/conversion of DiscJuggler and Nero images with
|
||||
included libdiscmage. The recognition of ISO, BIN, CDI and NRG images works
|
||||
in 80% of the cases. Every other function like ripping/converting is still
|
||||
flakey and therefore disabled in this beta release (by NoisyB)<br>
|
||||
<!-- beta 8 -->
|
||||
- updated (all) fixed problems with -rename & -rrom for files without a
|
||||
suffix (by dbjh)<br>
|
||||
- updated (all) links (including symbolic links) are handled correctly for
|
||||
-rename & -rrom (by dbjh)<br>
|
||||
- added support for I/O port driver io.dll to the Windows ports. See the FAQ
|
||||
for more information (by dbjh)<br>
|
||||
- added (SNES) -xfig send/receive ROM to/from Pro Fighter; --file=PORT (by
|
||||
JohnDie and dbjh)<br>
|
||||
- added (SNES) -xfigs send/receive SRAM to/from Pro Fighter; --file=PORT (by
|
||||
JohnDie and dbjh)<br>
|
||||
- added (all) --mkdat=DATFILE create DAT file based on a directory/list of ROMs
|
||||
(by dbjh)<br>
|
||||
- updated (N64) fixed -usms (by dbjh)<br>
|
||||
- updated (all) fixed problem with -rename when output directory is on another
|
||||
file system (M$ speak: drive) (by dbjh)<br>
|
||||
- added MinGW build support (including libdiscmage) (by dbjh)<br>
|
||||
- changed name of two property variables: now configdir is named
|
||||
ucon64_configdir and datdir is named ucon64_datdir (by dbjh)<br>
|
||||
- updated (SNES) changed checksum calculation function so that it is stricter
|
||||
(by dbjh; thanks to Nach)<br>
|
||||
- updated (SNES) added more verbose BS info (by dbjh, based on info of Derrick
|
||||
Sobodash)<br>
|
||||
- updated (GB) fixed -n2gb, -gbx & -sgb (by dbjh)<br>
|
||||
- updated (SNES) replaced -ehi with -erom (force ROM is "Extended") in order to
|
||||
support the two Extended LoROM dumps in the known universe (by dbjh)<br>
|
||||
- updated (SNES) added initial support for Sufami Turbo ROMs (by dbjh; thanks
|
||||
to Nach for some info)<br>
|
||||
- added support for GameCube images to libdiscmage (by NoisyB; thanks to
|
||||
gc-nfo.com)<br>
|
||||
- updated (SNES) improved detection of interleaved ROMs (by dbjh)<br>
|
||||
- updated (SNES) -smc, -swc, -fig, -mgd & -gd3 (if it's a LoROM dump)
|
||||
automatically deinterleave the ROM data if the ROM is detected as interleaved
|
||||
(by dbjh)<br>
|
||||
- updated (SNES) -gd3 can convert Tales of Phantasia and Dai Kaiju Monogatari 2
|
||||
(by dbjh)<br>
|
||||
- updated (SNES) interleaved extended HiROM dumps are handled correctly (by
|
||||
dbjh)<br>
|
||||
- updated (SNES) uCON64 follows the "uCONRST standard" for calculating the
|
||||
"search CRC32" of BS dumps (by dbjh)<br>
|
||||
- updated (all) both the search CRC32 and the "data CRC32" are displayed if
|
||||
they differ (by dbjh)<br>
|
||||
- updated (SNES) applied anomie's GD patch which solved a problem with one-part
|
||||
split files (by dbjh)<br>
|
||||
- updated (SNES) replaced John Weidman's BS detection code with Nach's (by
|
||||
dbjh)<br>
|
||||
- updated (SNES) uCON64 now recognises a complete GoodSNES 0.999.5 set (by
|
||||
JohnDie and dbjh)<br>
|
||||
- added (SNES) -dmirr strip mirrored block from end of ROM (by dbjh)<br>
|
||||
- added (SNES) support for native Super UFO file format (by John and dbjh) Use
|
||||
-ufo to convert a file to Super UFO format, use -s to split the resulting
|
||||
file (required for HiROM games)<br>
|
||||
- updated (SMS) -mgd is recognised again, -smd won't crash uCON64 anymore and
|
||||
-smds calls the SMS function when -sms is specified (by dbjh)<br>
|
||||
- updated (SMS) -sms in no longer required for SMD files, they are
|
||||
automatically detected (by dbjh)<br>
|
||||
- updated (SNES) fixed -b (apply Baseline patch) (by dbjh)<br>
|
||||
- updated (all) added support for non-standard parallel port addresses (by
|
||||
dbjh)<br>
|
||||
- updated (SNES) added crack for Tetris Attack (by dbjh; thanks to CL)<br>
|
||||
<p>
|
||||
<a name="198-2">1.9.8-2</a><br>
|
||||
- updated (SNES) -gd3 produces a more logical format for Daikaijuu Monogatari 2
|
||||
(by dbjh; thanks to Nach for the idea)<br>
|
||||
- updated (SMS) -smd interleaves SMS files (by dbjh; thanks to nori-p for
|
||||
testing and feedback)<br>
|
||||
- updated (GBA) fixed stupid bug introduced in 1.9.8beta8 that caused
|
||||
-xfalmulti to hang (-multi and -xfal still worked) (by dbjh)<br>
|
||||
- updated (SNES) hopefully fixed last problem with splitting GD3 files (by
|
||||
dbjh)<br>
|
||||
- updated (SNES) added crack for Dixie Kong's Double Trouble (by dbjh, based on
|
||||
IPS patch by Black Hole of Infernal Affairs)<br>
|
||||
- files of 0 bytes won't be detected as WonderSwan files anymore (by dbjh)<br>
|
||||
- removed (NES) support for bad FDS DAT files (by dbjh) If you really want to
|
||||
use FDS DAT files created by tools that erroneously include the header in the
|
||||
CRC32 calculation, use the switch -nhd. Someone with a complete FDS
|
||||
collection should create a new DAT file<br>
|
||||
- updated (SNES) fixed crashing on first split file of Tales of Phantasia and
|
||||
Daikaijuu Monogatari 2 (by dbjh)<br>
|
||||
- added (SNES) -xgd6 send ROM to Game Doctor SF6/SF7. This probably solves the
|
||||
problems people are having with -xgd3 (by John)<br>
|
||||
- added (SNES) -xgd6s send/receive SRAM to/from Game Doctor SF6/SF7 (by John)<br>
|
||||
- added (SNES) -xgd3s send SRAM to Game Doctor SF3/SF6/SF7 (by John)<br>
|
||||
- added (Genesis) -multi can create a multi-game file for use on the MD-PRO
|
||||
flash card. The downside: creating a multirom for the FAL doesn't work
|
||||
without -gba anymore (by dbjh; thanks to Enemy and acem77 for testing)<br>
|
||||
- added (Genesis) -f can fix region protections, addendum files are genpal.txt
|
||||
and mdntsc.txt (by dbjh)<br>
|
||||
- added (SNES) -id force -gd3 to produce a unique file name. This switch
|
||||
doesn't show in the help, because it "fails" for 130 dumps of the GoodSNES
|
||||
"0.999.6--" set. 128 IDs are each shared by 2 games, 2 IDs are shared by 3
|
||||
games (by dbjh)<br>
|
||||
- updated (all) the patch generation options (-mka, -mki, -mkppf) use the
|
||||
modified ROM name for the patch to create. They used to use the name of the
|
||||
original ROM (by dbjh)<br>
|
||||
- updated (N64) fixed major bug in APS creation code (by dbjh)<br>
|
||||
- updated (SNES) added NTSC/PAL fix for Magical Pop'n (J) and Metal Warriors
|
||||
(U) (by dbjh)<br>
|
||||
- added (Genesis) recognition of <i>real</i> MGD files (by dbjh; thanks to
|
||||
acem77 for the feedback)<br>
|
||||
- updated (Genesis) -mgd now produces proper MGD files (by dbjh)<br>
|
||||
- added (Genesis) -bin convert to binary format. This option produces files in
|
||||
the format that uCON64 1.9.8-1 produces with the option -mgd (by dbjh)<br>
|
||||
- added (Genesis) -xmd & -xmds send/receive ROM/SRAM to/from MD-PRO flash
|
||||
card programmer (by dbjh and NoisyB with many thanks to timofonic and of
|
||||
course ToToTEK Multi Media for providing us with the necessary information.
|
||||
Special thanks go to Leo of ToToTEK for being very helpful and willing to
|
||||
answer our questions)<br>
|
||||
- added (Genesis) -ssize=SIZE specify split part size in Mbit (by dbjh)<br>
|
||||
- updated (SNES, SMS, PC-Engine & Genesis) -mgd produces correct file names
|
||||
(by dbjh; thanks to acem77 for testing and feedback)<br>
|
||||
- updated (Genesis) -mgd automatically pads files to the right size (by dbjh)<br>
|
||||
- added (PC-Engine) -swap invert/swap bits of all bytes of a file. This
|
||||
effectively converts PC-Engine games between Japan and U.S.A. "mode" (by
|
||||
dbjh; thanks to acem77 for the information)<br>
|
||||
- added (SMS) backup unit header length detection (by dbjh; thanks to acem77
|
||||
for pointing this out) This made a problem with the current SMS DAT file
|
||||
surface: some CRC32 values are the result of including a backup unit header
|
||||
in the calculation. Someone with a complete GoodSMS collection should create
|
||||
a new DAT file<br>
|
||||
- updated (PC-Engine) auto-detection of bit-swapped files (by dbjh; thanks to
|
||||
Cowering for the info)<br>
|
||||
- updated (PC-Engine) -mgd automatically bit-swaps the file if it is detected
|
||||
as being in Japan "mode" (by dbjh)<br>
|
||||
- updated (PC-Engine) -smg automatically bit-swaps the file if it is detected
|
||||
as being in U.S.A. "mode" (by dbjh) I don't know if this correct. Please give
|
||||
feedback<br>
|
||||
- added (GB) -logo restore ROM logo character data (offset: 0x104-0x134)
|
||||
(by NoisyB)<br>
|
||||
<p>
|
||||
<a name="198-3">1.9.8-3</a><br>
|
||||
- added (SNES) -xswc-super option to force 32 Mbit dump (by John Weidman)<br>
|
||||
- updated (SNES) enabled -hi & -nhi for -xswc-super, -xswc (dumping) and
|
||||
-xfig (dumping) (by dbjh)<br>
|
||||
You should explicitly specify the parallel port address when you use -hi or
|
||||
-nhi in combination with one of the mentioned dump options<br>
|
||||
- updated (Genesis) fixed problem with -multi that caused problems with some
|
||||
games when run on the MD-PRO (by dbjh)<br>
|
||||
- updated (SNES, Genesis, PC-Engine, SMS, Game Gear & GB) -mgd now produces
|
||||
correct file names. This time for real! :-) (by dbjh; thanks to acem77 for
|
||||
testing and feedback)<br>
|
||||
- added (SNES) -xswcr send/receive RTS data to/from Super Wild Card*/(all)SWC
|
||||
(by dbjh)<br>
|
||||
- updated (PC-Engine) reversed how -mgd & -smg work. -mgd bit-swaps a file
|
||||
if it is detected as not being bit-swapped ("Japan mode"/"unencrypted"). -smg
|
||||
bit-swaps a file if it is detected as being bit-swapped
|
||||
("U.S.A. mode"/"encypted") (by dbjh; thanks to kyuusaku for the feedback)<br>
|
||||
Note that if you want to play a game with an MGD2 on a PC-Engine that you
|
||||
have to manually bit-swap the file with -swap (or specify -int while
|
||||
converting).<br>
|
||||
- updated (SMS) improved detection of SMS and Game Gear files. In most cases
|
||||
specifying -sms is no longer necessary (by dbjh)<br>
|
||||
- added (SMS) -chk fix checksum (by dbjh)<br>
|
||||
- updated (PC-Engine) it's Magic Super Griffin, not Super Magic Griffin. Thus
|
||||
the option -smg has been renamed to -msg (by dbjh; thanks to kyuusaku for the
|
||||
info)<br>
|
||||
- added (PC-Engine) -xmsg send/receive to/from Magic Super Griffin (by dbjh;
|
||||
thanks to kyuusaku for testing)<br>
|
||||
- added (PC-Engine) -f fix region protection (by dbjh; thanks to kyuusaku for
|
||||
testing)<br>
|
||||
- updated (NES) -ffe writes correct headers for the NES games that actually run
|
||||
on the Super Magic Card (by dbjh; thanks to kyuusaku for the info and
|
||||
testing)<br>
|
||||
- added (NES) -xsmc send to Super Magic Card (by dbjh; thanks to kyuusaku for
|
||||
testing)<br>
|
||||
- added (NES) -xsmcr send/receive RTS data to/from Super Magic Card (by dbjh)<br>
|
||||
- added (all) -pattern=FILE change ROM based on patterns specified in FILE (by
|
||||
dbjh)<br>
|
||||
- added (N64) -swap2 word-swap ROM (1234 <-> 3412) (by dbjh)<br>
|
||||
- added (SNES) -xgd3r & -xgd6r send/receive RTS data to/from Game Doctor
|
||||
SF3/6/7 (by John Weidman) -xgd3r can currently only be used for sending<br>
|
||||
- added (SNES) -gd3s convert emulator *.srm (SRAM) to GD BRAM format (by dbjh)<br>
|
||||
- updated (SNES) added crack for Front Mission - Gun Hazard (by dbjh; many
|
||||
thanks to John) This crack is only necessay when the game is modified, for
|
||||
example by -f.<br>
|
||||
- updated (SNES) added NTSC/PAL fix for Pop'n Twinbee (by dbjh)<br>
|
||||
- updated (SNES, Genesis, PC-Engine & NES) (dumping) functions for FFE
|
||||
copiers and Pro Fighter should work correctly with very fast PCs (by JohnDie)<br>
|
||||
- updated (N64) added work-around for old bug in DJGPP and Solaris. Now -swap,
|
||||
-swap2, -v64 and -z64 work correctly for large files (larger than 8 or 12 MB
|
||||
respectively) when using the DOS or Solaris port of uCON64 (by dbjh)<br>
|
||||
- updated (Genesis) replaced -pal with -region=CODE. Now it should be possible
|
||||
to create multi-game files for the MD-PRO that work on all three console
|
||||
types (by dbjh; many thanks to SamIAm for the info that brought me up the
|
||||
idea)<br>
|
||||
<p>
|
||||
<a name="198-4">1.9.8-4</a><br>
|
||||
- updated (all) fixed 2 bugs in code of -pattern (by dbjh)<br>
|
||||
- added (SNES) -xfigc and -xswcc option to transfer SRAM to/from cartridge in
|
||||
*Pro Fighter* and Super Wild Card copiers (by JohnDie)<br>
|
||||
- added support for Linux/PPC (by dbjh; thanks to Tobias Pflug and Misty De Meo)<br>
|
||||
- updated (SNES, Genesis, PC-Engine & NES) fixed subtle bug in code of FFE
|
||||
dumping routines (by dbjh; thanks to Neill Corlett for pointing this out)<br>
|
||||
- updated (SNES) implemented SRAM size display for Super FX ROMs (by JohnDie)<br>
|
||||
- updated (SMS) fixed bug that caused -chk not to work for uninterleaved files
|
||||
with a header (by dbjh)<br>
|
||||
- added support for Mac OS X (including libdiscmage) (by dbjh; many thanks to
|
||||
Steve Paige for his help)<br>
|
||||
- added (SNES) -xswc-dm=MODE specify SWC dump mode (by dbjh)<br>
|
||||
- removed (SNES) -xswc-super, use -xswc -xswc-dm=1 instead (by dbjh)<br>
|
||||
- updated (all) uCON64 won't accept a parallel port address without using --port
|
||||
anymore (by dbjh)<br>
|
||||
This used to be possible:<br>
|
||||
ucon64 <transfer option> <rom> <parallel port address><br>
|
||||
Now you should use a command like this:<br>
|
||||
ucon64 <transfer option> <rom> --port=<parallel port address><br>
|
||||
Or of course, if uCON64 automatically detects the right port or if you have
|
||||
specified the correct port in the configuration file, a command like this:<br>
|
||||
ucon64 <transfer option> <rom><br>
|
||||
This change removes the requirement of specifying the parallel port address
|
||||
when using additional command line options (switches) like -xfalm or -xswc-dm.
|
||||
It also prevents uCON64 from accessing I/O ports not associated to the
|
||||
parallel port if you specify additional transfer switches while <rom>
|
||||
has a name that starts with a number<br>
|
||||
- updated (SNES, Genesis, PC-Engine, SMS, Game Gear & GB) -mgd produces
|
||||
correct index files (MULTI-GD) (by dbjh)<br>
|
||||
- updated (SNES & Genesis) -s produces an index file if the ROM dump is in
|
||||
MGD format (by dbjh)<br>
|
||||
- added support for ppdev (GNU/Linux-only) (by dbjh)<br>
|
||||
This solves two problems:<br>
|
||||
1.) It's no longer necessary for uCON64 to be setuid root in order to
|
||||
communicate with a backup unit. Just make sure /dev/parport<n> has the
|
||||
right permissions or get yourself added to the correct group<br>
|
||||
2.) Non-standard parallel port addresses do not have to be specified. uCON64
|
||||
still uses the first parallel port by default. It's possible to override that
|
||||
by setting parport_dev in the configuration file or by setting an environment
|
||||
variable<br>
|
||||
Use the configure option --enable-ppdev to enable the code<br>
|
||||
- added (all) -md5 calculate MD5 checksum of ROM (by NoisyB)<br>
|
||||
- added (all) -sha1 calculate SHA-1 checksum of ROM (by NoisyB)<br>
|
||||
- added (GBA) support for the Flash 2 Advance (Ultra); options are -xf2a
|
||||
(transfer ROM data), -xf2ac=N (dump N Mbits), -xf2as (transfer 256 kB of SRAM
|
||||
data) and -xf2ab=BANK (transfer 64 kB of SRAM data to "bank" BANK) (by NoisyB
|
||||
and dbjh, based on source code of Ulrich Hecht and David Voswinkel; many
|
||||
thanks to David Voswinkel for testing the parallel port code)<br>
|
||||
- added (GBA) -xfa2multi=SIZE send multiple ROMs to the F2A. You should not
|
||||
specify a loader file on the command line as a file argument. Specify one in
|
||||
the configuration file or set an environment variable (by dbjh)<br>
|
||||
- added (SNES) -dnsrt restore name, region and checksum from NSRT header and
|
||||
remove it (by dbjh)<br>
|
||||
- updated (SNES) fixed shameful bug that caused -chk and -n not to work
|
||||
correctly for interleaved ROM dumps (by dbjh)<br>
|
||||
- updated (SNES) added/updated code to dump special-chip cartridges. Now it's
|
||||
possible to dump Super FX (2), S-DD1, SA-1 and SPC7110 cartridges, but see the
|
||||
comment in swc.c! (by JohnDie)<br>
|
||||
- updated (SNES) made -xswc-dm active for -xswcc so that SRAM data can be
|
||||
transferred to and from Super FX 2 cartridges (by dbjh)<br>
|
||||
- updated (SNES) renamed -xswc-dm to -xswc-io, because it can also be used for
|
||||
sending an SRAM file (by dbjh)<br>
|
||||
- updated (GBA) made -xfalmulti use gbaloader to be consistent with -xf2amulti.
|
||||
So, don't specify a loader as file argument anymore (by dbjh)<br>
|
||||
<p>
|
||||
<a name="200">2.0.0</a><br> <!-- 1.9.8-5 -->
|
||||
- updated (GBA) fixed F2A USB send code (by dbjh; many thanks to David Gauchard
|
||||
for feedback, testing and sending a patch to fix the problem)<br>
|
||||
- updated (N64) cleaned up Doctor V64 Junior transfer source code (by dbjh;
|
||||
thanks to TenOfTen and GameCopierUser0666 for testing)<br>
|
||||
- updated (SNES) added new SWC "I/O mode" 0x100, dump BIOS (by dbjh)<br>
|
||||
- updated (GB) improved ROM info (by dbjh)<br>
|
||||
- updated (GB) fixed problem with dumping "Rocket Games" cartridges with the
|
||||
Game Boy Xchanger (by dbjh; thanks to Anna Kubisty for reporting the problem
|
||||
and testing, and thanks to Cowering for his help and providing us with the
|
||||
necessary information)<br>
|
||||
- updated (GB) cleaned up Game Boy Xchanger transfer source code (by dbjh; many
|
||||
thanks to Anna Kubisty for testing)<br>
|
||||
- added (DC) --scr scramble 1ST_READ.BIN for selfboot CDs (by NoisyB)<br>
|
||||
- added (DC) --unscr unscramble 1ST_READ.BIN for non-selfboot CDs (by NoisyB)<br>
|
||||
- added (DC) --mkip generate IP.BIN file with default values (by NoisyB)<br>
|
||||
- added (DC) --parse=TEMPLATE parse TEMPLATE file into a IP.BIN (by NoisyB)<br>
|
||||
- updated (SNES) corrected output of -dbuh (by dbjh)<br>
|
||||
- added (GB) --xgbxm try to enable EPP mode (by dbjh)<br>
|
||||
- added (SMS/Game Gear) --xgg & --xggs send/receive ROM/SRAM to/from
|
||||
SMS-PRO/GG-PRO flash card programmer (by dbjh; thanks to timofonic and Leo of
|
||||
ToToTEK Multi Media for providing us with the necessary information, many
|
||||
thanks to Walter van Niftrik for testing)<br>
|
||||
- added (PCE) --xpce send/receive ROM to/from PCE-PRO flash card programmer (by
|
||||
dbjh; thanks to timofonic and Leo of ToToTEK Multi Media for providing us with
|
||||
the necessary information)<br>
|
||||
- added (PCE) --multi create a multi-game file for use on a PCE-PRO flash card
|
||||
(by dbjh)<br>
|
||||
- added (SMS/Game Gear) --multi create a multi-game file for use on an SMS-PRO
|
||||
or GG-PRO flash card (by dbjh; thanks to Walter van Niftrik for his patch and
|
||||
for testing)<br>
|
||||
- added (SMS/Game Gear) --xggb=BANK send/receive SRAM to/from SMS-PRO/GG-PRO
|
||||
BANK (by dbjh; thanks to Walter van Niftrik for the suggestion and testing)<br>
|
||||
- added (Genesis) --xmdb=BANK send/receive SRAM to/from MD-PRO BANK (by dbjh)<br>
|
||||
- added support for I/O port driver DlPortIO to the Windows ports. See the FAQ
|
||||
for more information (by dbjh)<br>
|
||||
- the Windows versions of uCON64 won't crash anymore without a (working) I/O
|
||||
port driver under Windows NT/2000/XP. They display a helpful error message
|
||||
instead (by dbjh)<br>
|
||||
- updated (GBA) improved recognition of GBA files and fixed start address
|
||||
information (by dbjh)<br>
|
||||
- updated (GBA) added support for Linux 2.5 (and later) to F2A USB code (by
|
||||
dbjh; thanks to colle for sending a patch and testing)<br>
|
||||
- added support for OpenBSD (by dbjh; thanks to timofonic for testing)<br>
|
||||
- added (N64) --xcd64, --xcd64b, --xcd64s, --xcd64f, --xcd64e, --xcd64m &
|
||||
--xcd64p transfer ROM/boot emu/SRAM/flash RAM/EEPROM/memory pack data to/from
|
||||
CD64 (by dbjh; thanks to Ryan Underwood for libcd64 and testing)<br>
|
||||
- added (Genesis) support for Mike Pavone's Genesis/Sega CD transfer cable (by
|
||||
dbjh; thanks to Mike Pavone for the information and thanks to timofonic for
|
||||
his PR work ;-)<br>
|
||||
- updated (SNES) -gd3 does not produce 28 Mbit HiROM files anymore, it
|
||||
automatically pads them to 32 Mbit (by dbjh)<br>
|
||||
- added (Genesis) support for Cyan's Megadrive ROM copier (by Cyan Helkaraxe and
|
||||
dbjh; thanks to timofonic for his PR work)<br>
|
||||
- moved and split some files in the codebase and changed the workflow. Adding a
|
||||
new option/function now requires only two changes in the code (by NoisyB)<br>
|
||||
- added --dual show ROM as dualdump (by NoisyB)<br>
|
||||
- added --code show ROM as code (by NoisyB)<br>
|
||||
- added --print show ROM in printable characters (by NoisyB)<br>
|
||||
- added --findi find STRING in ROM and ignore case of alpha bytes (by NoisyB)<br>
|
||||
- added --findr find STRING in ROM but look also for shifted/relative
|
||||
similarities (by NoisyB)<br>
|
||||
- added (NeoGeo Pocket) --xpl send/receive ROM to/from Pocket Linker, --xpli
|
||||
show information about inserted cartridge & --xplm try to enable EPP mode
|
||||
(by Walter van Niftrik)<br>
|
||||
- added (SNES) --multi create a multi-game file for use on a Super Flash flash
|
||||
card (by JohnDie)<br>
|
||||
- added (SNES) --xsf send/receive ROM to/from Super Flash card, --xsfs to
|
||||
send/receive SRAM to/from Super Flash card (by JohnDie)<br>
|
||||
- updated (Genesis) added support for 32 Mbit Intel MD-PRO flash card (by dbjh;
|
||||
thanks to Marc Haisenko for sending a patch and testing)<br>
|
||||
- updated (Genesis) fixed -n and -n2 (-n did what -n2 should do and vice versa)
|
||||
(by dbjh)<br>
|
||||
- added (Genesis) support for splitting and joining binary (Magicom) files (by
|
||||
dbjh; thanks to T. Reid for the information)<br>
|
||||
- updated (NES) fixed -dumpinfo so that the year field is read correctly from
|
||||
the dumper info file if it has more than 2 digits (by dbjh)<br>
|
||||
- updated (SNES) --swcs, --figs, --ufos & --gd3s now also work for backup
|
||||
unit SRAM files, i.e., files with a header (by dbjh)<br>
|
||||
- updated (SNES) fixed a bug that caused several headerless dumps to be detected
|
||||
as SWC RTS or SWC SRAM files (by dbjh; many thanks to Dweezledap for reporting
|
||||
this bug and for testing)<br>
|
||||
- updated (N64) added support for 6105 boot codes to check sum routine (by dbjh)<br>
|
||||
- updated (SNES) fixed some other issues with auto-detection (by dbjh; many
|
||||
thanks to Dweezledap for reporting these problems and for testing)<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
</tt></body></html>
|
||||
@@ -1,590 +0,0 @@
|
||||
<html><head>
|
||||
<link rel="icon" href="images/icon.png" type="image/png">
|
||||
<title>uCON64 - Developers</title></head><body bgcolor="#ffffff"><tt><br>
|
||||
Q1: <a href="#1">Who develops uCON64?</a><br>
|
||||
<br>
|
||||
Q2: <a href="#2">How can I take part?</a><br>
|
||||
<br>
|
||||
Q3: <a href="#3">How do I get the source of uCON64, using CVS as an anonymous user?</a><br>
|
||||
<br>
|
||||
Q4: <a href="#4">How do I connect to the CVS repository as developer with read/write access?</a><br>
|
||||
<br>
|
||||
Q5: <a href="#5">How do I create a patch from the CVS repository?</a><br>
|
||||
<br>
|
||||
Q6: <a href="#6">How is the source of uCON64 organized?</a><br>
|
||||
<br>
|
||||
Q7: <a href="#7">What coding style is preferred?</a><br>
|
||||
<br>
|
||||
<br>
|
||||
<p><!-- <p> instead of <br> to make lynx display a blank line between questions -->
|
||||
<a name="1"><b>Q1</b>: Who develops uCON64?</a><br>
|
||||
<b>A</b>: Written/modified by:<br>
|
||||
1999 - 2004 NoisyB (Dirk) <a href="mailto:noisyb AT gmx.net"><noisyb AT gmx.net></a><br>
|
||||
2001 - 2004 dbjh<br>
|
||||
<br>
|
||||
Additional developers:<br>
|
||||
2002 - 2004 John Weidman <a href="mailto:jweidman AT sonic.net"><jweidman AT sonic.net></a><br>
|
||||
Contributed several SNES-related features like Game Doctor & Super UFO
|
||||
support, the second version of the BS (Broadcast Satellaview) detection code,
|
||||
SNES cracks & NTSC/PAL fixes.<br>
|
||||
<br>
|
||||
2002 - 2004 Jan-Erik Karlsson<br>
|
||||
Maintainer of the Amiga ports.<br>
|
||||
<br>
|
||||
2003 - 2004 JohnDie<br><!-- It's a nick name, no space between John and Die -->
|
||||
Also contributed several SNES-related features like Pro Fighter support and
|
||||
Super Wild Card transfer code improvements.<br>
|
||||
<br>
|
||||
<br>
|
||||
uCON64 uses code (or at least ideas) from:<br>
|
||||
<br>
|
||||
<table>
|
||||
<tr>
|
||||
<td><tt>Chicken & chp</tt></td>
|
||||
<td><a href="mailto:ronaldm AT netcom.com"><tt>ronaldm AT netcom.com</tt></a><tt> (chp)</tt></td>
|
||||
<td><tt>original uCON</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tt>Silo / BlackBag</tt></td>
|
||||
<td></td>
|
||||
<td><tt>APS patcher</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tt>madman</tt></td>
|
||||
<td></td>
|
||||
<td><tt>IPS patcher</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tt>The White Knight / ATX</tt></td><!-- yes, breaking space -->
|
||||
<td></td>
|
||||
<td><tt>BSL patcher</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tt>Icarus / Paradox</tt></td>
|
||||
<td></td>
|
||||
<td><tt>PPF patcher</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tt>WyrmCorp</tt></td>
|
||||
<td><a href="http://wyrmcorp.com" target="_blank"><tt>http://wyrmcorp.com</tt></a></td>
|
||||
<td><tt>Game Genie "codec"</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tt>Marat Fayzullin</tt></td>
|
||||
<td><a href="mailto:fms AT cs.umd.edu"><tt>fms AT cs.umd.edu</tt></a><br>
|
||||
<a href="http://www.komkon.org/fms/" target="_blank">
|
||||
<tt>http://www.komkon.org/fms/</tt></a></td>
|
||||
<td><tt>some Famicom Disk System routines and NESLIST</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tt>Andreas Sterbenz</tt></td>
|
||||
<td><a href="mailto:stan AT sbox.tu-graz.ac.at"><tt>stan AT sbox.tu-graz.ac.at</tt></a></td>
|
||||
<td><tt>N64 checksum algorithm</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tt>Kami</tt></td>
|
||||
<td><a href="mailto:m-kami AT da2.so-net.ne.jp"><tt>m-kami AT da2.so-net.ne.jp</tt></a><br>
|
||||
<a href="http://www.playoffline.com" target="_blank">
|
||||
<tt>http://www.playoffline.com</tt></a></td>
|
||||
<td><tt>NES emulator for Game Boy</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tt>Gilligan / DC-S</tt></td>
|
||||
<td></td>
|
||||
<td><tt>show info for Neogeo Pocket</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tt>LaC</tt></td>
|
||||
<td></td>
|
||||
<td><tt>N64 makesram</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tt>Jeff Frohwein</tt></td>
|
||||
<td><a href="mailto:info AT devrs.com"><tt>info AT devrs.com</tt></a><br>
|
||||
<a href="http://www.devrs.com" target="_blank">
|
||||
<tt>http://www.devrs.com</tt></a></td>
|
||||
<td><tt>Flash Advance Linker transfer code</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tt>Omar Kilani</tt></td>
|
||||
<td><a href="mailto:gbautil AT aurore.net"><tt>gbautil AT aurore.net</tt></a></td>
|
||||
<td><tt>Game Boy Advance SRAM patching and "crash patching" code</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tt>Richard Davies</tt></td>
|
||||
<td><a href="mailto:richard AT debaser.force9.co.uk"><tt>richard AT debaser.force9.co.uk</tt></a><br>
|
||||
<a href="http://www.debaser.force9.co.uk" target="_blank">
|
||||
<tt>http://www.debaser.force9.co.uk</tt></a></td>
|
||||
<td><tt>PSX memory card code</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tt>Caz</tt></td>
|
||||
<td><a href="mailto:turok2 AT currantbun.com"><tt>turok2 AT currantbun.com</tt></a><br>
|
||||
<a href="http://www.infernal.currantbun.com" target="_blank">
|
||||
<tt>http://www.infernal.currantbun.com</tt></a></td>
|
||||
<td><tt>I/O port driver for BeOS, SWC help and Super UFO SRAM header format</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tt>Cowering</tt></td>
|
||||
<td><a href="mailto:hotemu AT hotmail.com"><tt>hotemu AT hotmail.com</tt></a></td>
|
||||
<td><tt>old BS ROM detection, BS checksum, some PC-Engine info & code and more</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tt>Jerremy Koot</tt></td>
|
||||
<td><a href="mailto:jkoot AT snes9x.com"><tt>jkoot AT snes9x.com</tt></a><br>
|
||||
<a href="http://www.snes9x.com" target="_blank">
|
||||
<tt>http://www.snes9x.com</tt></a></td>
|
||||
<td><tt>old interleave detection and old deinterleave code (SNES)</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tt>Gary Henderson</tt></td>
|
||||
<td><a href="mailto:gary AT snes9x.com"><tt>gary AT snes9x.com</tt></a><br>
|
||||
<a href="http://www.snes9x.com" target="_blank">
|
||||
<tt>http://www.snes9x.com</tt></a></td>
|
||||
<td><tt>old interleave detection and old deinterleave code (SNES)</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tt>Evan Teran</tt></td>
|
||||
<td><a href="mailto:emt3734 AT ritvax.isc.rit.edu"><tt>emt3734 AT ritvax.isc.rit.edu</tt></a></td>
|
||||
<td><tt>lib_unif (NES)</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tt>NSRT authors</tt></td>
|
||||
<td><a href="mailto:joecool22us AT yahoo.com"><tt>joecool22us AT yahoo.com</tt></a><br>
|
||||
<a href="http://nsrt.edgeemu.com" target="_blank"><tt>http://nsrt.edgeemu.com</tt></a></td>
|
||||
<td><tt>checksum algorithm for Momotaro Dentetsu Happy, their SNES add-on
|
||||
chip information page, SNES cracks (thanks to CL), third version of
|
||||
BS detection code (thanks to Nach) and general help and ideas</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tt>Gilles Vollant</tt></td>
|
||||
<td><a href="mailto:info AT winimage.com"><tt>info AT winimage.com</tt></a></td>
|
||||
<td><tt>unzip.c & unzip.h</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tt>Tiptonium</tt></td>
|
||||
<td><tt><a href="http://www.tiptonium.com" target="_blank">http://www.tiptonium.com</a></td>
|
||||
<td><tt>donated a Super Magic Drive (SMD)</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tt>FluBBa</tt></td>
|
||||
<td></td><!-- private -->
|
||||
<td><tt>maker (publisher) info for SNES, GB, CGB & GBA</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tt>gc-nfo.com</tt></td>
|
||||
<td></td><!-- private -->
|
||||
<td><tt>GameCube image specs</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tt>ToToTEK Multi Media</tt></td>
|
||||
<td><a href="mailto:rayman AT tototek.com"><tt>rayman AT tototek.com</tt></a><br>
|
||||
<a href="http://www.tototek.com" target="_blank">
|
||||
<tt>http://www.tototek.com</tt></a></td>
|
||||
<td><tt>MD-PRO, SMS-PRO/GG-PRO & PCE-PRO transfer code (Delphi) and help
|
||||
with that code</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tt>timofonic</tt></td>
|
||||
<td></td><!-- private? -->
|
||||
<td><tt>uCON64 PR work ;-)</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tt>Felipe XnaK</tt></td>
|
||||
<td><a href="mailto:felipe AT ComPorts.com"><tt>felipe AT ComPorts.com</tt></a><br>
|
||||
<a href="http://www.classicgaming.com/launchtool" target="_blank">
|
||||
<tt>http://www.classicgaming.com/launchtool</tt></a></td>
|
||||
<td><tt>some info from his Genesis ROM format document</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tt>Ulrich Hecht</tt></td>
|
||||
<td><a href="mailto:uli AT emulinks.de"><tt>uli AT emulinks.de</tt></a><br>
|
||||
<a href="http://www.emulinks.de/software.html" target="_blank">
|
||||
<tt>http://www.emulinks.de/software.html</tt></a></td>
|
||||
<td><tt>F2A (USB) code</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tt>David Voswinkel</tt></td>
|
||||
<td><a href="mailto:d.voswinkel AT netcologne.de"><tt>d.voswinkel AT netcologne.de</tt></a></td>
|
||||
<td><tt>F2A parallel port code</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tt>Ryan Underwood</tt></td>
|
||||
<td></td><!-- private? -->
|
||||
<td><tt>libcd64</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tt>Mike Pavone</tt></td>
|
||||
<td><a href="mailto:mask_of_destiny AT hotmail.com"><tt>mask_of_destiny AT hotmail.com</tt></a><br>
|
||||
<a href="http://www.retrodev.com" target="_blank">
|
||||
<tt>http://www.retrodev.com</tt></a></td>
|
||||
<td><tt>Genesis/Sega CD transfer code</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tt>Cyan Helkaraxe</tt></td>
|
||||
<td><a href="mailto:cyan AT emulationzone.org"><tt>cyan AT emulationzone.org</tt></a><br>
|
||||
<a href="http://www.emulationzone.org/projects/cyan/docs" target="_blank">
|
||||
<tt>http://www.emulationzone.org/projects/cyan/docs</tt></a></td>
|
||||
<td><tt>Cyan's Megadrive ROM copier transfer code</tt></td>
|
||||
</tr>
|
||||
</table><br>
|
||||
and others...<br>
|
||||
<br>
|
||||
<p>
|
||||
<a name="2"><b>Q2</b>: How can I take part?</a><br>
|
||||
<b>A</b>: Install <a href="http://www.cvshome.org" target="_blank">CVS</a> and
|
||||
checkout the latest version from
|
||||
<a href="http://ucon64.sourceforge.net" target="_blank">http://ucon64.sourceforge.net</a>.
|
||||
Then make your changes, email <a href="mailto:noisyb AT gmx.net">noisyb AT gmx.net</a>
|
||||
and you will be named in this file and in the sources of course. Just the
|
||||
typical way of open source development.<br>
|
||||
<br>
|
||||
<p>
|
||||
<a name="3"><b>Q3</b>: How do I get the source of uCON64, using CVS as an
|
||||
anonymous user?</a><br>
|
||||
<b>A</b>: For read-only access you must have CVS installed. First you have to
|
||||
login. To login, type:<br>
|
||||
cvs -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/ucon64 login<br>
|
||||
Then CVS will ask you for a password. Since you are logged in as anonymous
|
||||
you do not have a password, so just press the enter key at the password
|
||||
prompt. To download the uCON64 source, type:<br>
|
||||
cvs -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/ucon64 checkout -PR ucon64<br>
|
||||
The uCON64 source will then be downloaded to the directory ./ucon64.<br>
|
||||
It can be very busy at SourceForge which may result in a message like:<br>
|
||||
cvs [login aborted]: recv() from server cvs.sourceforge.net: EOF<br>
|
||||
or<br>
|
||||
cvs [checkout aborted]: recv() from server cvs.sourceforge.net: EOF<br>
|
||||
If you get that message simply try again.<br>
|
||||
You can speed up the download by using the option -z with a compression level
|
||||
parameter. For example:<br>
|
||||
cvs -z 9 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/ucon64 checkout -PR ucon64<br>
|
||||
If you want to get up to date with the newest source code later, enter the
|
||||
directory ucon64 and type:<br>
|
||||
cvs update -PRd<br>
|
||||
<br>
|
||||
<p>
|
||||
<a name="4"><b>Q4</b>: How do I connect to the CVS repository as developer with
|
||||
read/write access?</a><br>
|
||||
<b>A</b>: For read/write access you must have CVS and SSH installed and set the
|
||||
environment variable CVS_RSH=ssh. To download the source code, type:<br>
|
||||
cvs -z 9 -d:ext:<name>@cvs.sourceforge.net:/cvsroot/ucon64 checkout -PR ucon64<br>
|
||||
<enter password at prompt><br>
|
||||
If you never logged on to cvs.sourceforge.net before you may get a message
|
||||
(from ssh) like:<br>
|
||||
The authenticity of host 'cvs.sourceforge.net (66.35.250.207)' can't be established.<br>
|
||||
DSA key fingerprint is 02:ab:7c:aa:49:ed:0b:a8:50:13:10:c2:3e:92:0f:42.<br>
|
||||
Are you sure you want to continue connecting (yes/no)?<br>
|
||||
Type yes (the whole word). Ssh will respond with a message like:<br>
|
||||
Warning: Permanently added 'cvs.sourceforge.net' (DSA) to the list of known hosts.<br>
|
||||
Now all files will be downloaded. Afterwards you can simply cd into the top
|
||||
level directory and continue by just typing:<br>
|
||||
cvs update -PRd<br>
|
||||
cvs commit -R<br>
|
||||
cvs add <file><br>
|
||||
cvs remove -f <file><br>
|
||||
You don't need to specify
|
||||
-d:ext:<name>@cvs.sourceforge.net:/cvsroot/ucon64 anymore, because
|
||||
that information is stored in the CVS directories then.<br>
|
||||
If you use the update command in combination with (-)d, never forget to also
|
||||
use the option -P or you will get a lot of crap.<br>
|
||||
<br>
|
||||
<p>
|
||||
<a name="5"><b>Q5</b>: How do I create a patch from the CVS repository?</a><br>
|
||||
<b>A</b>: As developer:<br>
|
||||
cvs -d:ext:<name>@cvs.sourceforge.net:/cvsroot/ucon64 diff -u >mychanges.patch<br>
|
||||
<enter password at prompt><br>
|
||||
As anonymous:<br>
|
||||
cvs -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/ucon64 login<br>
|
||||
<just press enter at password prompt><br>
|
||||
cvs -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/ucon64 diff -u >mychanges.patch<br>
|
||||
<br>
|
||||
<p>
|
||||
<a name="6"><b>Q6</b>: How is the source of uCON64 organized?</a><br>
|
||||
<b>A</b>: The heart of uCON64 is ucon64.h/st_ucon64_t. This <i>struct</i> is
|
||||
designed to hold all workflow relevant informations and it has pointers
|
||||
to different structs which will be != NULL depending on which type or
|
||||
format uCON64 did detect for the current ROM. libdiscmage (if compiled)
|
||||
is involved in this process as well.<br><br>
|
||||
uCON64 starts with the name of a ROM and possibly some arguments. Then it
|
||||
checks if a configuration file exists and creates one if that is not the
|
||||
case. For example the value of
|
||||
ucon64.parport, the variable that contains the I/O address of the parallel
|
||||
port, will initially be set to the value that is found in the configuration
|
||||
file.<br>
|
||||
After these initial functions every ROM will be processed.<br><br>
|
||||
Processing a ROM.<br>
|
||||
The command line will be scanned for switches. Switches are command line
|
||||
arguments that will not result in an action by themselves, but they
|
||||
influence the other type of command line arguments, options. <br>
|
||||
uCON64 sets some other values in ucon64.h/st_ucon64_t, based on the
|
||||
switches. This code can be found in ucon64_opts.c/ucon64_switches().
|
||||
This is also the place where ucon64.c/ucon64.quiet is set. This variable
|
||||
determines whether or not uCON64 displays ROM information.<br>
|
||||
Then uCON64 starts scanning the command line for options. This code can be
|
||||
found in ucon64_opts.c/ucon64_options(). From this code almost all
|
||||
operations of uCON64 are executed. Under Unix this is also the point where
|
||||
root privileges are given up with a call to misc.c/drop_privileges().<br>
|
||||
First uCON64 tries to find out what console system the ROM belongs to using
|
||||
for example the init function for SNES (console/snes.c/snes_init() or
|
||||
console/nes.c/nes_init() for NES). Each init function tries to determine if the
|
||||
ROM file belongs to its console type. If that is the case it returns 0,
|
||||
otherwise -1.<br>
|
||||
Some ROM file types contain information such as the internal name, country
|
||||
and creator of the game that can be used to fill ucon64.c/main()/rom. SNES
|
||||
ROM files are an example of this type of file. For other ROM file types this
|
||||
information is not present inside the ROM file. NES ROMs are an example of
|
||||
that type. In that case uCON64 uses the DAT files in the data file
|
||||
directory. That makes it possible to display the full name of the game.
|
||||
ucon64.c/ucon64_rom_handling() calls the function
|
||||
ucon64_dat.c/ucon64_dat_search() that uses the CRC32 of the ROM file data to
|
||||
find the required information in the DAT files. If the information could be
|
||||
found ucon64_dat.c/ucon64_dat_search() fills ucon64.c/ucon64.dat with it.
|
||||
ucon64.c/ucon64_rom_handling() copies the name to ucon64.rominfo->name.<br>
|
||||
After that if ucon64.c/ucon64.quiet has a value smaller than 1 uCON64 will
|
||||
call ucon64.c/ucon64_nfo() which displays the values and strings of ucon64.
|
||||
For some options it doesn't make sense to display ROM info. If one of those
|
||||
options has been specified on the command line
|
||||
(ucon64.c/ucon64.flags & WF_NFO) will be zero.<br>
|
||||
After all this the option will be executed (ucon64_opts.c/ucon64_options()).<br>
|
||||
<br>
|
||||
<p>
|
||||
<a name="7"><b>Q7</b>: What coding style is preferred?</a><br>
|
||||
<b>A</b>:<br>
|
||||
<br>
|
||||
<b>Keywords</b><br>
|
||||
Always put a space after a keyword. That includes the keyword <i>sizeof</i>.<br>
|
||||
<br>
|
||||
<b>Indentation</b><br>
|
||||
Two spaces instead of a real tab. The curly braces of functions should not
|
||||
be indented.<br>
|
||||
If an <i>if</i> statement has an <i>else</i> part, that part should be
|
||||
aligned with the <i>if</i> part. For a <i>do-while</i> compound statement,
|
||||
<i>do</i> and <i>while</i> should also be aligned.<br>
|
||||
If <i>else</i> is immediately followed by an <i>if</i> statement, the
|
||||
<i>if</i> keyword together with the condition statement should be put on the
|
||||
same line as the <i>else</i> keyword. Example: <br>
|
||||
<pre>
|
||||
if (...)
|
||||
{
|
||||
...
|
||||
}
|
||||
else if (...)
|
||||
{
|
||||
...
|
||||
}
|
||||
else
|
||||
{
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
Note that this doesn't apply to the case where <i>else</i> is followed by a
|
||||
curly brace.<br>
|
||||
<br>
|
||||
<b>New lines</b><br>
|
||||
The statement(s) for <i>if</i>, <i>while</i> and <i>for</i> should always
|
||||
start on a new line. That also applies to one-line statements.<br>
|
||||
<br>
|
||||
<b>Compound statements</b><br>
|
||||
The curly braces should be indented and the code of the compound statement
|
||||
should be indented again. The only exception is the <i>switch</i> statement.
|
||||
The labels inside a <i>switch</i> statement should be aligned with the curly
|
||||
braces. Example:<br>
|
||||
<pre>
|
||||
int
|
||||
function (int value)
|
||||
{
|
||||
if (value < 0)
|
||||
{
|
||||
printf ("Invalid argument: %d\n", value);
|
||||
exit (1);
|
||||
}
|
||||
switch (value)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
case 2: // falling through
|
||||
puts ("lesser than or equal to 2\n");
|
||||
case 3:
|
||||
case 4:
|
||||
puts ("lesser than or equal to 4\n");
|
||||
break;
|
||||
default:
|
||||
puts ("greater than 4\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
A <i>do-while</i> compound statement should have this layout:<br>
|
||||
<pre>
|
||||
do
|
||||
{
|
||||
...
|
||||
}
|
||||
while (...);
|
||||
</pre>
|
||||
<br>
|
||||
<b>Functions</b><br>
|
||||
Function calls should contain one space after the name of the function.
|
||||
Every parameter of the function should be separated from a previous one with
|
||||
a space after the comma.<br>
|
||||
For a function implementation the return type should be specified on its own
|
||||
line. This doesn't apply to function prototypes. If a function needn't be
|
||||
known at global scope it should be declared or defined as <i>static</i>.
|
||||
Function implementations should be separated from each other by two new
|
||||
lines.<br>
|
||||
<br>
|
||||
<b>Variables</b><br>
|
||||
Variables of the same type should be defined in one group. Example:<br>
|
||||
<pre>
|
||||
int x, y = 0, z;
|
||||
char str1[] = "xyz", *str2;
|
||||
</pre>
|
||||
Variables that need to be known at file scope but not at global scope should
|
||||
be defined as <i>static</i>. Variables that do need to be known at global
|
||||
scope should be defined in a source file, not in a header file. The header
|
||||
file should contain an <i>extern</i> statement for the variable.<br>
|
||||
<br>
|
||||
<b>Types (<i>struct</i>s)</b><br>
|
||||
A <i>struct</i> tag of a <i>struct</i> should have the prefix "st_". A new
|
||||
type based on a <i>struct</i> should have the same prefix and the suffix
|
||||
"_t". Example:<br>
|
||||
<pre>
|
||||
typedef struct st_unif_chunk
|
||||
{
|
||||
unsigned long id;
|
||||
unsigned long length;
|
||||
void *data;
|
||||
} st_unif_chunk_t;
|
||||
</pre>
|
||||
<br>
|
||||
<b>Line length</b><br>
|
||||
The length of lines shouldn't be much longer than 90 characters. This
|
||||
doesn't necessarily include the length of comment. Longer lines should be
|
||||
broken into several shorter ones. Example:<br>
|
||||
<pre>
|
||||
static const int unif_prg_ids[] = {PRG0_ID, PRG1_ID, PRG2_ID, PRG3_ID,
|
||||
PRG4_ID, PRG5_ID, PRG6_ID, PRG7_ID,
|
||||
PRG8_ID, PRG9_ID, PRGA_ID, PRGB_ID,
|
||||
PRGC_ID, PRGD_ID, PRGE_ID, PRGF_ID};
|
||||
</pre>
|
||||
<br>
|
||||
<b>Comment</b><br>
|
||||
Single or two-line comments should use //. Comments that need more lines
|
||||
should use the pair /* and */. A two-line comment should signify that it is
|
||||
one two-line comment instead of two one-line comments by putting one extra
|
||||
space after the //. Single or two-line comments should start at column 49 if
|
||||
that's possible. Example:<br>
|
||||
<pre>
|
||||
char buf[SIZE_INFO], number[80]; // 4 should be enough, but don't
|
||||
// be too sensitive to errors
|
||||
</pre>
|
||||
Long comments should use the same indentation as the code that follows it:<br>
|
||||
<pre>
|
||||
if (deinterleave)
|
||||
/*
|
||||
This is a bit of a hack, i.e., putting the following code in this
|
||||
...
|
||||
*/
|
||||
{
|
||||
unsigned char *data;
|
||||
int size, n = 0, prg = 0, chr = 0;
|
||||
...
|
||||
</pre>
|
||||
<br>
|
||||
<b>Preprocessor directives</b><br>
|
||||
Preprocessor directives should not be indented. This does not only apply to
|
||||
#include, but to all preprocessor directives.<br>
|
||||
For #if and #ifdef blocks that are complex or enclose many lines of code the
|
||||
corresponding #else, #elif or #endif should contain a comment that signifies
|
||||
to which #if or #ifdef it belongs. <a name="multiplatform">Example:</a><br>
|
||||
<pre>
|
||||
#ifdef __unix__ // wait 32 milliseconds
|
||||
usleep (32000);
|
||||
...
|
||||
#elif defined __MSDOS__ // __unix__
|
||||
delay (32);
|
||||
...
|
||||
#elif defined __BEOS__ // __MSDOS__
|
||||
snooze (32000);
|
||||
...
|
||||
#endif // __BEOS__
|
||||
</pre>
|
||||
Standard system header files should be included by specifying the name of
|
||||
the header file between angle brackets. Non-standard header files should be
|
||||
included with the name between double quotes. Example:<br>
|
||||
<pre>
|
||||
#include <stdio.h>
|
||||
#ifdef __unix__
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include "ucon64.h"
|
||||
</pre>
|
||||
<br>
|
||||
<b>Header files</b><br>
|
||||
Header files should be protected against being included multiple times by
|
||||
putting the entire file inside an #ifndef block. Define the constant for
|
||||
which the #ifndef checks inside the #ifndef block. For example, for the file
|
||||
swc.h:<br>
|
||||
<pre>
|
||||
#ifndef SWC_H
|
||||
#define SWC_H
|
||||
...
|
||||
#endif // SWC_H
|
||||
</pre>
|
||||
Header files should only contain information about their corresponding
|
||||
source file that may be needed by other source files. They should not
|
||||
include information about variables or function definitions that are used
|
||||
only inside the source file.<br>
|
||||
<br>
|
||||
<b>Portability</b><br>
|
||||
Platform-specific function calls, variable types and #includes of header
|
||||
files should be put inside #ifdef or #if blocks. For an example see the
|
||||
<a href="#multiplatform">first code example</a> in the section Preprocessor
|
||||
directives.<br>
|
||||
<br>
|
||||
<p>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br></tt></body></html>
|
||||
@@ -1,210 +0,0 @@
|
||||
<html><head>
|
||||
<link rel="icon" href="images/icon.png" type="image/png">
|
||||
<title>uCON64 - Hardware</title></head><body bgcolor="#ffffff"><tt>
|
||||
The following backup units are currently supported by <img src="images/logo.png" height="50"><br>
|
||||
<br>
|
||||
If your backup unit is NOT supported yet, you might find what you need at <a href="http://mfm.subport.org" target="_blank">http://mfm.subport.org</a><br>
|
||||
For more information about backup units check <a href="http://www.robwebb.clara.co.uk/backup/" target="_blank">http://www.robwebb.clara.co.uk/backup/</a><br>
|
||||
|
||||
<tt><br>
|
||||
<br>
|
||||
<center>
|
||||
<table width="640">
|
||||
<tr>
|
||||
<td><tt>
|
||||
<img src="images/swc.png"><br>
|
||||
Super Wild Card 1.6XC/Super Wild Card 2.8CC/Super Wild Card DX(2)/SWC<br>
|
||||
19XX Front Far East/FFE <a href="http://www.front.com.tw">http://www.front.com.tw</a><br>
|
||||
(uCON64 options: --xswc, --xswc2, --xswcs, --xswcr, --xswcc, -xswc-io)<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<img src="images/fig.png"><br>
|
||||
Super Pro Fighter (Q/Q+)/Pro Fighter X (Turbo 2)/Double Pro Fighter (X Turbo)<br>
|
||||
19XX China Coach Limited/CCL <a href="http://www.ccltw.com.tw">http://www.ccltw.com.tw</a><br>
|
||||
(uCON64 options: --xfig, --xfigs, --xfigc)<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<img src="images/sf3.png"><br>
|
||||
Game Doctor SF3(SF6/SF7)/Professor SF(SF II)<br>
|
||||
19XX Bung Enterprises Ltd <a href="http://www.bung.com.hk">http://www.bung.com.hk</a><br>
|
||||
(uCON64 options: --xgd3, --xgd6, --xgd3s, --xgd6s, --xgd3r, --xgd6r)<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<img src="images/smd.png"><br>
|
||||
Super Com Pro (HK)/Super Magic Drive/SMD<br>
|
||||
19XX Front Far East/FFE <a href="http://www.front.com.tw">http://www.front.com.tw</a><br>
|
||||
(uCON64 options: --xsmd, --xsmds)<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<img src="images/smc.png"><br>
|
||||
Super Magic Card<br>
|
||||
19XX Front Far East/FFE <a href="http://www.front.com.tw">http://www.front.com.tw</a><br>
|
||||
(uCON64 options: --xsmc, --xsmcr)<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<img src="images/msg.png"><br>
|
||||
Magic Super Griffin/MSG<br>
|
||||
19XX Front Far East/FFE <a href="http://www.front.com.tw">http://www.front.com.tw</a><br>
|
||||
(uCON64 option: --xmsg)<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<img src="images/v64.png"><br>
|
||||
Doctor V64<br>
|
||||
19XX Bung Enterprises Ltd <a href="http://www.bung.com.hk">http://www.bung.com.hk</a><br>
|
||||
(uCON64 option: --xv64)<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<img src="images/v64jr.png"><br>
|
||||
Doctor V64 Junior<br>
|
||||
19XX Bung Enterprises Ltd <a href="http://www.bung.com.hk">http://www.bung.com.hk</a><br>
|
||||
(uCON64 option: --xdjr)<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<img src="images/dexdrive.png"><br>
|
||||
DexDrive (PSX and Nintendo 64 SRAMs)<br>
|
||||
19XX InterAct <a href="http://www.dexdrive.de">http://www.dexdrive.de</a><br>
|
||||
(uCON64 option: --xdex)<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
</td>
|
||||
<td><tt>
|
||||
<img src="images/gbx.png"><br>
|
||||
Game Boy Xchanger<br>
|
||||
19XX Bung Enterprises Ltd <a href="http://www.bung.com.hk">http://www.bung.com.hk</a><br>
|
||||
(uCON64 options: --xgbx, --xgbxs, --xgbxb, --xgbxm)<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<img src="images/cameralink.png"><br>
|
||||
Mad Catz Camera Link (Game Boy Camera)<br>
|
||||
XXXX Mad Catz Inc. <a href="http://www.madcatz.com">http://www.madcatz.com</a><br>
|
||||
(uCON64 option: --xmccl)<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<img src="images/fal.png"><br>
|
||||
Flash Advance Linker<br>
|
||||
2001 Visoly <a href="http://www.visoly.com">http://www.visoly.com</a><br>
|
||||
(uCON64 options: --xfal, --xfalmulti, --xfalc, --xfals, --xfalb, --xfalm)<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<img src="images/f2a.png"><br>
|
||||
Flash 2 Advance (Ultra)<br>
|
||||
2003 Flash2Advance <a href="http://www.flash2advance.com">http://www.flash2advance.com</a><br>
|
||||
(uCON64 options: --xf2a, --xf2amulti, --xf2ac, --xf2as, --xf2ab)<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
Lynxit (Lynx cartridge backup board)<br>
|
||||
1997 K. Wilkins (custom selfmade)<br>
|
||||
(uCON64 option: --xlit)<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<img src="images/cd_rw.png" height="50"><br>
|
||||
(uCON64 options: --mksheet, --cdirip, and --nrgrip)<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<img src="images/mdpro.png"><br>
|
||||
MD-PRO flash card programmer<br>
|
||||
200X ToToTEK <a href="http://www.tototek.com">http://www.tototek.com</a><br>
|
||||
(uCON64 options: --xmd, --xmds)<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<img src="images/pcepro.png"><br>
|
||||
PCE-PRO flash card programmer<br>
|
||||
200X ToToTEK <a href="http://www.tototek.com">http://www.tototek.com</a><br>
|
||||
(uCON64 option: --xpce)<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<img src="images/smspro.png"><br>
|
||||
SMS-PRO flash card programmer<br>
|
||||
200X ToToTEK <a href="http://www.tototek.com">http://www.tototek.com</a><br>
|
||||
(uCON64 options: --xgg, --xggs)<br><!-- yes, the same as for the GG-PRO -->
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<img src="images/ggpro.png"><br>
|
||||
GG-PRO flash card programmer<br>
|
||||
200X ToToTEK <a href="http://www.tototek.com">http://www.tototek.com</a><br>
|
||||
(uCON64 options: --xgg, --xggs)<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<!--img src="images/"><br-->
|
||||
Cyan's Megadrive Copier<br>
|
||||
1999-2004 Cyan Helkaraxe<br>
|
||||
(uCON64 options: --xcmc, --xcmct, --xcmcm)<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<!--img src="images/"><br-->
|
||||
Mike Pavone's Genesis/Sega CD transfer cable<br>
|
||||
200X Mike Pavone<br>
|
||||
(uCON64 options: --xmcd)<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
</tt></body></html>
|
||||
|
Before Width: | Height: | Size: 9.6 KiB |
|
Before Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 161 B |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 75 KiB |
|
Before Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 87 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 9.6 KiB |
@@ -1,5 +0,0 @@
|
||||
<html><head>
|
||||
<link rel="icon" href="images/icon.png" type="image/png">
|
||||
<title>uCON64 - Install</title></head><body bgcolor="#ffffff"><tt>
|
||||
What you expect here can be found in <a href="faq.html">faq.html</a>
|
||||
</tt></body></html>
|
||||
@@ -1,372 +0,0 @@
|
||||
--- parallel.c 2004-09-02 19:09:23.000000000 +0200
|
||||
+++ parallel.c.libieee1284 2004-09-04 03:07:38.000000000 +0200
|
||||
@@ -25,6 +25,11 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
+#define USE_LIBIEEE1284
|
||||
+#if defined USE_LIBIEEE1284 && defined USE_PPDEV
|
||||
+#undef USE_PPDEV
|
||||
+#endif
|
||||
+
|
||||
#ifdef USE_PARALLEL
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -40,7 +45,9 @@
|
||||
#include <sys/time.h>
|
||||
#include <linux/ppdev.h>
|
||||
#include <linux/parport.h>
|
||||
-#elif defined __linux__ && defined __GLIBC__ // USE_PPDEV
|
||||
+#elif defined USE_LIBIEEE1284 // USE_PPDEV
|
||||
+#include <ieee1284.h>
|
||||
+#elif defined __linux__ && defined __GLIBC__ // USE_LIBIEEE1284
|
||||
#ifdef HAVE_SYS_IO_H // necessary for some Linux/PPC configs
|
||||
#include <sys/io.h> // ioperm() (glibc), in{b, w}(), out{b, w}()
|
||||
#else
|
||||
@@ -78,8 +85,12 @@
|
||||
#include "getopt2.h"
|
||||
#include "ucon64.h"
|
||||
|
||||
+#if defined USE_LIBIEEE1284 && defined USE_PPDEV
|
||||
+#undef USE_PPDEV
|
||||
+#endif
|
||||
+
|
||||
|
||||
-#if defined USE_PPDEV || defined __BEOS__ || defined __FreeBSD__ || defined AMIGA
|
||||
+#if defined USE_PPDEV || defined __BEOS__ || defined __FreeBSD__ || defined AMIGA || defined USE_LIBIEEE1284
|
||||
static void close_io_port (void);
|
||||
#endif
|
||||
#if defined __i386__ || defined __x86_64__ // GCC && x86
|
||||
@@ -92,8 +103,12 @@
|
||||
|
||||
#if defined USE_PPDEV || defined __BEOS__ || defined __FreeBSD__
|
||||
static int parport_io_fd;
|
||||
-#ifdef USE_PPDEV
|
||||
+#endif
|
||||
+#if defined USE_PPDEV || defined USE_LIBIEEE1284
|
||||
static enum { FORWARD = 0, REVERSE } parport_io_direction;
|
||||
+#ifdef USE_LIBIEEE1284
|
||||
+struct parport *libieee1284_port;
|
||||
+#else
|
||||
static int parport_io_mode;
|
||||
#endif
|
||||
#endif
|
||||
@@ -113,7 +128,7 @@
|
||||
#endif
|
||||
|
||||
|
||||
-#if defined _WIN32 || defined __CYGWIN__
|
||||
+#if (defined _WIN32 || defined __CYGWIN__) && !defined USE_LIBIEEE1284
|
||||
|
||||
#define NODRIVER_MSG "ERROR: No (working) I/O port driver. Please see the FAQ, question 4\n"
|
||||
|
||||
@@ -172,7 +187,7 @@
|
||||
static void (*output_word) (unsigned short, unsigned short) = outpw_func;
|
||||
|
||||
#endif
|
||||
-#endif // _WIN32 || __CYGWIN__
|
||||
+#endif // (_WIN32 || __CYGWIN__) && !USE_LIBIEEE1284
|
||||
|
||||
|
||||
#if defined __i386__ || defined __x86_64__ // GCC && x86
|
||||
@@ -275,6 +290,43 @@
|
||||
exit (1);
|
||||
}
|
||||
return byte;
|
||||
+#elif defined USE_LIBIEEE1284
|
||||
+ int ppreg = port - ucon64.parport;
|
||||
+ unsigned char byte;
|
||||
+
|
||||
+ switch (ppreg)
|
||||
+ {
|
||||
+ case 0: // data
|
||||
+ if (parport_io_direction == FORWARD) // dir is forward?
|
||||
+ {
|
||||
+ parport_io_direction = REVERSE; // change it to reverse
|
||||
+ ieee1284_data_dir (libieee1284_port, parport_io_direction);
|
||||
+ }
|
||||
+ byte = (unsigned char) ieee1284_read_data (libieee1284_port);
|
||||
+ break;
|
||||
+ case 1: // status
|
||||
+ byte = (unsigned char) (ieee1284_read_status (libieee1284_port) ^ S1284_INVERTED);
|
||||
+ break;
|
||||
+ case 2: // control
|
||||
+ byte = (unsigned char) (ieee1284_read_control (libieee1284_port) ^ C1284_INVERTED);
|
||||
+ break;
|
||||
+ case 3: // EPP/ECP address
|
||||
+ ieee1284_epp_read_addr (libieee1284_port, F1284_NONBLOCK, (char *) &byte, 1);
|
||||
+ break;
|
||||
+ case 4: // EPP/ECP data
|
||||
+ ieee1284_epp_read_data (libieee1284_port, F1284_NONBLOCK, (char *) &byte, 1);
|
||||
+ break;
|
||||
+ case 0x402: // ECP register
|
||||
+ printf ("WARNING: Ignored read from ECP register, returning 0\n");
|
||||
+ byte = 0;
|
||||
+ break;
|
||||
+ default:
|
||||
+ fprintf (stderr,
|
||||
+ "ERROR: inportb() tried to read from an unsupported port (0x%x)\n",
|
||||
+ port);
|
||||
+ exit (1);
|
||||
+ }
|
||||
+ return byte;
|
||||
#elif defined __BEOS__
|
||||
st_ioport_t temp;
|
||||
|
||||
@@ -358,6 +410,26 @@
|
||||
exit (1);
|
||||
}
|
||||
return buf[0] | buf[1] << 8; // words are read in little endian format
|
||||
+#elif defined USE_LIBIEEE1284
|
||||
+ int ppreg = port - ucon64.parport;
|
||||
+ unsigned char buf[2];
|
||||
+
|
||||
+ switch (ppreg)
|
||||
+ {
|
||||
+ case 3: // EPP/ECP address
|
||||
+ ieee1284_epp_read_addr (libieee1284_port, F1284_NONBLOCK | F1284_FASTEPP, (char *) buf, 2);
|
||||
+ break;
|
||||
+ case 4: // EPP/ECP data
|
||||
+ ieee1284_epp_read_data (libieee1284_port, F1284_NONBLOCK | F1284_FASTEPP, (char *) buf, 2);
|
||||
+ break;
|
||||
+ // the data, status, control and ECP registers should only be accessed in "8-bit mode"
|
||||
+ default:
|
||||
+ fprintf (stderr,
|
||||
+ "ERROR: inportw() tried to read from an unsupported port (0x%x)\n",
|
||||
+ port);
|
||||
+ exit (1);
|
||||
+ }
|
||||
+ return buf[0] | buf[1] << 8; // words are read in little endian format
|
||||
#elif defined __BEOS__
|
||||
st_ioport_t temp;
|
||||
|
||||
@@ -434,6 +506,37 @@
|
||||
port);
|
||||
exit (1);
|
||||
}
|
||||
+#elif defined USE_LIBIEEE1284
|
||||
+ int ppreg = port - ucon64.parport;
|
||||
+
|
||||
+ switch (ppreg)
|
||||
+ {
|
||||
+ case 0: // data
|
||||
+ if (parport_io_direction == REVERSE) // dir is reverse?
|
||||
+ {
|
||||
+ parport_io_direction = FORWARD; // change it to forward
|
||||
+ ieee1284_data_dir (libieee1284_port, parport_io_direction);
|
||||
+ }
|
||||
+ ieee1284_write_data (libieee1284_port, byte);
|
||||
+ break;
|
||||
+ case 2: // control
|
||||
+ ieee1284_write_control (libieee1284_port, (unsigned char) (byte ^ C1284_INVERTED));
|
||||
+ break;
|
||||
+ case 3: // EPP/ECP address
|
||||
+ ieee1284_epp_write_addr (libieee1284_port, F1284_NONBLOCK, (char *) &byte, 1);
|
||||
+ break;
|
||||
+ case 4: // EPP/ECP data
|
||||
+ ieee1284_epp_write_data (libieee1284_port, F1284_NONBLOCK, (char *) &byte, 1);
|
||||
+ break;
|
||||
+ case 0x402: // ECP register
|
||||
+ printf ("WARNING: Ignored write to ECP register\n");
|
||||
+ break;
|
||||
+ default:
|
||||
+ fprintf (stderr,
|
||||
+ "ERROR: outportb() tried to write to an unsupported port (0x%x)\n",
|
||||
+ port);
|
||||
+ exit (1);
|
||||
+ }
|
||||
#elif defined __BEOS__
|
||||
st_ioport_t temp;
|
||||
|
||||
@@ -499,6 +602,28 @@
|
||||
port);
|
||||
exit (1);
|
||||
}
|
||||
+#elif defined USE_LIBIEEE1284
|
||||
+ int ppreg = port - ucon64.parport;
|
||||
+ unsigned char buf[2];
|
||||
+
|
||||
+ // words are written in little endian format
|
||||
+ buf[0] = (unsigned char) word;
|
||||
+ buf[1] = word >> 8;
|
||||
+ switch (ppreg)
|
||||
+ {
|
||||
+ case 3: // EPP/ECP address
|
||||
+ ieee1284_epp_write_addr (libieee1284_port, F1284_NONBLOCK | F1284_FASTEPP, (char *) buf, 2);
|
||||
+ break;
|
||||
+ case 4: // EPP/ECP data
|
||||
+ ieee1284_epp_write_data (libieee1284_port, F1284_NONBLOCK | F1284_FASTEPP, (char *) buf, 2);
|
||||
+ break;
|
||||
+ // the data, control and ECP registers should only be accessed in "8-bit mode"
|
||||
+ default:
|
||||
+ fprintf (stderr,
|
||||
+ "ERROR: outportw() tried to write to an unsupported port (0x%x)\n",
|
||||
+ port);
|
||||
+ exit (1);
|
||||
+ }
|
||||
#elif defined __BEOS__
|
||||
st_ioport_t temp;
|
||||
|
||||
@@ -529,7 +654,7 @@
|
||||
}
|
||||
|
||||
|
||||
-#if (defined __i386__ || defined __x86_64__ || defined _WIN32) && !defined USE_PPDEV
|
||||
+#if (defined __i386__ || defined __x86_64__ || defined _WIN32) && !defined USE_PPDEV && !defined USE_LIBIEEE1284
|
||||
#define DETECT_MAX_CNT 1000
|
||||
static int
|
||||
parport_probe (unsigned int port)
|
||||
@@ -557,6 +682,7 @@
|
||||
#endif
|
||||
|
||||
|
||||
+#ifndef USE_LIBIEEE1284
|
||||
#ifdef _WIN32
|
||||
static LONG
|
||||
new_exception_filter (LPEXCEPTION_POINTERS exception_pointers)
|
||||
@@ -584,6 +710,7 @@
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
#endif
|
||||
+#endif
|
||||
|
||||
|
||||
int
|
||||
@@ -637,6 +764,48 @@
|
||||
|
||||
parport_io_direction = FORWARD; // set forward direction as default
|
||||
ioctl (parport_io_fd, PPDATADIR, &parport_io_direction);
|
||||
+#elif defined USE_LIBIEEE1284
|
||||
+ struct parport_list list;
|
||||
+ int capabilities, ucon64_parport;
|
||||
+
|
||||
+ if (port == PARPORT_UNKNOWN)
|
||||
+ port = 0;
|
||||
+
|
||||
+ if (ieee1284_find_ports (&list, 0) != E1284_OK)
|
||||
+ {
|
||||
+ fputs ("ERROR: Could not get port list\n", stderr);
|
||||
+ exit (1);
|
||||
+ }
|
||||
+
|
||||
+ if (port < list.portc)
|
||||
+ libieee1284_port = list.portv[port];
|
||||
+ else
|
||||
+ {
|
||||
+ fprintf (stderr, "ERROR: libieee1284 port %d not available\n", port);
|
||||
+ exit (1);
|
||||
+ }
|
||||
+
|
||||
+ if (ieee1284_open (libieee1284_port, F1284_EXCL, &capabilities) != E1284_OK)
|
||||
+ {
|
||||
+ fprintf (stderr, "ERROR: Could not open libieee1284 port %d\n", port);
|
||||
+ exit (1);
|
||||
+ }
|
||||
+ // TODO: Handle ECP mode correctly
|
||||
+ if (ucon64.parport_mode == UCON64_EPP || ucon64.parport_mode == UCON64_ECP)
|
||||
+ if ((capabilities & (CAP1284_EPP | CAP1284_ECP)) == 0)
|
||||
+ printf ("WARNING: EPP or ECP mode was requested, but not available\n");
|
||||
+
|
||||
+ ieee1284_free_ports (&list);
|
||||
+
|
||||
+ if (ieee1284_claim (libieee1284_port) != E1284_OK)
|
||||
+ {
|
||||
+ fprintf (stderr, "ERROR: Could not claim libieee1284 port %d\n", port);
|
||||
+ ieee1284_close (libieee1284_port);
|
||||
+ exit (1);
|
||||
+ }
|
||||
+
|
||||
+ parport_io_direction = FORWARD;
|
||||
+ ieee1284_data_dir (libieee1284_port, parport_io_direction);
|
||||
#elif defined __BEOS__
|
||||
parport_io_fd = open ("/dev/misc/ioport", O_RDWR | O_NONBLOCK);
|
||||
if (parport_io_fd == -1)
|
||||
@@ -710,16 +879,18 @@
|
||||
}
|
||||
#endif
|
||||
|
||||
-#if defined USE_PPDEV || defined __BEOS__ || defined __FreeBSD__
|
||||
+#if defined USE_PPDEV || defined __BEOS__ || defined __FreeBSD__ || defined USE_LIBIEEE1284
|
||||
if (register_func (close_io_port) == -1)
|
||||
{
|
||||
+#ifndef USE_LIBIEEE1284
|
||||
close (parport_io_fd);
|
||||
+#endif
|
||||
fprintf (stderr, "ERROR: Could not register function with register_func()\n");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
-#if defined __linux__ && (defined __i386__ || defined __x86_64__) && !defined USE_PPDEV
|
||||
+#if defined __linux__ && (defined __i386__ || defined __x86_64__) && !defined USE_PPDEV && !defined USE_LIBIEEE1284
|
||||
/*
|
||||
Some code needs us to switch to the real uid and gid. However, other code
|
||||
needs access to I/O ports other than the standard printer port registers.
|
||||
@@ -751,7 +922,7 @@
|
||||
}
|
||||
#endif
|
||||
|
||||
-#if (defined __i386__ || defined __x86_64__ || defined _WIN32) && !defined USE_PPDEV
|
||||
+#if (defined __i386__ || defined __x86_64__ || defined _WIN32) && !defined USE_PPDEV && !defined USE_LIBIEEE1284
|
||||
|
||||
#if defined _WIN32 || defined __CYGWIN__
|
||||
/*
|
||||
@@ -914,9 +1085,9 @@
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
-#endif // (__i386__ || __x86_64__ || _WIN32) && !USE_PPDEV
|
||||
+#endif // (__i386__ || __x86_64__ || _WIN32) && !USE_PPDEV && !USE_LIBIEEE1284
|
||||
|
||||
-#ifdef USE_PPDEV
|
||||
+#if defined USE_PPDEV || defined USE_LIBIEEE1284
|
||||
// the following two calls need a valid value for ucon64.parport
|
||||
ucon64_parport = ucon64.parport;
|
||||
ucon64.parport = port;
|
||||
@@ -924,7 +1095,7 @@
|
||||
outportb ((unsigned short) (port + PARPORT_CONTROL),
|
||||
(unsigned char) (inportb ((unsigned short) (port + PARPORT_CONTROL)) & 0x0f));
|
||||
// bit 4 = 0 -> IRQ disable for ACK, bit 5-7 unused
|
||||
-#ifdef USE_PPDEV
|
||||
+#if defined USE_PPDEV || defined USE_LIBIEEE1284
|
||||
ucon64.parport = ucon64_parport;
|
||||
#endif
|
||||
|
||||
@@ -932,7 +1103,7 @@
|
||||
}
|
||||
|
||||
|
||||
-#if defined USE_PPDEV || defined __BEOS__ || defined __FreeBSD__ || defined AMIGA
|
||||
+#if defined USE_PPDEV || defined __BEOS__ || defined __FreeBSD__ || defined AMIGA || defined USE_LIBIEEE1284
|
||||
void
|
||||
close_io_port (void)
|
||||
{
|
||||
@@ -947,6 +1118,9 @@
|
||||
// it ppdev will do it for us...
|
||||
ioctl (parport_io_fd, PPNEGOT, &parport_io_mode);
|
||||
ioctl (parport_io_fd, PPRELEASE);
|
||||
+#elif defined USE_LIBIEEE1284
|
||||
+ ieee1284_release (libieee1284_port);
|
||||
+ ieee1284_close (libieee1284_port);
|
||||
#else // __BEOS__ || __FreeBSD__
|
||||
close (parport_io_fd);
|
||||
#endif
|
||||
@@ -958,7 +1132,7 @@
|
||||
parport_close (int parport)
|
||||
{
|
||||
(void) parport;
|
||||
-#if defined USE_PPDEV || defined __BEOS__ || defined __FreeBSD__ || defined AMIGA
|
||||
+#if defined USE_PPDEV || defined __BEOS__ || defined __FreeBSD__ || defined AMIGA || defined USE_LIBIEEE1284
|
||||
if (unregister_func (close_io_port) == 0) // call func only if it can be removed!
|
||||
close_io_port (); // (or else it will be called twice)
|
||||
#elif defined _WIN32 || defined __CYGWIN__
|
||||
@@ -976,6 +1150,9 @@
|
||||
{
|
||||
#ifdef USE_PPDEV
|
||||
printf ("Using parallel port device: %s\n", ucon64.parport_dev);
|
||||
+#elif defined USE_LIBIEEE1284
|
||||
+ printf ("Using parallel port device: %s, base address 0x%lx\n",
|
||||
+ libieee1284_port->filename, libieee1284_port->base_addr); // ->name
|
||||
#elif defined AMIGA
|
||||
printf ("Using parallel port device: %s, port %d\n", ucon64.parport_dev, ucon64.parport);
|
||||
#else
|
||||
@@ -1,343 +0,0 @@
|
||||
<html><head>
|
||||
<link rel="icon" href="images/icon.png" type="image/png">
|
||||
<title>uCON64 - License</title></head><body bgcolor="#ffffff"><tt>
|
||||
GNU GENERAL PUBLIC LICENSE<br>
|
||||
Version 2, June 1991<br>
|
||||
<br>
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.<br>
|
||||
675 Mass Ave, Cambridge, MA 02139, USA<br>
|
||||
Everyone is permitted to copy and distribute verbatim copies<br>
|
||||
of this license document, but changing it is not allowed.<br>
|
||||
<br>
|
||||
Preamble<br>
|
||||
<br>
|
||||
The licenses for most software are designed to take away your<br>
|
||||
freedom to share and change it. By contrast, the GNU General Public<br>
|
||||
License is intended to guarantee your freedom to share and change free<br>
|
||||
software--to make sure the software is free for all its users. This<br>
|
||||
General Public License applies to most of the Free Software<br>
|
||||
Foundation's software and to any other program whose authors commit to<br>
|
||||
using it. (Some other Free Software Foundation software is covered by<br>
|
||||
the GNU Library General Public License instead.) You can apply it to<br>
|
||||
your programs, too.<br>
|
||||
<br>
|
||||
When we speak of free software, we are referring to freedom, not<br>
|
||||
price. Our General Public Licenses are designed to make sure that you<br>
|
||||
have the freedom to distribute copies of free software (and charge for<br>
|
||||
this service if you wish), that you receive source code or can get it<br>
|
||||
if you want it, that you can change the software or use pieces of it<br>
|
||||
in new free programs; and that you know you can do these things.<br>
|
||||
<br>
|
||||
To protect your rights, we need to make restrictions that forbid<br>
|
||||
anyone to deny you these rights or to ask you to surrender the rights.<br>
|
||||
These restrictions translate to certain responsibilities for you if you<br>
|
||||
distribute copies of the software, or if you modify it.<br>
|
||||
<br>
|
||||
For example, if you distribute copies of such a program, whether<br>
|
||||
gratis or for a fee, you must give the recipients all the rights that<br>
|
||||
you have. You must make sure that they, too, receive or can get the<br>
|
||||
source code. And you must show them these terms so they know their<br>
|
||||
rights.<br>
|
||||
<br>
|
||||
We protect your rights with two steps: (1) copyright the software, and<br>
|
||||
(2) offer you this license which gives you legal permission to copy,<br>
|
||||
distribute and/or modify the software.<br>
|
||||
<br>
|
||||
Also, for each author's protection and ours, we want to make certain<br>
|
||||
that everyone understands that there is no warranty for this free<br>
|
||||
software. If the software is modified by someone else and passed on, we<br>
|
||||
want its recipients to know that what they have is not the original, so<br>
|
||||
that any problems introduced by others will not reflect on the original<br>
|
||||
authors' reputations.<br>
|
||||
<br>
|
||||
Finally, any free program is threatened constantly by software<br>
|
||||
patents. We wish to avoid the danger that redistributors of a free<br>
|
||||
program will individually obtain patent licenses, in effect making the<br>
|
||||
program proprietary. To prevent this, we have made it clear that any<br>
|
||||
patent must be licensed for everyone's free use or not licensed at all.<br>
|
||||
<br>
|
||||
The precise terms and conditions for copying, distribution and<br>
|
||||
modification follow.<br>
|
||||
<br>
|
||||
GNU GENERAL PUBLIC LICENSE<br>
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION<br>
|
||||
<br>
|
||||
0. This License applies to any program or other work which contains<br>
|
||||
a notice placed by the copyright holder saying it may be distributed<br>
|
||||
under the terms of this General Public License. The "Program", below,<br>
|
||||
refers to any such program or work, and a "work based on the Program"<br>
|
||||
means either the Program or any derivative work under copyright law:<br>
|
||||
that is to say, a work containing the Program or a portion of it,<br>
|
||||
either verbatim or with modifications and/or translated into another<br>
|
||||
language. (Hereinafter, translation is included without limitation in<br>
|
||||
the term "modification".) Each licensee is addressed as "you".<br>
|
||||
<br>
|
||||
Activities other than copying, distribution and modification are not<br>
|
||||
covered by this License; they are outside its scope. The act of<br>
|
||||
running the Program is not restricted, and the output from the Program<br>
|
||||
is covered only if its contents constitute a work based on the<br>
|
||||
Program (independent of having been made by running the Program).<br>
|
||||
Whether that is true depends on what the Program does.<br>
|
||||
<br>
|
||||
1. You may copy and distribute verbatim copies of the Program's<br>
|
||||
source code as you receive it, in any medium, provided that you<br>
|
||||
conspicuously and appropriately publish on each copy an appropriate<br>
|
||||
copyright notice and disclaimer of warranty; keep intact all the<br>
|
||||
notices that refer to this License and to the absence of any warranty;<br>
|
||||
and give any other recipients of the Program a copy of this License<br>
|
||||
along with the Program.<br>
|
||||
<br>
|
||||
You may charge a fee for the physical act of transferring a copy, and<br>
|
||||
you may at your option offer warranty protection in exchange for a fee.<br>
|
||||
<br>
|
||||
2. You may modify your copy or copies of the Program or any portion<br>
|
||||
of it, thus forming a work based on the Program, and copy and<br>
|
||||
distribute such modifications or work under the terms of Section 1<br>
|
||||
above, provided that you also meet all of these conditions:<br>
|
||||
<br>
|
||||
a) You must cause the modified files to carry prominent notices<br>
|
||||
stating that you changed the files and the date of any change.<br>
|
||||
<br>
|
||||
b) You must cause any work that you distribute or publish, that in<br>
|
||||
whole or in part contains or is derived from the Program or any<br>
|
||||
part thereof, to be licensed as a whole at no charge to all third<br>
|
||||
parties under the terms of this License.<br>
|
||||
<br>
|
||||
c) If the modified program normally reads commands interactively<br>
|
||||
when run, you must cause it, when started running for such<br>
|
||||
interactive use in the most ordinary way, to print or display an<br>
|
||||
announcement including an appropriate copyright notice and a<br>
|
||||
notice that there is no warranty (or else, saying that you provide<br>
|
||||
a warranty) and that users may redistribute the program under<br>
|
||||
these conditions, and telling the user how to view a copy of this<br>
|
||||
License. (Exception: if the Program itself is interactive but<br>
|
||||
does not normally print such an announcement, your work based on<br>
|
||||
the Program is not required to print an announcement.)<br>
|
||||
<br>
|
||||
These requirements apply to the modified work as a whole. If<br>
|
||||
identifiable sections of that work are not derived from the Program,<br>
|
||||
and can be reasonably considered independent and separate works in<br>
|
||||
themselves, then this License, and its terms, do not apply to those<br>
|
||||
sections when you distribute them as separate works. But when you<br>
|
||||
distribute the same sections as part of a whole which is a work based<br>
|
||||
on the Program, the distribution of the whole must be on the terms of<br>
|
||||
this License, whose permissions for other licensees extend to the<br>
|
||||
entire whole, and thus to each and every part regardless of who wrote it.<br>
|
||||
<br>
|
||||
Thus, it is not the intent of this section to claim rights or contest<br>
|
||||
your rights to work written entirely by you; rather, the intent is to<br>
|
||||
exercise the right to control the distribution of derivative or<br>
|
||||
collective works based on the Program.<br>
|
||||
<br>
|
||||
In addition, mere aggregation of another work not based on the Program<br>
|
||||
with the Program (or with a work based on the Program) on a volume of<br>
|
||||
a storage or distribution medium does not bring the other work under<br>
|
||||
the scope of this License.<br>
|
||||
<br>
|
||||
3. You may copy and distribute the Program (or a work based on it,<br>
|
||||
under Section 2) in object code or executable form under the terms of<br>
|
||||
Sections 1 and 2 above provided that you also do one of the following:<br>
|
||||
<br>
|
||||
a) Accompany it with the complete corresponding machine-readable<br>
|
||||
source code, which must be distributed under the terms of Sections<br>
|
||||
1 and 2 above on a medium customarily used for software interchange; or,<br>
|
||||
<br>
|
||||
b) Accompany it with a written offer, valid for at least three<br>
|
||||
years, to give any third party, for a charge no more than your<br>
|
||||
cost of physically performing source distribution, a complete<br>
|
||||
machine-readable copy of the corresponding source code, to be<br>
|
||||
distributed under the terms of Sections 1 and 2 above on a medium<br>
|
||||
customarily used for software interchange; or,<br>
|
||||
<br>
|
||||
c) Accompany it with the information you received as to the offer<br>
|
||||
to distribute corresponding source code. (This alternative is<br>
|
||||
allowed only for noncommercial distribution and only if you<br>
|
||||
received the program in object code or executable form with such<br>
|
||||
an offer, in accord with Subsection b above.)<br>
|
||||
<br>
|
||||
The source code for a work means the preferred form of the work for<br>
|
||||
making modifications to it. For an executable work, complete source<br>
|
||||
code means all the source code for all modules it contains, plus any<br>
|
||||
associated interface definition files, plus the scripts used to<br>
|
||||
control compilation and installation of the executable. However, as a<br>
|
||||
special exception, the source code distributed need not include<br>
|
||||
anything that is normally distributed (in either source or binary<br>
|
||||
form) with the major components (compiler, kernel, and so on) of the<br>
|
||||
operating system on which the executable runs, unless that component<br>
|
||||
itself accompanies the executable.<br>
|
||||
<br>
|
||||
If distribution of executable or object code is made by offering<br>
|
||||
access to copy from a designated place, then offering equivalent<br>
|
||||
access to copy the source code from the same place counts as<br>
|
||||
distribution of the source code, even though third parties are not<br>
|
||||
compelled to copy the source along with the object code.<br>
|
||||
<br>
|
||||
4. You may not copy, modify, sublicense, or distribute the Program<br>
|
||||
except as expressly provided under this License. Any attempt<br>
|
||||
otherwise to copy, modify, sublicense or distribute the Program is<br>
|
||||
void, and will automatically terminate your rights under this License.<br>
|
||||
However, parties who have received copies, or rights, from you under<br>
|
||||
this License will not have their licenses terminated so long as such<br>
|
||||
parties remain in full compliance.<br>
|
||||
<br>
|
||||
5. You are not required to accept this License, since you have not<br>
|
||||
signed it. However, nothing else grants you permission to modify or<br>
|
||||
distribute the Program or its derivative works. These actions are<br>
|
||||
prohibited by law if you do not accept this License. Therefore, by<br>
|
||||
modifying or distributing the Program (or any work based on the<br>
|
||||
Program), you indicate your acceptance of this License to do so, and<br>
|
||||
all its terms and conditions for copying, distributing or modifying<br>
|
||||
the Program or works based on it.<br>
|
||||
<br>
|
||||
6. Each time you redistribute the Program (or any work based on the<br>
|
||||
Program), the recipient automatically receives a license from the<br>
|
||||
original licensor to copy, distribute or modify the Program subject to<br>
|
||||
these terms and conditions. You may not impose any further<br>
|
||||
restrictions on the recipients' exercise of the rights granted herein.<br>
|
||||
You are not responsible for enforcing compliance by third parties to<br>
|
||||
this License.<br>
|
||||
<br>
|
||||
7. If, as a consequence of a court judgment or allegation of patent<br>
|
||||
infringement or for any other reason (not limited to patent issues),<br>
|
||||
conditions are imposed on you (whether by court order, agreement or<br>
|
||||
otherwise) that contradict the conditions of this License, they do not<br>
|
||||
excuse you from the conditions of this License. If you cannot<br>
|
||||
distribute so as to satisfy simultaneously your obligations under this<br>
|
||||
License and any other pertinent obligations, then as a consequence you<br>
|
||||
may not distribute the Program at all. For example, if a patent<br>
|
||||
license would not permit royalty-free redistribution of the Program by<br>
|
||||
all those who receive copies directly or indirectly through you, then<br>
|
||||
the only way you could satisfy both it and this License would be to<br>
|
||||
refrain entirely from distribution of the Program.<br>
|
||||
<br>
|
||||
If any portion of this section is held invalid or unenforceable under<br>
|
||||
any particular circumstance, the balance of the section is intended to<br>
|
||||
apply and the section as a whole is intended to apply in other<br>
|
||||
circumstances.<br>
|
||||
<br>
|
||||
It is not the purpose of this section to induce you to infringe any<br>
|
||||
patents or other property right claims or to contest validity of any<br>
|
||||
such claims; this section has the sole purpose of protecting the<br>
|
||||
integrity of the free software distribution system, which is<br>
|
||||
implemented by public license practices. Many people have made<br>
|
||||
generous contributions to the wide range of software distributed<br>
|
||||
through that system in reliance on consistent application of that<br>
|
||||
system; it is up to the author/donor to decide if he or she is willing<br>
|
||||
to distribute software through any other system and a licensee cannot<br>
|
||||
impose that choice.<br>
|
||||
<br>
|
||||
This section is intended to make thoroughly clear what is believed to<br>
|
||||
be a consequence of the rest of this License.<br>
|
||||
<br>
|
||||
8. If the distribution and/or use of the Program is restricted in<br>
|
||||
certain countries either by patents or by copyrighted interfaces, the<br>
|
||||
original copyright holder who places the Program under this License<br>
|
||||
may add an explicit geographical distribution limitation excluding<br>
|
||||
those countries, so that distribution is permitted only in or among<br>
|
||||
countries not thus excluded. In such case, this License incorporates<br>
|
||||
the limitation as if written in the body of this License.<br>
|
||||
<br>
|
||||
9. The Free Software Foundation may publish revised and/or new versions<br>
|
||||
of the General Public License from time to time. Such new versions will<br>
|
||||
be similar in spirit to the present version, but may differ in detail to<br>
|
||||
address new problems or concerns.<br>
|
||||
<br>
|
||||
Each version is given a distinguishing version number. If the Program<br>
|
||||
specifies a version number of this License which applies to it and "any<br>
|
||||
later version", you have the option of following the terms and conditions<br>
|
||||
either of that version or of any later version published by the Free<br>
|
||||
Software Foundation. If the Program does not specify a version number of<br>
|
||||
this License, you may choose any version ever published by the Free Software<br>
|
||||
Foundation.<br>
|
||||
<br>
|
||||
10. If you wish to incorporate parts of the Program into other free<br>
|
||||
programs whose distribution conditions are different, write to the author<br>
|
||||
to ask for permission. For software which is copyrighted by the Free<br>
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes<br>
|
||||
make exceptions for this. Our decision will be guided by the two goals<br>
|
||||
of preserving the free status of all derivatives of our free software and<br>
|
||||
of promoting the sharing and reuse of software generally.<br>
|
||||
<br>
|
||||
NO WARRANTY<br>
|
||||
<br>
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY<br>
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN<br>
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES<br>
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED<br>
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF<br>
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS<br>
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE<br>
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,<br>
|
||||
REPAIR OR CORRECTION.<br>
|
||||
<br>
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING<br>
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR<br>
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,<br>
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING<br>
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED<br>
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY<br>
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER<br>
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE<br>
|
||||
POSSIBILITY OF SUCH DAMAGES.<br>
|
||||
<br>
|
||||
END OF TERMS AND CONDITIONS<br>
|
||||
<br>
|
||||
Appendix: How to Apply These Terms to Your New Programs<br>
|
||||
<br>
|
||||
If you develop a new program, and you want it to be of the greatest<br>
|
||||
possible use to the public, the best way to achieve this is to make it<br>
|
||||
free software which everyone can redistribute and change under these terms.<br>
|
||||
<br>
|
||||
To do so, attach the following notices to the program. It is safest<br>
|
||||
to attach them to the start of each source file to most effectively<br>
|
||||
convey the exclusion of warranty; and each file should have at least<br>
|
||||
the "copyright" line and a pointer to where the full notice is found.<br>
|
||||
<br>
|
||||
<one line to give the program's name and a brief idea of what it does.><br>
|
||||
Copyright (C) 19yy <name of author><br>
|
||||
<br>
|
||||
This program is free software; you can redistribute it and/or modify<br>
|
||||
it under the terms of the GNU General Public License as published by<br>
|
||||
the Free Software Foundation; either version 2 of the License, or<br>
|
||||
(at your option) any later version.<br>
|
||||
<br>
|
||||
This program is distributed in the hope that it will be useful,<br>
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br>
|
||||
GNU General Public License for more details.<br>
|
||||
<br>
|
||||
You should have received a copy of the GNU General Public License<br>
|
||||
along with this program; if not, write to the Free Software<br>
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.<br>
|
||||
<br>
|
||||
Also add information on how to contact you by electronic and paper mail.<br>
|
||||
<br>
|
||||
If the program is interactive, make it output a short notice like this<br>
|
||||
when it starts in an interactive mode:<br>
|
||||
<br>
|
||||
Gnomovision version 69, Copyright (C) 19yy name of author<br>
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.<br>
|
||||
This is free software, and you are welcome to redistribute it<br>
|
||||
under certain conditions; type `show c' for details.<br>
|
||||
<br>
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate<br>
|
||||
parts of the General Public License. Of course, the commands you use may<br>
|
||||
be called something other than `show w' and `show c'; they could even be<br>
|
||||
mouse-clicks or menu items--whatever suits your program.<br>
|
||||
<br>
|
||||
You should also get your employer (if you work as a programmer) or your<br>
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if<br>
|
||||
necessary. Here is a sample; alter the names:<br>
|
||||
<br>
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program<br>
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.<br>
|
||||
<br>
|
||||
<signature of Ty Coon>, 1 April 1989<br>
|
||||
Ty Coon, President of Vice<br>
|
||||
<br>
|
||||
This General Public License does not permit incorporating your program into<br>
|
||||
proprietary programs. If your program is a subroutine library, you may<br>
|
||||
consider it more useful to permit linking proprietary applications with the<br>
|
||||
library. If this is what you want to do, use the GNU Library General<br>
|
||||
Public License instead of this License.<br>
|
||||
</tt></body></html>
|
||||
@@ -1,594 +0,0 @@
|
||||
<html><head>
|
||||
<link rel="icon" href="images/icon.png" type="image/png">
|
||||
<title>uCON64 - ReadMe</title></head><body bgcolor="#ffffff"><tt><pre>
|
||||
uCON64 - THE tool for all your video game console concerns.
|
||||
|
||||
Its main features are:
|
||||
- It is Open Source Software
|
||||
- (Therefore) support for MANY platforms like: Unix, Win32, MSDOS, etc...
|
||||
- Support for 14+ different cartridge and disc-based video game console systems
|
||||
- Support for ALL common patch file formats like: IPS *), APS, BSL, PPF and
|
||||
Game Genie
|
||||
*) with RLE compression<!--
|
||||
- Support of DAT file formats like: RomCenter Data, GoodXXXX
|
||||
RomCenter Data
|
||||
MAME Listinfo
|
||||
RomCenter 2 Data
|
||||
Title List
|
||||
RAINE Gameinfo
|
||||
Callus Gamelist
|
||||
Retrocade Romlist
|
||||
Sparcade RAT File
|
||||
Mimic GCS
|
||||
Nebula Driver
|
||||
-->
|
||||
- Support for 10+ different backup units to backup/restore ROM(s), disc(s) and
|
||||
SRAM(s) like: Flash Advance Linker, Flash 2 Advance, Doctor V64 (Junior),
|
||||
Super Wild Card, Game Doctor, Dexdrive, Super Magic Drive, Game Boy Xchanger,
|
||||
Mad Catz Camera Link, Lynxit, MD-PRO, SMS-PRO, PCE-PRO, GG-PRO, Super Flash
|
||||
and your CD-writer.
|
||||
- Finally 150+(!) different options/features for every kind of ROM
|
||||
handling/management known to man :-)
|
||||
<!-- 120 options, 62 switches last time I counted them -->
|
||||
Including:
|
||||
*VERY* verbose ROM information for ALL systems, detection of bad dumps using
|
||||
internal checksums or DAT files, CRC32 calculation, ROM comparison,
|
||||
modification (strip, pad, etc...), SRAM conversion (emulator <-> backup
|
||||
unit), DiscJuggler and Nero image conversions, complete gzip and zip support
|
||||
for all file-related funtions, etc...
|
||||
- Always up-to-date with support for new shit, trends, formats, and headers
|
||||
like UNIF (NES), NSRT (SNES), new DAT file formats, etc...
|
||||
|
||||
For console specific options check the following usage:
|
||||
|
||||
uCON64 2.0.0 Unix (Linux) 1999-2005
|
||||
Uses code from various people. See 'developers.html' for more!
|
||||
This may be freely redistributed under the terms of the GNU Public License
|
||||
|
||||
Usage: ucon64 [OPTION]... [ROM|IMAGE|SRAM|FILE|DIR|ARCHIVE]...
|
||||
|
||||
Options
|
||||
-o=DIRECTORY specify output directory
|
||||
--nbak prevents backup files (*.BAK)
|
||||
--ncol disable ANSI colors in output
|
||||
--port=PORT specify USB or parallel PORT={USB0, USB1, 3bc, 378, 278, ...}
|
||||
--hdn=N force ROM has backup unit/emulator header with size of N Bytes
|
||||
--hd same as --hdn=512
|
||||
most backup units use a header with a size of 512 Bytes
|
||||
--nhd force ROM has no backup unit/emulator header
|
||||
--ns force ROM is not split
|
||||
-e emulate/run ROM (check .ucon64rc for all Emulator settings)
|
||||
--crc show CRC32 value of ROM
|
||||
--sha1 show SHA1 value of ROM
|
||||
--md5 show MD5 value of ROM
|
||||
--ls generate ROM list for all recognized ROMs
|
||||
--lsv like --ls but more verbose
|
||||
--hex[=ST] show ROM as hexdump; use "ucon64 --hex ...|less"
|
||||
ST is the optional start value in bytes
|
||||
--dual[=ST] show ROM as dualdump; use "ucon64 --dual ...|less"
|
||||
--code[=ST] show ROM as code; use "ucon64 --code ...|less"
|
||||
--print[=ST] show ROM in printable characters; use "ucon64 --print ...|less"
|
||||
--find=STRING find STRING in ROM (wildcard: '?')
|
||||
--findi=STR like --find but ignores the case of alpha bytes
|
||||
--findr=STR like --find but looks also for shifted/relative similarities
|
||||
(wildcard: disabled)
|
||||
-c=FILE compare FILE with ROM for differences
|
||||
--cs=FILE compare FILE with ROM for similarities
|
||||
--help display this help and exit
|
||||
--version output version information and exit
|
||||
-q be quiet (don't show ROM info)
|
||||
-v be more verbose (show backup unit headers also)
|
||||
|
||||
Padding
|
||||
--ispad check if ROM is padded
|
||||
--pad pad ROM to next Mb
|
||||
-p same as --pad
|
||||
--padn=N pad ROM to N Bytes (put Bytes with value 0x00 after end)
|
||||
--strip=N strip N Bytes from end of ROM
|
||||
--stpn=N strip N Bytes from start of ROM
|
||||
--stp same as --stpn=512
|
||||
most backup units use a header with a size of 512 Bytes
|
||||
--insn=N insert N Bytes (0x00) before ROM
|
||||
--ins same as --insn=512
|
||||
most backup units use a header with a size of 512 Bytes
|
||||
|
||||
DATabase (support for DAT files)
|
||||
--db DATabase statistics
|
||||
--dbv like --db but more verbose
|
||||
--dbs=CRC32 search ROM with CRC32 in DATabase
|
||||
--scan generate ROM list for all ROMs using DATabase
|
||||
like: GoodXXXX scan ...
|
||||
--lsd same as --scan
|
||||
--mkdat=DATFILE create DAT file; use -o to specify an output directory
|
||||
--rrom rename ROMs to their internal names
|
||||
--rename rename ROMs to their DATabase names
|
||||
use -o to specify an output directory
|
||||
--rr83 force to rename to 8.3 filenames
|
||||
--force63 force to rename all filenames into Joliet CD format
|
||||
like: GoodXXXX rename inplace force63 ...
|
||||
TIP: using --nes would process only NES ROMs
|
||||
--rl rename ROMs to lowercase
|
||||
--ru rename ROMs to uppercase
|
||||
|
||||
Patching
|
||||
--poke=OFF:V change byte at file offset OFF to value V (both in hexadecimal)
|
||||
--pattern=FILE change ROM based on patterns specified in FILE
|
||||
--patch=PATCH specify the PATCH for the following options
|
||||
use this option or uCON64 expects the last commandline
|
||||
argument to be the name of the PATCH file
|
||||
-b apply Baseline/BSL PATCH to ROM
|
||||
-i apply IPS PATCH to ROM (IPS<=v1.2)
|
||||
--mki=ORG_ROM create IPS patch; ROM should be the modified ROM
|
||||
-a apply APS PATCH to ROM (APS<=v1.2)
|
||||
--mka=ORG_ROM create APS patch; ROM should be the modified ROM
|
||||
--na=DESC change APS single line DESCRIPTION
|
||||
--ppf apply PPF PATCH to IMAGE (PPF<=v2.0); ROM should be an IMAGE
|
||||
--mkppf=ORG_IMG create PPF patch; ROM should be the modified IMAGE
|
||||
--nppf=DESC change PPF single line DESCRIPTION
|
||||
--idppf=FILE_ID.DIZ change FILE_ID.DIZ of PPF PATCH (PPF v2.0)
|
||||
--gge=CODE encode and display Game Genie code
|
||||
example: --gge=CODE --sms or --gge=CODE --gb
|
||||
CODE='AAAA:VV' or CODE='AAAA:VV:CC'
|
||||
--gge=CODE --gen
|
||||
CODE='AAAAAA:VVVV'
|
||||
--gge=CODE --nes
|
||||
CODE='AAAA:VV' or CODE='AAAA:VV:CC'
|
||||
--gge=CODE --snes
|
||||
CODE='AAAAAA:VV'
|
||||
--ggd=GG_CODE decode Game Genie code
|
||||
example: --ggd=GG_CODE --sms or --ggd=GG_CODE --gb
|
||||
GG_CODE='XXX-XXX' or GG_CODE='XXX-XXX-XXX'
|
||||
--ggd=GG_CODE --gen
|
||||
GG_CODE='XXXX-XXXX'
|
||||
--ggd=GG_CODE --nes
|
||||
GG_CODE='XXXXXX' or GG_CODE='XXXXXXXX'
|
||||
--ggd=GG_CODE --snes
|
||||
GG_CODE='XXXX-XXXX'
|
||||
--gg=GG_CODE apply Game Genie code (permanently)
|
||||
example: like above but a ROM is required
|
||||
supported are:
|
||||
Game Boy/(Super GB)/GB Pocket/Color GB/(GB Advance),
|
||||
Sega Master System(II/III)/Game Gear (Handheld),
|
||||
Genesis/Sega Mega Drive/Sega CD/32X/Nomad,
|
||||
Nintendo Entertainment System/NES/Famicom/Game Axe (Redant),
|
||||
Super Nintendo Entertainment System/SNES/Super Famicom
|
||||
|
||||
All disc-based consoles
|
||||
--disc force recognition; NEEDED
|
||||
--rip=N rip/dump track N from IMAGE
|
||||
--bin2iso=N convert track N to ISO (if possible) by resizing
|
||||
sectors to 2048 Bytes
|
||||
--isofix=N fix corrupted track N (if possible)
|
||||
if PVD points to a bad DR offset it will add padding data
|
||||
so actual DR gets located in right absolute address
|
||||
--mkcue generate CUE sheet for IMAGE or existing TOC sheet
|
||||
--mktoc generate TOC sheet for IMAGE or existing CUE sheet
|
||||
|
||||
Dreamcast
|
||||
--dc force recognition
|
||||
--scr scramble 1ST_READ.BIN for selfboot CDs
|
||||
--unscr unscramble 1ST_READ.BIN for non-selfboot CDs
|
||||
--mkip generate IP.BIN file with default values
|
||||
--parse=TEMPLATE parse TEMPLATE file into a IP.BIN;
|
||||
creates an empty template when TEMPLATE does not exist
|
||||
|
||||
Playstation (One)/Playstation 2 (CD only)
|
||||
--psx force recognition
|
||||
DexDrive
|
||||
--xdex=N send/receive Block N to/from DexDrive; --port=PORT
|
||||
receives automatically when SRAM does not exist
|
||||
|
||||
Game Boy Advance
|
||||
--gba force recognition
|
||||
-n=NEW_NAME change internal ROM name to NEW_NAME
|
||||
--logo restore ROM logo character data (offset: 0x04-0x9F)
|
||||
--chk fix ROM header checksum
|
||||
--sram patch ROM for SRAM saving
|
||||
--crp=WAIT_TIME slow down ROM access ("crash patch");
|
||||
WAIT_TIME=0 default in most crash patches
|
||||
WAIT_TIME=4 faster than 0, slower than 8
|
||||
WAIT_TIME=8 faster than 4, slower than 28
|
||||
WAIT_TIME=12 slowest cartridge access speed
|
||||
WAIT_TIME=16 faster than 28, but slower than 20
|
||||
WAIT_TIME=20 default in most original cartridges
|
||||
WAIT_TIME=24 fastest cartridge access speed
|
||||
WAIT_TIME=28 faster than 8 but slower than 16
|
||||
--multi=SIZE make multi-game file for use with FAL/F2A flash card, truncated
|
||||
to SIZE Mbit; file with loader must be specified first, then
|
||||
all the ROMs, multi-game file to create last
|
||||
Flash 2 Advance (Ultra)
|
||||
--xf2a send/receive ROM to/from Flash 2 Advance (Ultra); --port=PORT
|
||||
receives automatically (32 Mbits) when ROM does not exist
|
||||
--xf2amulti=SIZE send multiple ROMs to Flash 2 Advance (Ultra); specify a
|
||||
loader in the configuration file; --port=PORT
|
||||
--xf2ac=N receive N Mbits of ROM from Flash 2 Advance (Ultra);
|
||||
--port=PORT
|
||||
--xf2as send/receive SRAM to/from Flash 2 Advance (Ultra); --port=PORT
|
||||
receives automatically when SRAM does not exist
|
||||
--xf2ab=BANK send/receive SRAM to/from Flash 2 Advance (Ultra) BANK
|
||||
BANK should be a number >= 1; --port=PORT
|
||||
receives automatically when SRAM does not exist
|
||||
Flash Advance Linker
|
||||
--xfal send/receive ROM to/from Flash Advance Linker; --port=PORT
|
||||
receives automatically (32 Mbits) when ROM does not exist
|
||||
--xfalmulti=SIZE send multiple ROMs to Flash Advance Linker (makes temporary
|
||||
multi-game file truncated to SIZE Mbit); specify a loader in
|
||||
the configuration file; --port=PORT
|
||||
--xfalc=N receive N Mbits of ROM from Flash Advance Linker; --port=PORT
|
||||
N can be 8, 16, 32, 64, 128 or 256
|
||||
--xfals send/receive SRAM to/from Flash Advance Linker; --port=PORT
|
||||
receives automatically when SRAM does not exist
|
||||
--xfalb=BANK send/receive SRAM to/from Flash Advance Linker BANK
|
||||
BANK can be 1, 2, 3 or 4; --port=PORT
|
||||
receives automatically when SRAM does not exist
|
||||
--xfalm try to enable EPP mode, default is SPP mode
|
||||
|
||||
Nintendo 64
|
||||
--n64 force recognition
|
||||
--int force ROM is in interleaved format (2143, V64)
|
||||
--nint force ROM is not in interleaved format (1234, Z64)
|
||||
-n=NEW_NAME change internal ROM name to NEW_NAME
|
||||
--v64 convert to Doctor V64 (and compatibles/interleaved)
|
||||
--z64 convert to Mr. Backup Z64 (not interleaved)
|
||||
--dint convert ROM to (non-)interleaved format (1234 <-> 2143)
|
||||
--swap same as --dint, byte-swap ROM
|
||||
--swap2 word-swap ROM (1234 <-> 3412)
|
||||
--bot=BOOTCODE replace/extract BOOTCODE (4032 Bytes) in/from ROM;
|
||||
extracts automatically if BOOTCODE does not exist
|
||||
--lsram=SRAM LaC's SRAM upload tool; ROM should be LaC's ROM image
|
||||
the SRAM must have a size of 512 Bytes
|
||||
this option generates a ROM which can be used to transfer
|
||||
SRAMs to your cartridge's SRAM (EEPROM)
|
||||
--usms=SMSROM Jos Kwanten's UltraSMS (Sega Master System/Game Gear emulator);
|
||||
ROM should be Jos Kwanten's UltraSMS ROM image
|
||||
works only for SMS ROMs which are <= 4 Mb in size
|
||||
--chk fix ROM checksum
|
||||
supports only 6102 and 6105 boot codes
|
||||
Doctor V64
|
||||
--xv64 send/receive ROM to/from Doctor V64; --port=PORT
|
||||
receives automatically when ROM does not exist
|
||||
Doctor V64 Junior
|
||||
--xdjr send ROM to Doctor V64 Junior; --port=PORT
|
||||
CD64
|
||||
--xcd64 send/receive ROM to/from CD64; --port=PORT
|
||||
receives automatically (64 Mbits) when ROM does not exist
|
||||
--xcd64c=N receive N Mbits of ROM from CD64; --port=PORT
|
||||
--xcd64b send boot emu to CD64; --port=PORT
|
||||
--xcd64s send/receive SRAM to/from CD64; --port=PORT
|
||||
receives automatically when SRAM file does not exist
|
||||
--xcd64f send/receive flash RAM to/from CD64; --port=PORT
|
||||
receives automatically when flash RAM file does not exist
|
||||
--xcd64e send/receive EEPROM data to/from CD64; --port=PORT
|
||||
receives automatically when EEPROM file does not exist
|
||||
--xcd64m=INDEX send/receive memory pack data to/from CD64; --port=PORT
|
||||
INDEX is ignored for CD64 BIOS protocol
|
||||
receives automatically when memory pack file does not exist
|
||||
--xcd64p=PROT use protocol PROT when communicating with CD64; --port=PORT
|
||||
PROT=0 CD64 BIOS
|
||||
PROT=1 Ghemor
|
||||
PROT=2 UltraLink
|
||||
DexDrive
|
||||
--xdex=N send/receive Block N to/from DexDrive; --port=PORT
|
||||
receives automatically when SRAM does not exist
|
||||
|
||||
Super Nintendo Entertainment System/SNES/Super Famicom
|
||||
--snes force recognition
|
||||
--hi force ROM is HiROM
|
||||
--nhi force ROM is not HiROM
|
||||
--erom force ROM is "Extended" (combine with -hi for Extended HiROM)
|
||||
--int force ROM is in interleaved format (GD3/UFO)
|
||||
--int2 force ROM is in interleaved format 2 (SFX)
|
||||
--nint force ROM is not in interleaved format
|
||||
--bs force ROM is a Broadcast Satellaview dump
|
||||
--nbs force ROM is a regular cartridge dump
|
||||
-n=NEW_NAME change internal ROM name to NEW_NAME
|
||||
--fig convert to *Pro Fighter*/FIG
|
||||
--figs convert emulator *.srm (SRAM) to *Pro Fighter*/FIG
|
||||
--gd3 convert to Game Doctor SF3(SF6/SF7)/Professor SF(SF II)
|
||||
--gd3s convert emulator *.srm (SRAM) to GD SF3(SF6/SF7)/Professor SF*
|
||||
--mgd convert to Multi Game*/MGD2/MGH/RAW
|
||||
--smc convert to Super Magicom/SMC
|
||||
--swc convert to Super Wild Card*/SWC
|
||||
--swcs convert emulator *.srm (SRAM) to Super Wild Card*/SWC
|
||||
--ufo convert to Super UFO
|
||||
--ufos convert emulator *.srm (SRAM) to Super UFO
|
||||
--stp convert SRAM from backup unit for use with an emulator
|
||||
--stp just strips the first 512 bytes
|
||||
--dbuh display (relevant part of) backup unit header
|
||||
--dint deinterleave ROM (regardless whether the ROM is interleaved)
|
||||
--ctrl=TYPE specify type of controller in port 1 for emu when converting
|
||||
TYPE=0 gamepad
|
||||
TYPE=1 mouse
|
||||
TYPE=2 mouse / gamepad
|
||||
TYPE=6 multitap
|
||||
--ctrl2=TYPE specify type of controller in port 2 for emu when converting
|
||||
TYPE=0 gamepad
|
||||
TYPE=1 mouse
|
||||
TYPE=2 mouse / gamepad
|
||||
TYPE=3 super scope
|
||||
TYPE=4 super scope / gamepad
|
||||
TYPE=5 Konami's justifier
|
||||
TYPE=6 multitap
|
||||
TYPE=7 mouse / super scope / gamepad
|
||||
--col=0xCOLOR convert 0xRRGGBB (HTML) <-> 0xXXXX (SNES)
|
||||
-j join split ROM
|
||||
-s split ROM; default part size is 8 Mb
|
||||
--ssize=SIZE specify split part size in Mbit (not for Game Doctor SF3)
|
||||
-k remove protection (crack)
|
||||
-f remove NTSC/PAL protection
|
||||
-l remove SlowROM checks
|
||||
--chk fix ROM checksum
|
||||
--multi=SIZE make multi-game file for use with Super Flash flash card,
|
||||
truncated to SIZE Mbit; file with loader must be specified
|
||||
first, then all the ROMs, multi-game file to create last
|
||||
--dmirr "de-mirror" ROM (strip mirrored block from end of ROM)
|
||||
--dnsrt "de-NSRT" ROM (restore name and checksum from NSRT header)
|
||||
Super Com Pro/Super Magicom/SMC/Super Wild Card (1.6XC/2.7CC/2.8CC/DX/DX2)/SWC
|
||||
--xswc send/receive ROM to/from Super Wild Card*/SWC; --port=PORT
|
||||
receives automatically when ROM does not exist
|
||||
--xswc2 same as --xswc, but enables Real Time Save mode (SWC only)
|
||||
--xswc-io=MODE specify SWC I/O mode; use with -xswc or -xswcc
|
||||
MODE=0x001 force 32 Mbit dump
|
||||
MODE=0x002 use alternative method for determining ROM size
|
||||
MODE=0x004 Super FX
|
||||
MODE=0x008 S-DD1
|
||||
MODE=0x010 SA-1
|
||||
MODE=0x020 SPC7110
|
||||
MODE=0x040 DX2 trick (might work with other SWC models)
|
||||
MODE=0x080 Mega Man X 2
|
||||
MODE=0x100 dump BIOS
|
||||
It is possible to combine flags. MODE=0x44 makes it possible
|
||||
to dump for example Yoshi's Island
|
||||
--xswcs send/receive SRAM to/from Super Wild Card*/SWC; --port=PORT
|
||||
receives automatically when SRAM does not exist
|
||||
--xswcc send/receive SRAM to/from cartridge in Super Wild Card*/SWC;
|
||||
--port=PORT
|
||||
receives automatically when SRAM does not exist
|
||||
--xswcr send/receive RTS data to/from Super Wild Card*/SWC; --port=PORT
|
||||
receives automatically when RTS file does not exist
|
||||
Game Doctor SF3(SF6/SF7)/Professor SF(SF II)
|
||||
--xgd3 send ROM to Game Doctor SF3/SF6/SF7; --port=PORT
|
||||
this option uses the Game Doctor SF3 protocol
|
||||
--xgd6 send ROM to Game Doctor SF6/SF7; --port=PORT
|
||||
this option uses the Game Doctor SF6 protocol
|
||||
--xgd3s send SRAM to Game Doctor SF3/SF6/SF7; --port=PORT
|
||||
--xgd6s send/receive SRAM to/from Game Doctor SF6/SF7; --port=PORT
|
||||
receives automatically when SRAM does not exist
|
||||
--xgd6r send/receive saver (RTS) data to/from Game Doctor SF6/SF7;
|
||||
--port=PORT
|
||||
receives automatically when saver file does not exist
|
||||
Super Pro Fighter (Q/Q+)/Pro Fighter X (Turbo 2)/Double Pro Fighter (X Turbo)
|
||||
--xfig send/receive ROM to/from *Pro Fighter*/FIG; --port=PORT
|
||||
receives automatically when ROM does not exist
|
||||
--xfigs send/receive SRAM to/from *Pro Fighter*/FIG; --port=PORT
|
||||
receives automatically when SRAM does not exist
|
||||
--xfigc send/receive SRAM to/from cartridge in *Pro Fighter*/FIG;
|
||||
--port=PORT
|
||||
receives automatically when SRAM does not exist
|
||||
Super Flash flash card programmer
|
||||
--xsf send/receive ROM to/from Super Flash flash card programmer
|
||||
--port=PORT
|
||||
receives automatically (64 Mbits) when ROM does not exist
|
||||
--xsfs send/receive SRAM to/from Super Flash flash card programmer
|
||||
--port=PORT
|
||||
receives automatically when SRAM does not exist
|
||||
|
||||
Neo Geo/Neo Geo CD(Z)/MVS
|
||||
--ng force recognition
|
||||
--bios=BIOS convert NeoCD BIOS to work with NeoCD emulator
|
||||
--sam=SAMFILE convert SAM/M.A.M.E. sound to WAV
|
||||
|
||||
Genesis/Sega Mega Drive/Sega CD/32X/Nomad
|
||||
--gen force recognition
|
||||
--int force ROM is in interleaved format (SMD)
|
||||
--int2 force ROM is in interleaved format 2 (MGD)
|
||||
--nint force ROM is not in interleaved format (BIN/RAW)
|
||||
-n=NEW_NAME change foreign ROM name to NEW_NAME
|
||||
--n2=NEW_NAME change Japanese ROM name to NEW_NAME
|
||||
--smd convert to Super Magic Drive/SMD
|
||||
--smds convert emulator (*.srm) SRAM to Super Magic Drive/SMD
|
||||
--bin convert to Magicom/BIN/RAW
|
||||
--mgd convert to Multi Game*/MGD2/MGH
|
||||
--stp convert SRAM from backup unit for use with an emulator
|
||||
--stp just strips the first 512 bytes
|
||||
-j join split ROM
|
||||
-s split ROM; default part size is 8 Mb (4 Mb for SMD)
|
||||
--ssize=SIZE specify split part size in Mbit
|
||||
-f remove NTSC/PAL protection
|
||||
--chk fix ROM checksum
|
||||
--1991 fix old third party ROMs to work with consoles build after
|
||||
October 1991 by inserting "(C) SEGA" and "(C)SEGA"
|
||||
--multi=SIZE make multi-game file for use with MD-PRO flash card, truncated
|
||||
to SIZE Mbit; file with loader must be specified first, then
|
||||
all the ROMs, multi-game file to create last
|
||||
--region=CODE enable region function; use with -multi
|
||||
CODE=0 force NTSC/Japan for all games
|
||||
CODE=1 force NTSC/U.S.A. for all games
|
||||
CODE=2 force PAL for all games
|
||||
CODE=x use whatever setting games expect
|
||||
Super Com Pro/Super Magic Drive/SMD
|
||||
--xsmd send/receive ROM to/from Super Magic Drive/SMD; --port=PORT
|
||||
receives automatically when ROM does not exist
|
||||
--xsmds send/receive SRAM to/from Super Magic Drive/SMD; --port=PORT
|
||||
receives automatically when SRAM does not exist
|
||||
MD-PRO flash card programmer
|
||||
--xmd send/receive ROM to/from MD-PRO flash card programmer
|
||||
--port=PORT
|
||||
receives automatically (32/64 Mbits) when ROM does not exist
|
||||
--xmds send/receive SRAM to/from MD-PRO flash card programmer
|
||||
--port=PORT
|
||||
receives automatically when SRAM does not exist
|
||||
--xmdb=BANK send/receive SRAM to/from MD-PRO BANK
|
||||
BANK can be a number from 1 to 4; --port=PORT
|
||||
receives automatically when SRAM does not exist
|
||||
Mike Pavone's Genesis/Sega CD transfer cable
|
||||
--xmcd receive ROM from Genesis/Sega CD; --port=PORT
|
||||
Cyan's Megadrive ROM copier
|
||||
--xcmc receive ROM from Cyan's Megadrive ROM copier; --port=PORT
|
||||
--xcmct=TEST run test TEST
|
||||
TEST=1 burn-in reliability test (specify speed)
|
||||
TEST=2 testbench mode (experts only)
|
||||
--xcmcm=SPEED specify transfer speed
|
||||
SPEED=1 slow (debug)
|
||||
SPEED=2 medium
|
||||
SPEED=3 fast (default)
|
||||
SPEED=4 full speed (risky)
|
||||
|
||||
Game Boy/(Super GB)/GB Pocket/Color GB/(GB Advance)
|
||||
--gb force recognition
|
||||
-n=NEW_NAME change internal ROM name to NEW_NAME
|
||||
--logo restore ROM logo character data (offset: 0x104-0x134)
|
||||
--mgd convert to Multi Game*/MGD2/RAW
|
||||
--ssc convert to Super Smart Card/SSC
|
||||
--sgb convert from GB Xchanger/GB/GBC to Super Backup Card/GX/GBX
|
||||
--gbx convert from Super Backup Card/GX/GBX to GB Xchanger/GB/GBC
|
||||
--n2gb=NESROM KAMI's FC EMUlator (NES emulator);
|
||||
ROM should be KAMI's FC Emulator ROM image
|
||||
NESROM should contain 16 kB of PRG data and 8 kB of CHR data
|
||||
--chk fix ROM checksum
|
||||
Game Boy Xchanger/GBDoctor
|
||||
--xgbx send/receive ROM to/from GB Xchanger; --port=PORT
|
||||
receives automatically when ROM does not exist
|
||||
--xgbxs send/receive SRAM to/from GB Xchanger; --port=PORT
|
||||
receives automatically when SRAM does not exist
|
||||
--xgbxb=BANK send/receive 64 kbits SRAM to/from GB Xchanger BANK
|
||||
BANK can be a number from 0 to 15; --port=PORT
|
||||
receives automatically when ROM does not exist
|
||||
--xgbxm try to enable EPP mode, default is SPP mode
|
||||
Mad Catz Camera Link (Game Boy Camera)
|
||||
--xmccl receives from Mad Catz Camera Link; --port=PORT
|
||||
|
||||
Handy (prototype)/Lynx/Lynx II
|
||||
--lynx force recognition
|
||||
--lyx convert to LYX/RAW (strip 64 Bytes LNX header)
|
||||
--lnx convert to LNX (uses default values for the header);
|
||||
adjust the LNX header with the following options
|
||||
-n=NEW_NAME change internal ROM name to NEW_NAME (LNX only)
|
||||
--nrot set no rotation (LNX only)
|
||||
--rotl set rotation left (LNX only)
|
||||
--rotr set rotation right (LNX only)
|
||||
--b0=N change Bank0 kBytes size to N={0,64,128,256,512} (LNX only)
|
||||
--b1=N change Bank1 kBytes size to N={0,64,128,256,512} (LNX only)
|
||||
Lynxit (Lynx cartridge backup board)
|
||||
--xlit receive ROM from Lynxit interface; --port=PORT
|
||||
|
||||
PC-Engine (CD Unit/Core Grafx(II)/Shuttle/GT/LT/Super CDROM/DUO(-R(X)))
|
||||
Super Grafx/Turbo (Grafx(16)/CD/DUO/Express)
|
||||
--pce force recognition
|
||||
--int force ROM is in interleaved (bit-swapped) format
|
||||
--nint force ROM is not in interleaved (bit-swapped) format
|
||||
--msg convert to Magic Super Griffin/MSG
|
||||
--mgd convert to Multi Game Doctor*/MGD2/RAW
|
||||
--swap swap bits of all bytes in file (TurboGrafx-16 <-> PC-Engine)
|
||||
-f fix region protection
|
||||
--multi=SIZE make multi-game file for use with PCE-PRO flash card, truncated
|
||||
to SIZE Mbit; file with loader must be specified first, then
|
||||
all the ROMs, multi-game file to create last
|
||||
Magic Super Griffin/MSG
|
||||
--xmsg send/receive ROM to/from Magic Super Griffin/MSG; --port=PORT
|
||||
receives automatically when ROM does not exist
|
||||
PCE-PRO flash card programmer
|
||||
--xpce send/receive ROM to/from PCE-PRO flash card programmer
|
||||
--port=PORT
|
||||
receives automatically (32 Mbits) when ROM does not exist
|
||||
|
||||
Nintendo Entertainment System/NES/Famicom/Game Axe (Redant)
|
||||
--nes force recognition
|
||||
-n=NEW_NAME change internal ROM name to NEW_NAME (UNIF only)
|
||||
--unif convert to UNIF format/UNF (uses default values)
|
||||
--ines convert to iNES format/NES (uses default values)
|
||||
--ineshd extract iNES header from ROM (16 Bytes)
|
||||
-j join Pasofami/PRM/700/PRG/CHR/split ROM (Pasofami -> iNES)
|
||||
--pasofami convert to Pasofami/PRM/700/PRG/CHR
|
||||
-s convert/split to Pasofami/PRM/700/PRG/CHR (iNES -> Pasofami)
|
||||
--ffe convert to FFE format (Super Magic Card)
|
||||
--mapr=MAPR specify board name or mapper number for conversion options
|
||||
MAPR must be a board name for UNIF or a number for Pasofami
|
||||
and iNES
|
||||
--dint deinterleave ROM (regardless whether the ROM is interleaved)
|
||||
--ctrl=TYPE specify controller type (UNIF only)
|
||||
TYPE=0 regular joypad
|
||||
TYPE=1 zapper
|
||||
TYPE=2 R.O.B.
|
||||
TYPE=3 Arkanoid controller
|
||||
TYPE=4 powerpad
|
||||
TYPE=5 four-score adapter
|
||||
--ntsc specify TV standard is NTSC (UNIF only)
|
||||
--pal specify TV standard is PAL (UNIF only)
|
||||
--bat specify battery is present
|
||||
--nbat specify battery is not present
|
||||
--vram specify VRAM override (UNIF only)
|
||||
--nvram specify no VRAM override (UNIF only)
|
||||
--mirr=MTYPE specify mirroring type
|
||||
MTYPE=0 horizontal mirroring
|
||||
MTYPE=1 vertical mirroring
|
||||
MTYPE=2 mirror all pages from $2000 (UNIF only)
|
||||
MTYPE=3 mirror all pages from $2400 (UNIF only)
|
||||
MTYPE=4 four screens of VRAM
|
||||
MTYPE=5 mirroring controlled by mapper hardware (UNIF only)
|
||||
--cmnt=TEXT specify that TEXT should be used as comment (UNIF only)
|
||||
--dumpinfo=FILE use dumper info from FILE when converting to UNIF
|
||||
--fds convert Famicom Disk System file (diskimage) from FAM to FDS
|
||||
--fdsl list Famicom Disk System/FDS (diskimage) contents
|
||||
Super Magic Card
|
||||
--xsmc send ROM (in FFE format) to Super Magic Card; --port=PORT
|
||||
--xsmcr send/receive RTS data to/from Super Magic Card; --port=PORT
|
||||
receives automatically when RTS file does not exist
|
||||
|
||||
Sega Master System(II/III)/Game Gear (Handheld)
|
||||
--sms force recognition
|
||||
--int force ROM is in interleaved format (SMD)
|
||||
--nint force ROM is not in interleaved format (RAW)
|
||||
--mgd convert to Multi Game*/MGD2/MGH/RAW (gives SMS name)
|
||||
--mgdgg same as --mgd, but gives GG name
|
||||
--smd convert to Super Magic Drive/SMD
|
||||
--smds convert emulator (*.srm) SRAM to Super Magic Drive/SMD
|
||||
--chk fix ROM checksum (SMS only)
|
||||
--multi=SIZE make multi-game file for use with SMS-PRO/GG-PRO flash card,
|
||||
truncated to SIZE Mbit; file with loader must be specified
|
||||
first, then all the ROMs, multi-game file to create last
|
||||
SMS-PRO/GG-PRO flash card programmer
|
||||
--xgg send/receive ROM to/from SMS-PRO/GG-PRO flash card programmer
|
||||
--port=PORT
|
||||
receives automatically (32 Mbits) when ROM does not exist
|
||||
--xggs send/receive SRAM to/from SMS-PRO/GG-PRO flash card programmer
|
||||
--port=PORT
|
||||
receives automatically when SRAM does not exist
|
||||
--xggb=BANK send/receive SRAM to/from SMS-PRO/GG-PRO BANK
|
||||
BANK can be a number from 1 to 4; --port=PORT
|
||||
receives automatically when SRAM does not exist
|
||||
|
||||
WonderSwan/WonderSwan Color/SwanCrystal
|
||||
--swan force recognition
|
||||
--chk fix ROM checksum
|
||||
|
||||
Panther(32bit prototype)/Jaguar64/Jaguar64 CD
|
||||
--jag force recognition
|
||||
|
||||
Neo Geo Pocket/Neo Geo Pocket Color
|
||||
--ngp force recognition
|
||||
Pocket Linker
|
||||
--xpl send/receive ROM to/from Pocket Linker; --port=PORT
|
||||
receives automatically when ROM does not exist
|
||||
--xpli show information about inserted cartridge; --port=PORT
|
||||
--xplm try to enable EPP mode, default is SPP mode
|
||||
|
||||
Atari VCS 2600(aka Stella)/Atari 5200 SuperSystem/Atari CX7800/Atari 2600 Jr
|
||||
--ata force recognition
|
||||
|
||||
DATabase: 32626 known ROMs (DAT files: /mnt/hd2-1/home/daniel/.ucon64/dat)
|
||||
|
||||
NOTE: You only need to specify PORT if uCON64 doesn't detect the (right)
|
||||
parallel port. If that is the case give a hardware address. For example:
|
||||
ucon64 --xswc "rom.swc" --port=0x378
|
||||
In order to connect a copier to a PC's parallel port you need a standard
|
||||
bidirectional parallel cable
|
||||
|
||||
TIP: ucon64 --help --snes (would show only SNES related help)
|
||||
ucon64 --help|less (to see everything in less)
|
||||
Give the force recognition switch a try if something went wrong
|
||||
|
||||
Please report any problems/ideas/fixes to noisyb@gmx.net or
|
||||
ucon64-announce@lists.sf.net or visit http://ucon64.sf.net
|
||||
|
||||
</pre></tt></body></html>
|
||||
@@ -1,173 +0,0 @@
|
||||
..................
|
||||
...............: STANDARD CODES ::...............
|
||||
: :\
|
||||
: [a] Alternate [p] Pirate :\
|
||||
: [b] Bad Dump [t] Trained :\
|
||||
: [f] Fixed [T-] OldTranslation :\
|
||||
: [T+] NewerTranslation :\
|
||||
: [h] Hack (-) Unknown Year :\
|
||||
: [o] Overdump [!] Verified Good Dump :\
|
||||
: (M#) Multilanguage (# of Languages) :\
|
||||
: (###) Checksum (??k) ROM Size :\
|
||||
: ZZZ_ Unclassified (Unl) Unlicensed :\
|
||||
:...............................................:\
|
||||
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
||||
|
||||
.................
|
||||
................: SPECIAL CODES ::...............
|
||||
: :\
|
||||
: .-----Gameboy-----. .----Super Nintendo----. :\
|
||||
: [ [C] Color ] [ (BS) BS ROMs ] :\
|
||||
: [ [S] Super ] [ (ST) Sufami Turbo ] :\
|
||||
: [ [BF] Bung Fix ] [ (NP) Nintendo Power ] :\
|
||||
: `-----------------' `----------------------' :\
|
||||
: .--------Atari---------. :\
|
||||
: .-----Genesis-----. [ (PAL) Euro Version ] :\
|
||||
: [ (1) Japan ] `----------------------' :\
|
||||
: [ (4) USA ] .---------GBA----------. :\
|
||||
: [ (5) NTSC Only ] [ [hI??] Intro hacks ] :\
|
||||
: [ (8) PAL Only ] `----------------------' :\
|
||||
: [ (B) non USA ] .--------Coleco--------. :\
|
||||
: [ [c] Checksum ] [ (Adam) ADAM Version ] :\
|
||||
: [ [x] Bad Checksum] `----------------------' :\
|
||||
: [ [R-] Countries ] :\
|
||||
: `-----------------' :\
|
||||
: .--------NES/FC--------. :\
|
||||
: .--NeoGeo Pocket--. [ (PC10) PlayChoice 10 ] :\
|
||||
: [ [M] Mono Only ] [ (VS) Versus ] :\
|
||||
: `-----------------' [ [hFFE] FFE Copier fmt] :\
|
||||
: `----------------------' :\
|
||||
:...............................................:\
|
||||
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
||||
|
||||
.................
|
||||
................: COUNTRY CODES ::...............
|
||||
: :\
|
||||
: (1) Japan & Korea (4) USA & BrazilNTSC :\
|
||||
: (A) Australia (J) Japan :\
|
||||
: (B) non USA (Genesis) (K) Korea :\
|
||||
: (C) China (NL) Netherlands :\
|
||||
: (E) Europe (PD) Public Domain :\
|
||||
: (F) France (S) Spain :\
|
||||
: (F) World (Genesis) :\
|
||||
: (FC) French Canadian (SW) Sweden :\
|
||||
: (FN) Finland (U) USA :\
|
||||
: (G) Germany (UK) England :\
|
||||
: (GR) Greece (Unk) Unknown Country :\
|
||||
: (HK) Hong Kong (I) Italy :\
|
||||
: (H) Holland (Unl) Unlicensed :\
|
||||
:...............................................:\
|
||||
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
||||
|
||||
.......................
|
||||
.............: STANDARD CODE NOTES ::............
|
||||
: :\
|
||||
: [a] This is simply an alternate version of a :\
|
||||
: ROM. Many games have been re-released to :\
|
||||
: fix bugs or even to eliminate Game Genie :\
|
||||
: codes (Yes, Nintendo hates that device). :\
|
||||
: ------------------- :\
|
||||
: [b] A bad dump often occurs with an older :\
|
||||
: game or a faulty dumper (bad connection). :\
|
||||
: Another common source of [b] ROMs is a :\
|
||||
: corrupted upload to a release FTP. :\
|
||||
: ------------------- :\
|
||||
: [f] A fixed game has been altered in some way :\
|
||||
: so that it will run better on a copier :\
|
||||
: or emulator. :\
|
||||
: ------------------- :\
|
||||
: [h] Something in this ROM is not quite as it :\
|
||||
: should be. Often a hacked ROM simply has :\
|
||||
: a changed header or has been enabled to :\
|
||||
: run in different regions. Other times it :\
|
||||
: could be a release group intro, or just :\
|
||||
: some kind of cheating or funny hack. :\
|
||||
: ------------------- :\
|
||||
: [o] An overdumped ROM image has more data :\
|
||||
: than is actually in the cart. The extra :\
|
||||
: information means nothing and is removed :\
|
||||
: from the true image. :\
|
||||
: ------------------- :\
|
||||
: [t] A trainer is special code which executes :\
|
||||
: before the game is begun. It allows you :\
|
||||
: to access cheats from a menu. :\
|
||||
: ------------------- :\
|
||||
: [!] Verified good dump. Thank God for these! :\
|
||||
:...............................................:\
|
||||
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
||||
|
||||
......................
|
||||
.............: SPECIAL CODE NOTES ::.............
|
||||
: :\
|
||||
: **** SNES **** :\
|
||||
: (BS) These Japanese ROMs were distributed :\
|
||||
: through a satellite system in Japan :\
|
||||
: known as the Broadcast Satellaview. :\
|
||||
: They were transmitted along with a TV :\
|
||||
: show which was connected to the game in :\
|
||||
: some way. These games were only playable :\
|
||||
: during the show, and thus stop after an :\
|
||||
: hour, and many were timed so that only :\
|
||||
: certain time periods were playable. :\
|
||||
: ------------------- :\
|
||||
: (ST) The Sufami Turbo device allowed two :\
|
||||
: GameBoy sized carts to be plugged into :\
|
||||
: the SNES. Certain carts combined into :\
|
||||
: new games much like the Sonic & Knuckles :\
|
||||
: lock-on technology by Sega. :\
|
||||
: ------------------- :\
|
||||
: (NP) Nintendo Power has been known to release :\
|
||||
: games only available to its subscribers. :\
|
||||
: Most of these ROMs are Japanese, as this :\
|
||||
: practice occured mainly in Japan. :\
|
||||
: ------------------- :\
|
||||
: :\
|
||||
: **** Genesis **** :\
|
||||
: (1) Carts with this code will run on both :\
|
||||
: Japanese and Korean machines. :\
|
||||
: ------------------- :\
|
||||
: (4) While this code is technically the same :\
|
||||
: as a (U) code, it is a newer header :\
|
||||
: format and represents that the cart will :\
|
||||
: run on USA and Brazil NTSC machines. :\
|
||||
: ------------------- :\
|
||||
: (B) This country code indicates that the :\
|
||||
: cart will run on any non US machine. :\
|
||||
: ------------------- :\
|
||||
: [c] This code represents a cart with known :\
|
||||
: faulty checksum routines. :\
|
||||
: ------------------- :\
|
||||
: :\
|
||||
: **** GameBoy **** :\
|
||||
: [BF] Bung released a programmable cartridge :\
|
||||
: compatable with the GameBoy which could :\
|
||||
: hold any data you wished to play. :\
|
||||
: However, many games do not function on :\
|
||||
: Bung v1.0 carts and have to be 'fixed.' :\
|
||||
: ------------------- :\
|
||||
: :\
|
||||
: **** Nintendo **** :\
|
||||
: PC10 The PlayChoice 10 was an arcade unit :\
|
||||
: which played exact copies of NES games :\
|
||||
: in an arcade cabinet. The machines had a :\
|
||||
: choice of 10 games to choose from and :\
|
||||
: ran for about 3 minutes on 25 cents. :\
|
||||
: ------------------- :\
|
||||
: :\
|
||||
: VS The Versus system ran on similar hard- :\
|
||||
: ware to the PC10 machines, but simply :\
|
||||
: allowed you to play against each other. :\
|
||||
:...............................................:\
|
||||
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
||||
|
||||
...........
|
||||
...................: Credits ::..................
|
||||
: :\
|
||||
: Document written by Psych0phobiA / q^-o|o-^p :\
|
||||
: :\
|
||||
: All codes developed by Cowering for the :\
|
||||
: Goodxxxx series ROM file renaming utilities. :\
|
||||
: :\
|
||||
: Visit #rareroms on NewNet in IRC! :\
|
||||
:...............................................:\
|
||||
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
||||
@@ -1,380 +0,0 @@
|
||||
.PHONY: all clean distclean install uninstall
|
||||
|
||||
@DEFINE_DLOPEN_MAKE@
|
||||
@DEFINE_ZLIB_MAKE@
|
||||
@DEFINE_DISCMAGE_MAKE@
|
||||
@DEFINE_USB_MAKE@
|
||||
@DEFINE_LIBCD64_MAKE@
|
||||
|
||||
CC=@CC@
|
||||
CFLAGS=-I. -Wall -W -O3 @DEFS@
|
||||
LDFLAGS=-s
|
||||
TARGETS=
|
||||
|
||||
ifdef USE_DISCMAGE
|
||||
LIBNAME_DM=discmage
|
||||
endif
|
||||
|
||||
# The test for Cygwin should be done before the test for DJGPP, because the
|
||||
# environment variable DJGPP can be set under Bash for people who have
|
||||
# installed both GCC (and friends) ports.
|
||||
|
||||
GCC_WIN=0
|
||||
# test cygwin before DJGPP; OSTYPE is not exported on Cygwin
|
||||
ifeq ($(TERM),cygwin)
|
||||
GCC_WIN=1
|
||||
endif
|
||||
# test msys before DJGPP; MSYS, MinGW's POSIX build environment
|
||||
ifeq ($(OSTYPE),msys)
|
||||
GCC_WIN=1
|
||||
endif
|
||||
|
||||
ifeq ($(GCC_WIN),1)
|
||||
|
||||
ifdef USE_DISCMAGE
|
||||
FULLLIBNAME_DM=$(LIBNAME_DM).dll
|
||||
ifndef DLOPEN
|
||||
LDFLAGS+=libdiscmage/$(LIBNAME_DM).a
|
||||
endif
|
||||
endif
|
||||
|
||||
else
|
||||
ifdef DJGPP
|
||||
|
||||
ifdef USE_DISCMAGE
|
||||
FULLLIBNAME_DM=$(LIBNAME_DM).dxe
|
||||
ifndef DLOPEN
|
||||
LDFLAGS+=libdiscmage/$(LIBNAME_DM).a
|
||||
endif
|
||||
endif
|
||||
|
||||
else # Unix, BeOS or Mac OS X (Darwin)
|
||||
|
||||
ifeq ($(findstring openbsd,$(OSTYPE)),openbsd) # for example "openbsd3.4"
|
||||
# i386_iopl() is located in libi386.a
|
||||
LDFLAGS+=@LIBI386_MAKE@
|
||||
endif
|
||||
|
||||
ifdef USE_DISCMAGE
|
||||
ifeq ($(findstring darwin,$(OSTYPE)),darwin) # for example "darwin7.0"
|
||||
FULLLIBNAME_DM=$(LIBNAME_DM).dylib
|
||||
else
|
||||
FULLLIBNAME_DM=$(LIBNAME_DM).so
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef DLOPEN
|
||||
|
||||
ifneq ($(OSTYPE),beos)
|
||||
ifeq ($(findstring freebsd,$(OSTYPE)),) # false if OSTYPE contains "freebsd"
|
||||
ifeq ($(findstring openbsd,$(OSTYPE)),) # false if OSTYPE contains "openbsd"
|
||||
LDFLAGS+=-ldl
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
else # DLOPEN
|
||||
ifdef USE_DISCMAGE # GNU specific: "simply expanded variable"
|
||||
FULLLIBNAME_DM:=$(addprefix lib,$(FULLLIBNAME_DM))
|
||||
LDFLAGS+=-Llibdiscmage -l$(LIBNAME_DM)
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
endif # DJGPP
|
||||
endif # GCC_WIN
|
||||
|
||||
TARGETS+=libdiscmage/$(FULLLIBNAME_DM)
|
||||
|
||||
|
||||
ifdef USE_LIBCD64
|
||||
LDFLAGS+=backup/libcd64/libcd64.a
|
||||
TARGETS+=backup/libcd64/libcd64.a
|
||||
endif
|
||||
|
||||
|
||||
OBJECTS=ucon64.o ucon64_dat.o ucon64_misc.o ucon64_opts.o \
|
||||
misc/chksum.o misc/file.o misc/getopt.o misc/getopt2.o \
|
||||
misc/misc.o misc/parallel.o misc/property.o misc/string.o \
|
||||
patch/aps.o patch/bsl.o patch/gg.o patch/ips.o patch/pal4u.o \
|
||||
patch/ppf.o patch/xps.o \
|
||||
console/dc.o console/gb.o console/gba.o console/genesis.o \
|
||||
console/jaguar.o console/lynx.o console/n64.o console/neogeo.o \
|
||||
console/nes.o console/ngp.o console/pce.o console/psx.o console/sms.o \
|
||||
console/snes.o console/swan.o \
|
||||
backup/cd64.o backup/cmc.o backup/dex.o backup/doctor64.o \
|
||||
backup/doctor64jr.o backup/f2a.o backup/fal.o backup/ffe.o \
|
||||
backup/fig.o backup/gbx.o backup/gd.o backup/interceptor.o \
|
||||
backup/lynxit.o backup/mccl.o backup/mcd.o backup/md-pro.o \
|
||||
backup/mgd.o backup/msg.o backup/pce-pro.o backup/pl.o \
|
||||
backup/psxpblib.o backup/sflash.o backup/smc.o backup/smd.o \
|
||||
backup/smsgg-pro.o backup/ssc.o backup/swc.o backup/tototek.o \
|
||||
backup/ufo.o backup/yoko.o backup/z64.o
|
||||
ifdef USE_ZLIB
|
||||
LDFLAGS+=-lz
|
||||
OBJECTS+=misc/archive.o misc/map.o misc/unzip.o
|
||||
endif
|
||||
ifdef USE_USB
|
||||
LDFLAGS+=-lusb
|
||||
OBJECTS+=misc/usb.o
|
||||
endif
|
||||
|
||||
ifdef DLOPEN
|
||||
OBJECTS+=misc/dlopen.o
|
||||
ifndef USE_ZLIB
|
||||
ifeq ($(GCC_WIN),1)
|
||||
else
|
||||
ifdef DJGPP # DJGPP code in dlopen needs map code
|
||||
OBJECTS+=misc/map.o
|
||||
endif # DJGPP
|
||||
endif # GCC_WIN
|
||||
endif # USE_ZLIB
|
||||
else
|
||||
ifeq ($(GCC_WIN),1) # Cygwin/MinGW code in ucon64_misc needs dlopen code
|
||||
OBJECTS+=misc/dlopen.o
|
||||
endif # GCC_WIN
|
||||
endif # DLOPEN
|
||||
|
||||
|
||||
TARGET=ucon64
|
||||
ifeq ($(GCC_WIN),1)
|
||||
TARGET:=$(addsuffix .exe,$(TARGET)) # adding .exe avoids "problems" with Cygwin/MinGW
|
||||
else
|
||||
ifdef DJGPP # OSTYPE is not defined by default under DOS
|
||||
TARGET:=$(addsuffix .exe,$(TARGET))
|
||||
endif # DJGPP
|
||||
endif # GCC_WIN
|
||||
TARGETS+=$(TARGET)
|
||||
|
||||
all: $(TARGETS)
|
||||
|
||||
|
||||
CLEAN_CMD=rm -f $(TARGET) $(OBJECTS) *.core *.stackdump *~ */*~ */*/*~; \
|
||||
cd libdiscmage && $(MAKE) clean; \
|
||||
cd ../backup/libcd64 && $(MAKE) clean
|
||||
|
||||
clean:
|
||||
ifeq ($(GCC_WIN),1)
|
||||
$(CLEAN_CMD)
|
||||
else
|
||||
ifdef DJGPP
|
||||
del *.o
|
||||
del patch\*.o
|
||||
del console\*.o
|
||||
del backup\*.o
|
||||
del misc\*.o
|
||||
del $(TARGET)
|
||||
cd libdiscmage
|
||||
$(MAKE) clean
|
||||
cd ../backup/libcd64
|
||||
$(MAKE) clean
|
||||
cd ../..
|
||||
else # Unix, BeOS or Mac OS X (Darwin)
|
||||
$(CLEAN_CMD)
|
||||
endif # DJGPP
|
||||
endif # GCC_WIN
|
||||
|
||||
|
||||
DISTCLEAN_CMD=rm -f Makefile config.log config.status config.cache config.h; \
|
||||
cd libdiscmage && $(MAKE) distclean; \
|
||||
cd ../backup/libcd64 && $(MAKE) clean
|
||||
# libcd64 Makefile has no distclean target
|
||||
|
||||
distclean: clean
|
||||
ifeq ($(GCC_WIN),1)
|
||||
$(DISTCLEAN_CMD)
|
||||
else
|
||||
ifdef DJGPP
|
||||
del Makefile
|
||||
del config.log
|
||||
del config.status
|
||||
del config.cache
|
||||
del config.h
|
||||
cd libdiscmage
|
||||
$(MAKE) distclean
|
||||
cd ../backup/libcd64
|
||||
$(MAKE) clean
|
||||
cd ../..
|
||||
else
|
||||
$(DISTCLEAN_CMD)
|
||||
endif # DJGPP
|
||||
endif # GCC_WIN
|
||||
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
backup/cd64.o: backup/cd64.c
|
||||
$(CC) $(CFLAGS) -Ibackup/libcd64 -c $< -o $@
|
||||
|
||||
|
||||
ifdef USE_DISCMAGE
|
||||
libdiscmage/$(FULLLIBNAME_DM):
|
||||
ifeq ($(GCC_WIN),1)
|
||||
cd libdiscmage && $(MAKE)
|
||||
else
|
||||
ifdef DJGPP
|
||||
cd libdiscmage
|
||||
$(MAKE)
|
||||
cd ..
|
||||
else
|
||||
cd libdiscmage && $(MAKE)
|
||||
endif # DJGPP
|
||||
endif # GCC_WIN
|
||||
endif # USE_DISCMAGE
|
||||
|
||||
ifdef USE_LIBCD64
|
||||
backup/libcd64/libcd64.a:
|
||||
ifeq ($(GCC_WIN),1)
|
||||
cd backup/libcd64 && $(MAKE)
|
||||
else
|
||||
ifdef DJGPP
|
||||
cd backup/libcd64
|
||||
$(MAKE)
|
||||
cd ../..
|
||||
else
|
||||
cd backup/libcd64 && $(MAKE)
|
||||
endif # DJGPP
|
||||
endif # GCC_WIN
|
||||
endif # USE_DISCMAGE
|
||||
|
||||
$(TARGET): $(OBJECTS)
|
||||
$(CC) $(OBJECTS) $(LDFLAGS) -o $@
|
||||
|
||||
|
||||
install:
|
||||
ifeq ($(TERM),cygwin) # test cygwin before DJGPP
|
||||
else
|
||||
ifeq ($(OSTYPE),msys) # test msys before DJGPP
|
||||
else
|
||||
ifdef DJGPP
|
||||
else
|
||||
ifeq ($(OSTYPE),beos)
|
||||
./install_beos.sh
|
||||
else
|
||||
./install.sh
|
||||
endif # beos
|
||||
endif # DJGPP
|
||||
endif # msys
|
||||
endif # cygwin
|
||||
ifndef DLOPEN
|
||||
cd libdiscmage && $(MAKE) install
|
||||
endif
|
||||
|
||||
|
||||
uninstall:
|
||||
ifeq ($(TERM),cygwin) # test cygwin before DJGPP
|
||||
else
|
||||
ifeq ($(OSTYPE),msys) # test msys before DJGPP
|
||||
else
|
||||
ifdef DJGPP
|
||||
else
|
||||
ifeq ($(OSTYPE),beos)
|
||||
rm -f $(HOME)/config/bin/$(TARGET)
|
||||
else
|
||||
rm -f /usr/local/bin/$(TARGET)
|
||||
endif # beos
|
||||
endif # DJGPP
|
||||
endif # msys
|
||||
endif # cygwin
|
||||
ifndef DLOPEN
|
||||
cd libdiscmage && $(MAKE) uninstall
|
||||
endif
|
||||
|
||||
|
||||
# Dependencies
|
||||
|
||||
# Most source files include these
|
||||
UCON64_STD_H=ucon64.h ucon64_misc.h misc/misc.h config.h ucon64_defines.h
|
||||
|
||||
misc/archive.o: misc/archive.h misc/map.h config.h
|
||||
misc/chksum.o: misc/chksum.h config.h
|
||||
misc/dlopen.o: misc/dlopen.h misc/dxedll_pub.h config.h
|
||||
misc/getopt.o: misc/getopt.h
|
||||
misc/map.o: misc/map.h config.h
|
||||
misc/misc.o: misc/misc.h misc/archive.h config.h
|
||||
misc/parallel.o: misc/parallel.h config.h
|
||||
misc/usb.o: misc/usb.h config.h
|
||||
misc/unzip.o: misc/unzip.h config.h
|
||||
ucon64.o: misc/dlopen.h misc/getopt.h ucon64_dat.h ucon64_opts.h \
|
||||
console/dc.h console/gb.h console/gba.h console/genesis.h \
|
||||
console/jaguar.h console/lynx.h console/n64.h console/neogeo.h \
|
||||
console/nes.h console/ngp.h console/pce.h console/psx.h console/sms.h \
|
||||
console/snes.h console/swan.h \
|
||||
backup/cd64.h backup/dex.h backup/doctor64.h backup/doctor64jr.h \
|
||||
backup/f2a.h backup/fal.h backup/ffe.h backup/fig.h backup/gbx.h \
|
||||
backup/gd.h backup/interceptor.h backup/lynxit.h backup/mccl.h \
|
||||
backup/mcd.h backup/md-pro.h backup/mgd.h backup/msg.h \
|
||||
backup/pce-pro.h backup/pl.h backup/smc.h backup/smd.h \
|
||||
backup/smsgg-pro.h backup/ssc.h backup/swc.h backup/tototek.h \
|
||||
backup/ufo.h backup/yoko.h backup/z64.h \
|
||||
patch/aps.h patch/bsl.h patch/gg.h patch/ips.h patch/pal4u.h \
|
||||
patch/ppf.h patch/xps.h $(UCON64_STD_H)
|
||||
ucon64_dat.o: ucon64_dat.h $(UCON64_STD_H)
|
||||
ucon64_misc.o: misc/dlopen.h $(UCON64_STD_H)
|
||||
ucon64_opts.o: misc/dlopen.h misc/getopt.h ucon64_dat.h ucon64_opts.h \
|
||||
console/dc.h console/gb.h console/gba.h console/genesis.h \
|
||||
console/jaguar.h console/lynx.h console/n64.h console/neogeo.h \
|
||||
console/nes.h console/ngp.h console/pce.h console/psx.h \
|
||||
console/sms.h console/snes.h console/swan.h \
|
||||
backup/cd64.h backup/dex.h backup/doctor64.h \
|
||||
backup/doctor64jr.h backup/f2a.h backup/fal.h backup/ffe.h \
|
||||
backup/fig.h backup/gbx.h backup/gd.h backup/interceptor.h \
|
||||
backup/lynxit.h backup/mccl.h backup/mcd.h backup/md-pro.h \
|
||||
backup/mgd.h backup/msg.h backup/pce-pro.h backup/pl.h \
|
||||
backup/smc.h backup/smd.h backup/smsgg-pro.h backup/ssc.h \
|
||||
backup/swc.h backup/tototek.h backup/ufo.h backup/yoko.h \
|
||||
backup/z64.h \
|
||||
patch/aps.h patch/bsl.h patch/gg.h patch/ips.h patch/pal4u.h \
|
||||
patch/ppf.h patch/xps.h $(UCON64_STD_H)
|
||||
console/dc.o: console/dc.h $(UCON64_STD_H)
|
||||
console/gb.o: console/gb.h backup/mgd.h $(UCON64_STD_H)
|
||||
console/gba.o: console/gba.h $(UCON64_STD_H)
|
||||
console/genesis.o: console/genesis.h backup/smd.h backup/mgd.h $(UCON64_STD_H)
|
||||
console/jaguar.o: console/jaguar.h $(UCON64_STD_H)
|
||||
console/lynx.o: console/lynx.h $(UCON64_STD_H)
|
||||
console/n64.o: console/n64.h $(UCON64_STD_H)
|
||||
console/neogeo.o: console/neogeo.h $(UCON64_STD_H)
|
||||
console/nes.o: console/nes.h $(UCON64_STD_H)
|
||||
console/ngp.o: console/ngp.h $(UCON64_STD_H)
|
||||
console/pce.o: console/pce.h backup/mgd.h $(UCON64_STD_H)
|
||||
console/psx.o: console/psx.h $(UCON64_STD_H)
|
||||
console/sms.o: console/sms.h backup/smd.h backup/mgd.h $(UCON64_STD_H)
|
||||
console/snes.o: console/snes.h backup/mgd.h $(UCON64_STD_H)
|
||||
console/swan.o: console/swan.h $(UCON64_STD_H)
|
||||
backup/cd64.o: backup/cd64.h $(UCON64_STD_H)
|
||||
backup/cmc.o: backup/cmc.h $(UCON64_STD_H)
|
||||
backup/dex.o: backup/dex.h backup/psxpblib.h $(UCON64_STD_H)
|
||||
backup/doctor64.o: backup/doctor64.h $(UCON64_STD_H)
|
||||
backup/doctor64jr.o: backup/doctor64jr.h $(UCON64_STD_H)
|
||||
backup/f2a.o: backup/f2a.h $(UCON64_STD_H)
|
||||
backup/fal.o: backup/fal.h backup/cartlib.c $(UCON64_STD_H)
|
||||
backup/ffe.o: backup/ffe.h $(UCON64_STD_H)
|
||||
backup/fig.o: backup/fig.h console/snes.h $(UCON64_STD_H)
|
||||
backup/gd.o: backup/gd.h console/snes.h $(UCON64_STD_H)
|
||||
backup/gbx.o: backup/gbx.h $(UCON64_STD_H)
|
||||
backup/lynxit.o: backup/lynxit.h $(UCON64_STD_H)
|
||||
backup/mccl.o: backup/mccl.h $(UCON64_STD_H)
|
||||
backup/mcd.o: backup/mcd.h $(UCON64_STD_H)
|
||||
backup/md-pro.o: backup/md-pro.h backup/tototek.h $(UCON64_STD_H)
|
||||
backup/mgd.o: backup/mgd.h $(UCON64_STD_H)
|
||||
backup/msg.o: backup/msg.h backup/ffe.h $(UCON64_STD_H)
|
||||
backup/pce-pro.o: backup/pce-pro.h backup/tototek.h $(UCON64_STD_H)
|
||||
backup/pl.o: backup/pl.h $(UCON64_STD_H)
|
||||
backup/psxpblib.o: backup/psxpblib.h $(UCON64_STD_H)
|
||||
backup/sflash.o: backup/sflash.h backup/tototek.h $(UCON64_STD_H)
|
||||
backup/smc.o: backup/smc.h backup/ffe.h $(UCON64_STD_H)
|
||||
backup/smd.o: backup/smd.h backup/ffe.h $(UCON64_STD_H)
|
||||
backup/smsgg-pro.o: backup/smsgg-pro.h backup/tototek.h $(UCON64_STD_H)
|
||||
backup/swc.o: backup/swc.h backup/ffe.h console/snes.h $(UCON64_STD_H)
|
||||
backup/tototek.o: backup/tototek.h $(UCON64_STD_H)
|
||||
backup/ufo.o: backup/ufo.h $(UCON64_STD_H)
|
||||
backup/yoko.o: backup/yoko.h $(UCON64_STD_H)
|
||||
backup/z64.o: backup/z64.h $(UCON64_STD_H)
|
||||
patch/aps.o: patch/aps.h $(UCON64_STD_H)
|
||||
patch/bsl.o: patch/bsl.h $(UCON64_STD_H)
|
||||
patch/gg.o: patch/gg.h $(UCON64_STD_H)
|
||||
patch/ips.o: patch/ips.h $(UCON64_STD_H)
|
||||
patch/pal4u.o: patch/pal4u.h $(UCON64_STD_H)
|
||||
patch/ppf.o: patch/ppf.h $(UCON64_STD_H)
|
||||
patch/xps.o: patch/xps.h $(UCON64_STD_H)
|
||||
@@ -1,380 +0,0 @@
|
||||
.PHONY: all clean distclean install uninstall
|
||||
|
||||
DLOPEN=1
|
||||
#USE_ZLIB=1
|
||||
USE_DISCMAGE=1
|
||||
#USE_USB=1
|
||||
USE_LIBCD64=1
|
||||
|
||||
CC=gcc
|
||||
CFLAGS=-I. -Wall -W -O3 -DHAVE_CONFIG_H
|
||||
LDFLAGS=-s
|
||||
TARGETS=
|
||||
|
||||
ifdef USE_DISCMAGE
|
||||
LIBNAME_DM=discmage
|
||||
endif
|
||||
|
||||
# The test for Cygwin should be done before the test for DJGPP, because the
|
||||
# environment variable DJGPP can be set under Bash for people who have
|
||||
# installed both GCC (and friends) ports.
|
||||
|
||||
GCC_WIN=0
|
||||
# test cygwin before DJGPP; OSTYPE is not exported on Cygwin
|
||||
ifeq ($(TERM),cygwin)
|
||||
GCC_WIN=1
|
||||
endif
|
||||
# test msys before DJGPP; MSYS, MinGW's POSIX build environment
|
||||
ifeq ($(OSTYPE),msys)
|
||||
GCC_WIN=1
|
||||
endif
|
||||
|
||||
ifeq ($(GCC_WIN),1)
|
||||
|
||||
ifdef USE_DISCMAGE
|
||||
FULLLIBNAME_DM=$(LIBNAME_DM).dll
|
||||
ifndef DLOPEN
|
||||
LDFLAGS+=libdiscmage/$(LIBNAME_DM).a
|
||||
endif
|
||||
endif
|
||||
|
||||
else
|
||||
ifdef DJGPP
|
||||
|
||||
ifdef USE_DISCMAGE
|
||||
FULLLIBNAME_DM=$(LIBNAME_DM).dxe
|
||||
ifndef DLOPEN
|
||||
LDFLAGS+=libdiscmage/$(LIBNAME_DM).a
|
||||
endif
|
||||
endif
|
||||
|
||||
else # Unix, BeOS or Mac OS X (Darwin)
|
||||
|
||||
ifeq ($(findstring openbsd,$(OSTYPE)),openbsd) # for example "openbsd3.4"
|
||||
# i386_iopl() is located in libi386.a
|
||||
LDFLAGS+=
|
||||
endif
|
||||
|
||||
ifdef USE_DISCMAGE
|
||||
ifeq ($(findstring darwin,$(OSTYPE)),darwin) # for example "darwin7.0"
|
||||
FULLLIBNAME_DM=$(LIBNAME_DM).dylib
|
||||
else
|
||||
FULLLIBNAME_DM=$(LIBNAME_DM).so
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef DLOPEN
|
||||
|
||||
ifneq ($(OSTYPE),beos)
|
||||
ifeq ($(findstring freebsd,$(OSTYPE)),) # false if OSTYPE contains "freebsd"
|
||||
ifeq ($(findstring openbsd,$(OSTYPE)),) # false if OSTYPE contains "openbsd"
|
||||
LDFLAGS+=-ldl
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
else # DLOPEN
|
||||
ifdef USE_DISCMAGE # GNU specific: "simply expanded variable"
|
||||
FULLLIBNAME_DM:=$(addprefix lib,$(FULLLIBNAME_DM))
|
||||
LDFLAGS+=-Llibdiscmage -l$(LIBNAME_DM)
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
endif # DJGPP
|
||||
endif # GCC_WIN
|
||||
|
||||
TARGETS+=libdiscmage/$(FULLLIBNAME_DM)
|
||||
|
||||
|
||||
ifdef USE_LIBCD64
|
||||
LDFLAGS+=backup/libcd64/libcd64.a
|
||||
TARGETS+=backup/libcd64/libcd64.a
|
||||
endif
|
||||
|
||||
|
||||
OBJECTS=ucon64.o ucon64_dat.o ucon64_misc.o ucon64_opts.o \
|
||||
misc/chksum.o misc/file.o misc/getopt.o misc/getopt2.o \
|
||||
misc/misc.o misc/parallel.o misc/property.o misc/string.o \
|
||||
patch/aps.o patch/bsl.o patch/gg.o patch/ips.o patch/pal4u.o \
|
||||
patch/ppf.o patch/xps.o \
|
||||
console/dc.o console/gb.o console/gba.o console/genesis.o \
|
||||
console/jaguar.o console/lynx.o console/n64.o console/neogeo.o \
|
||||
console/nes.o console/ngp.o console/pce.o console/psx.o console/sms.o \
|
||||
console/snes.o console/swan.o \
|
||||
backup/cd64.o backup/cmc.o backup/dex.o backup/doctor64.o \
|
||||
backup/doctor64jr.o backup/f2a.o backup/fal.o backup/ffe.o \
|
||||
backup/fig.o backup/gbx.o backup/gd.o backup/interceptor.o \
|
||||
backup/lynxit.o backup/mccl.o backup/mcd.o backup/md-pro.o \
|
||||
backup/mgd.o backup/msg.o backup/pce-pro.o backup/pl.o \
|
||||
backup/psxpblib.o backup/sflash.o backup/smc.o backup/smd.o \
|
||||
backup/smsgg-pro.o backup/ssc.o backup/swc.o backup/tototek.o \
|
||||
backup/ufo.o backup/yoko.o backup/z64.o
|
||||
ifdef USE_ZLIB
|
||||
LDFLAGS+=-lz
|
||||
OBJECTS+=misc/archive.o misc/map.o misc/unzip.o
|
||||
endif
|
||||
ifdef USE_USB
|
||||
LDFLAGS+=-lusb
|
||||
OBJECTS+=misc/usb.o
|
||||
endif
|
||||
|
||||
ifdef DLOPEN
|
||||
OBJECTS+=misc/dlopen.o
|
||||
ifndef USE_ZLIB
|
||||
ifeq ($(GCC_WIN),1)
|
||||
else
|
||||
ifdef DJGPP # DJGPP code in dlopen needs map code
|
||||
OBJECTS+=misc/map.o
|
||||
endif # DJGPP
|
||||
endif # GCC_WIN
|
||||
endif # USE_ZLIB
|
||||
else
|
||||
ifeq ($(GCC_WIN),1) # Cygwin/MinGW code in ucon64_misc needs dlopen code
|
||||
OBJECTS+=misc/dlopen.o
|
||||
endif # GCC_WIN
|
||||
endif # DLOPEN
|
||||
|
||||
|
||||
TARGET=ucon64
|
||||
ifeq ($(GCC_WIN),1)
|
||||
TARGET:=$(addsuffix .exe,$(TARGET)) # adding .exe avoids "problems" with Cygwin/MinGW
|
||||
else
|
||||
ifdef DJGPP # OSTYPE is not defined by default under DOS
|
||||
TARGET:=$(addsuffix .exe,$(TARGET))
|
||||
endif # DJGPP
|
||||
endif # GCC_WIN
|
||||
TARGETS+=$(TARGET)
|
||||
|
||||
all: $(TARGETS)
|
||||
|
||||
|
||||
CLEAN_CMD=rm -f $(TARGET) $(OBJECTS) *.core *.stackdump *~ */*~ */*/*~; \
|
||||
cd libdiscmage && $(MAKE) clean; \
|
||||
cd ../backup/libcd64 && $(MAKE) clean
|
||||
|
||||
clean:
|
||||
ifeq ($(GCC_WIN),1)
|
||||
$(CLEAN_CMD)
|
||||
else
|
||||
ifdef DJGPP
|
||||
del *.o
|
||||
del patch\*.o
|
||||
del console\*.o
|
||||
del backup\*.o
|
||||
del misc\*.o
|
||||
del $(TARGET)
|
||||
cd libdiscmage
|
||||
$(MAKE) clean
|
||||
cd ../backup/libcd64
|
||||
$(MAKE) clean
|
||||
cd ../..
|
||||
else # Unix, BeOS or Mac OS X (Darwin)
|
||||
$(CLEAN_CMD)
|
||||
endif # DJGPP
|
||||
endif # GCC_WIN
|
||||
|
||||
|
||||
DISTCLEAN_CMD=rm -f Makefile config.log config.status config.cache config.h; \
|
||||
cd libdiscmage && $(MAKE) distclean; \
|
||||
cd ../backup/libcd64 && $(MAKE) clean
|
||||
# libcd64 Makefile has no distclean target
|
||||
|
||||
distclean: clean
|
||||
ifeq ($(GCC_WIN),1)
|
||||
$(DISTCLEAN_CMD)
|
||||
else
|
||||
ifdef DJGPP
|
||||
del Makefile
|
||||
del config.log
|
||||
del config.status
|
||||
del config.cache
|
||||
del config.h
|
||||
cd libdiscmage
|
||||
$(MAKE) distclean
|
||||
cd ../backup/libcd64
|
||||
$(MAKE) clean
|
||||
cd ../..
|
||||
else
|
||||
$(DISTCLEAN_CMD)
|
||||
endif # DJGPP
|
||||
endif # GCC_WIN
|
||||
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
backup/cd64.o: backup/cd64.c
|
||||
$(CC) $(CFLAGS) -Ibackup/libcd64 -c $< -o $@
|
||||
|
||||
|
||||
ifdef USE_DISCMAGE
|
||||
libdiscmage/$(FULLLIBNAME_DM):
|
||||
ifeq ($(GCC_WIN),1)
|
||||
cd libdiscmage && $(MAKE)
|
||||
else
|
||||
ifdef DJGPP
|
||||
cd libdiscmage
|
||||
$(MAKE)
|
||||
cd ..
|
||||
else
|
||||
cd libdiscmage && $(MAKE)
|
||||
endif # DJGPP
|
||||
endif # GCC_WIN
|
||||
endif # USE_DISCMAGE
|
||||
|
||||
ifdef USE_LIBCD64
|
||||
backup/libcd64/libcd64.a:
|
||||
ifeq ($(GCC_WIN),1)
|
||||
cd backup/libcd64 && $(MAKE)
|
||||
else
|
||||
ifdef DJGPP
|
||||
cd backup/libcd64
|
||||
$(MAKE)
|
||||
cd ../..
|
||||
else
|
||||
cd backup/libcd64 && $(MAKE)
|
||||
endif # DJGPP
|
||||
endif # GCC_WIN
|
||||
endif # USE_DISCMAGE
|
||||
|
||||
$(TARGET): $(OBJECTS)
|
||||
$(CC) $(OBJECTS) $(LDFLAGS) -o $@
|
||||
|
||||
|
||||
install:
|
||||
ifeq ($(TERM),cygwin) # test cygwin before DJGPP
|
||||
else
|
||||
ifeq ($(OSTYPE),msys) # test msys before DJGPP
|
||||
else
|
||||
ifdef DJGPP
|
||||
else
|
||||
ifeq ($(OSTYPE),beos)
|
||||
./install_beos.sh
|
||||
else
|
||||
./install.sh
|
||||
endif # beos
|
||||
endif # DJGPP
|
||||
endif # msys
|
||||
endif # cygwin
|
||||
ifndef DLOPEN
|
||||
cd libdiscmage && $(MAKE) install
|
||||
endif
|
||||
|
||||
|
||||
uninstall:
|
||||
ifeq ($(TERM),cygwin) # test cygwin before DJGPP
|
||||
else
|
||||
ifeq ($(OSTYPE),msys) # test msys before DJGPP
|
||||
else
|
||||
ifdef DJGPP
|
||||
else
|
||||
ifeq ($(OSTYPE),beos)
|
||||
rm -f $(HOME)/config/bin/$(TARGET)
|
||||
else
|
||||
rm -f /usr/local/bin/$(TARGET)
|
||||
endif # beos
|
||||
endif # DJGPP
|
||||
endif # msys
|
||||
endif # cygwin
|
||||
ifndef DLOPEN
|
||||
cd libdiscmage && $(MAKE) uninstall
|
||||
endif
|
||||
|
||||
|
||||
# Dependencies
|
||||
|
||||
# Most source files include these
|
||||
UCON64_STD_H=ucon64.h ucon64_misc.h misc/misc.h config.h ucon64_defines.h
|
||||
|
||||
misc/archive.o: misc/archive.h misc/map.h config.h
|
||||
misc/chksum.o: misc/chksum.h config.h
|
||||
misc/dlopen.o: misc/dlopen.h misc/dxedll_pub.h config.h
|
||||
misc/getopt.o: misc/getopt.h
|
||||
misc/map.o: misc/map.h config.h
|
||||
misc/misc.o: misc/misc.h misc/archive.h config.h
|
||||
misc/parallel.o: misc/parallel.h config.h
|
||||
misc/usb.o: misc/usb.h config.h
|
||||
misc/unzip.o: misc/unzip.h config.h
|
||||
ucon64.o: misc/dlopen.h misc/getopt.h ucon64_dat.h ucon64_opts.h \
|
||||
console/dc.h console/gb.h console/gba.h console/genesis.h \
|
||||
console/jaguar.h console/lynx.h console/n64.h console/neogeo.h \
|
||||
console/nes.h console/ngp.h console/pce.h console/psx.h console/sms.h \
|
||||
console/snes.h console/swan.h \
|
||||
backup/cd64.h backup/dex.h backup/doctor64.h backup/doctor64jr.h \
|
||||
backup/f2a.h backup/fal.h backup/ffe.h backup/fig.h backup/gbx.h \
|
||||
backup/gd.h backup/interceptor.h backup/lynxit.h backup/mccl.h \
|
||||
backup/mcd.h backup/md-pro.h backup/mgd.h backup/msg.h \
|
||||
backup/pce-pro.h backup/pl.h backup/smc.h backup/smd.h \
|
||||
backup/smsgg-pro.h backup/ssc.h backup/swc.h backup/tototek.h \
|
||||
backup/ufo.h backup/yoko.h backup/z64.h \
|
||||
patch/aps.h patch/bsl.h patch/gg.h patch/ips.h patch/pal4u.h \
|
||||
patch/ppf.h patch/xps.h $(UCON64_STD_H)
|
||||
ucon64_dat.o: ucon64_dat.h $(UCON64_STD_H)
|
||||
ucon64_misc.o: misc/dlopen.h $(UCON64_STD_H)
|
||||
ucon64_opts.o: misc/dlopen.h misc/getopt.h ucon64_dat.h ucon64_opts.h \
|
||||
console/dc.h console/gb.h console/gba.h console/genesis.h \
|
||||
console/jaguar.h console/lynx.h console/n64.h console/neogeo.h \
|
||||
console/nes.h console/ngp.h console/pce.h console/psx.h \
|
||||
console/sms.h console/snes.h console/swan.h \
|
||||
backup/cd64.h backup/dex.h backup/doctor64.h \
|
||||
backup/doctor64jr.h backup/f2a.h backup/fal.h backup/ffe.h \
|
||||
backup/fig.h backup/gbx.h backup/gd.h backup/interceptor.h \
|
||||
backup/lynxit.h backup/mccl.h backup/mcd.h backup/md-pro.h \
|
||||
backup/mgd.h backup/msg.h backup/pce-pro.h backup/pl.h \
|
||||
backup/smc.h backup/smd.h backup/smsgg-pro.h backup/ssc.h \
|
||||
backup/swc.h backup/tototek.h backup/ufo.h backup/yoko.h \
|
||||
backup/z64.h \
|
||||
patch/aps.h patch/bsl.h patch/gg.h patch/ips.h patch/pal4u.h \
|
||||
patch/ppf.h patch/xps.h $(UCON64_STD_H)
|
||||
console/dc.o: console/dc.h $(UCON64_STD_H)
|
||||
console/gb.o: console/gb.h backup/mgd.h $(UCON64_STD_H)
|
||||
console/gba.o: console/gba.h $(UCON64_STD_H)
|
||||
console/genesis.o: console/genesis.h backup/smd.h backup/mgd.h $(UCON64_STD_H)
|
||||
console/jaguar.o: console/jaguar.h $(UCON64_STD_H)
|
||||
console/lynx.o: console/lynx.h $(UCON64_STD_H)
|
||||
console/n64.o: console/n64.h $(UCON64_STD_H)
|
||||
console/neogeo.o: console/neogeo.h $(UCON64_STD_H)
|
||||
console/nes.o: console/nes.h $(UCON64_STD_H)
|
||||
console/ngp.o: console/ngp.h $(UCON64_STD_H)
|
||||
console/pce.o: console/pce.h backup/mgd.h $(UCON64_STD_H)
|
||||
console/psx.o: console/psx.h $(UCON64_STD_H)
|
||||
console/sms.o: console/sms.h backup/smd.h backup/mgd.h $(UCON64_STD_H)
|
||||
console/snes.o: console/snes.h backup/mgd.h $(UCON64_STD_H)
|
||||
console/swan.o: console/swan.h $(UCON64_STD_H)
|
||||
backup/cd64.o: backup/cd64.h $(UCON64_STD_H)
|
||||
backup/cmc.o: backup/cmc.h $(UCON64_STD_H)
|
||||
backup/dex.o: backup/dex.h backup/psxpblib.h $(UCON64_STD_H)
|
||||
backup/doctor64.o: backup/doctor64.h $(UCON64_STD_H)
|
||||
backup/doctor64jr.o: backup/doctor64jr.h $(UCON64_STD_H)
|
||||
backup/f2a.o: backup/f2a.h $(UCON64_STD_H)
|
||||
backup/fal.o: backup/fal.h backup/cartlib.c $(UCON64_STD_H)
|
||||
backup/ffe.o: backup/ffe.h $(UCON64_STD_H)
|
||||
backup/fig.o: backup/fig.h console/snes.h $(UCON64_STD_H)
|
||||
backup/gd.o: backup/gd.h console/snes.h $(UCON64_STD_H)
|
||||
backup/gbx.o: backup/gbx.h $(UCON64_STD_H)
|
||||
backup/lynxit.o: backup/lynxit.h $(UCON64_STD_H)
|
||||
backup/mccl.o: backup/mccl.h $(UCON64_STD_H)
|
||||
backup/mcd.o: backup/mcd.h $(UCON64_STD_H)
|
||||
backup/md-pro.o: backup/md-pro.h backup/tototek.h $(UCON64_STD_H)
|
||||
backup/mgd.o: backup/mgd.h $(UCON64_STD_H)
|
||||
backup/msg.o: backup/msg.h backup/ffe.h $(UCON64_STD_H)
|
||||
backup/pce-pro.o: backup/pce-pro.h backup/tototek.h $(UCON64_STD_H)
|
||||
backup/pl.o: backup/pl.h $(UCON64_STD_H)
|
||||
backup/psxpblib.o: backup/psxpblib.h $(UCON64_STD_H)
|
||||
backup/sflash.o: backup/sflash.h backup/tototek.h $(UCON64_STD_H)
|
||||
backup/smc.o: backup/smc.h backup/ffe.h $(UCON64_STD_H)
|
||||
backup/smd.o: backup/smd.h backup/ffe.h $(UCON64_STD_H)
|
||||
backup/smsgg-pro.o: backup/smsgg-pro.h backup/tototek.h $(UCON64_STD_H)
|
||||
backup/swc.o: backup/swc.h backup/ffe.h console/snes.h $(UCON64_STD_H)
|
||||
backup/tototek.o: backup/tototek.h $(UCON64_STD_H)
|
||||
backup/ufo.o: backup/ufo.h $(UCON64_STD_H)
|
||||
backup/yoko.o: backup/yoko.h $(UCON64_STD_H)
|
||||
backup/z64.o: backup/z64.h $(UCON64_STD_H)
|
||||
patch/aps.o: patch/aps.h $(UCON64_STD_H)
|
||||
patch/bsl.o: patch/bsl.h $(UCON64_STD_H)
|
||||
patch/gg.o: patch/gg.h $(UCON64_STD_H)
|
||||
patch/ips.o: patch/ips.h $(UCON64_STD_H)
|
||||
patch/pal4u.o: patch/pal4u.h $(UCON64_STD_H)
|
||||
patch/ppf.o: patch/ppf.h $(UCON64_STD_H)
|
||||
patch/xps.o: patch/xps.h $(UCON64_STD_H)
|
||||
@@ -1,223 +0,0 @@
|
||||
DLOPEN=1
|
||||
#USE_ZLIB=1
|
||||
USE_DISCMAGE=1
|
||||
#USE_USB=1
|
||||
USE_LIBCD64=1
|
||||
|
||||
CC=cl.exe
|
||||
CFLAGS=/nologo /I. /W3 /O2 /DHAVE_CONFIG_H
|
||||
LDFLAGS=/NOLOGO setargv.obj
|
||||
TARGETS=
|
||||
|
||||
!ifdef USE_DISCMAGE
|
||||
LIBNAME_DM=discmage
|
||||
!endif
|
||||
|
||||
!ifdef USE_DISCMAGE
|
||||
FULLLIBNAME_DM=$(LIBNAME_DM).dll
|
||||
!ifndef DLOPEN
|
||||
LDFLAGS=$(LDFLAGS) libdiscmage/$(LIBNAME_DM).lib
|
||||
!endif
|
||||
!endif
|
||||
|
||||
TARGETS=$(TARGETS) libdiscmage/$(FULLLIBNAME_DM)
|
||||
|
||||
|
||||
!ifdef USE_LIBCD64
|
||||
LDFLAGS=$(LDFLAGS) backup/libcd64/cd64.lib
|
||||
TARGETS=$(TARGETS) backup/libcd64/cd64.lib
|
||||
!endif
|
||||
|
||||
|
||||
OBJECTS=ucon64.obj ucon64_dat.obj ucon64_misc.obj ucon64_opts.obj \
|
||||
misc/chksum.obj misc/file.obj misc/getopt.obj misc/getopt2.obj \
|
||||
misc/misc.obj misc/parallel.obj misc/property.obj misc/string.obj \
|
||||
misc/dlopen.obj \
|
||||
patch/aps.obj patch/bsl.obj patch/gg.obj patch/ips.obj \
|
||||
patch/pal4u.obj patch/ppf.obj patch/xps.obj \
|
||||
console/dc.obj console/gb.obj console/gba.obj console/genesis.obj \
|
||||
console/jaguar.obj console/lynx.obj console/n64.obj \
|
||||
console/neogeo.obj console/nes.obj console/ngp.obj console/pce.obj \
|
||||
console/psx.obj console/sms.obj console/snes.obj console/swan.obj \
|
||||
backup/cd64.obj backup/cmc.obj backup/dex.obj backup/doctor64.obj \
|
||||
backup/doctor64jr.obj backup/f2a.obj backup/fal.obj backup/ffe.obj \
|
||||
backup/fig.obj backup/gbx.obj backup/gd.obj backup/interceptor.obj \
|
||||
backup/lynxit.obj backup/mccl.obj backup/mcd.obj backup/md-pro.obj \
|
||||
backup/mgd.obj backup/msg.obj backup/pce-pro.obj backup/pl.obj \
|
||||
backup/psxpblib.obj backup/sflash.obj backup/smc.obj backup/smd.obj \
|
||||
backup/smsgg-pro.obj backup/ssc.obj backup/swc.obj backup/tototek.obj \
|
||||
backup/ufo.obj backup/yoko.obj backup/z64.obj
|
||||
!ifdef USE_ZLIB
|
||||
LDFLAGS=$(LDFLAGS) zlib.lib
|
||||
OBJECTS=$(OBJECTS) misc/map.obj misc/archive.obj misc/unzip.obj
|
||||
!endif
|
||||
!ifdef USE_USB
|
||||
LDFLAGS=$(LDFLAGS) usb.lib
|
||||
OBJECTS=$(OBJECTS) misc/usb.obj
|
||||
!endif
|
||||
|
||||
|
||||
TARGET=ucon64.exe
|
||||
TARGETS=$(TARGETS) $(TARGET)
|
||||
|
||||
all: $(TARGETS)
|
||||
|
||||
|
||||
clean:
|
||||
del *.obj
|
||||
del patch\*.obj
|
||||
del console\*.obj
|
||||
del backup\*.obj
|
||||
del misc\*.obj
|
||||
del $(TARGET)
|
||||
cd libdiscmage
|
||||
$(MAKE) /NOLOGO /f Makefile.vc6 clean
|
||||
cd ..\backup\libcd64
|
||||
$(MAKE) /NOLOGO /f Makefile.vc6 clean
|
||||
cd ..\..
|
||||
|
||||
|
||||
distclean: clean
|
||||
del config.h
|
||||
cd libdiscmage
|
||||
$(MAKE) /NOLOGO /f Makefile.vc6 distclean
|
||||
cd ..\backup\libcd64
|
||||
# libcd64 Makefile has no distclean target
|
||||
$(MAKE) /NOLOGO /f Makefile.vc6 clean
|
||||
cd ..\..
|
||||
|
||||
|
||||
.c.obj:
|
||||
$(CC) $(CFLAGS) /c $< /Fo$@
|
||||
|
||||
backup/cd64.obj:
|
||||
$(CC) $(CFLAGS) /Ibackup/libcd64 /c $*.c /Fo$@
|
||||
|
||||
|
||||
!ifdef USE_DISCMAGE
|
||||
libdiscmage/$(FULLLIBNAME_DM):
|
||||
cd libdiscmage
|
||||
$(MAKE) /NOLOGO /f Makefile.vc6
|
||||
cd ..
|
||||
!endif
|
||||
|
||||
!ifdef USE_LIBCD64
|
||||
backup/libcd64/cd64.lib:
|
||||
cd backup/libcd64
|
||||
$(MAKE) /NOLOGO /f Makefile.vc6
|
||||
cd ../..
|
||||
!endif
|
||||
|
||||
|
||||
$(TARGET): $(OBJECTS)
|
||||
link.exe $(OBJECTS) $(LDFLAGS) /OUT:$@
|
||||
|
||||
|
||||
install:
|
||||
cd libdiscmage
|
||||
$(MAKE) /NOLOGO /f Makefile.vc6 install
|
||||
cd ..
|
||||
|
||||
|
||||
uninstall:
|
||||
cd libdiscmage
|
||||
$(MAKE) /NOLOGO /f Makefile.vc6 uninstall
|
||||
cd ..
|
||||
|
||||
|
||||
# Dependencies
|
||||
|
||||
# Most source files include these
|
||||
UCON64_STD_H=ucon64.h ucon64_misc.h misc/misc.h config.h ucon64_defines.h
|
||||
|
||||
misc/archive.obj: misc/archive.h misc/map.h config.h
|
||||
misc/chk.obj: misc/chksum.h config.h
|
||||
misc/dlopen.obj: misc/dlopen.h misc/dxedll_pub.h config.h
|
||||
misc/getopt.obj: misc/getopt.h
|
||||
misc/map.obj: misc/map.h config.h
|
||||
misc/misc.obj: misc/misc.h misc/archive.h config.h
|
||||
misc/parallel.obj: misc/parallel.h config.h
|
||||
misc/usb.obj: misc/usb.h config.h
|
||||
misc/unzip.obj: misc/unzip.h config.h
|
||||
ucon64.obj: misc/dlopen.h misc/getopt.h ucon64_dat.h ucon64_opts.h \
|
||||
console/dc.h console/gb.h console/gba.h console/genesis.h \
|
||||
console/jaguar.h console/lynx.h console/n64.h console/neogeo.h \
|
||||
console/nes.h console/ngp.h console/pce.h console/psx.h \
|
||||
console/sms.h console/snes.h console/swan.h \
|
||||
backup/cd64.h backup/dex.h backup/doctor64.h backup/doctor64jr.h \
|
||||
backup/f2a.h backup/fal.h backup/ffe.h backup/fig.h backup/gbx.h \
|
||||
backup/gd.h backup/interceptor.h backup/lynxit.h backup/mccl.h \
|
||||
backup/mcd.h backup/md-pro.h backup/mgd.h backup/msg.h \
|
||||
backup/pce-pro.h backup/pl.h backup/smc.h backup/smd.h \
|
||||
backup/smsgg-pro.h backup/ssc.h backup/swc.h backup/tototek.h \
|
||||
backup/ufo.h backup/yoko.h backup/z64.h \
|
||||
patch/aps.h patch/bsl.h patch/gg.h patch/ips.h patch/pal4u.h \
|
||||
patch/ppf.h patch/xps.h $(UCON64_STD_H)
|
||||
ucon64_dat.obj: ucon64_dat.h $(UCON64_STD_H)
|
||||
ucon64_misc.obj: misc/dlopen.h $(UCON64_STD_H)
|
||||
ucon64_opts.obj: misc/dlopen.h misc/getopt.h ucon64_dat.h ucon64_opts.h \
|
||||
console/dc.h console/gb.h console/gba.h console/genesis.h \
|
||||
console/jaguar.h console/lynx.h console/n64.h \
|
||||
console/neogeo.h console/nes.h console/ngp.h console/pce.h \
|
||||
console/psx.h console/sms.h console/snes.h console/swan.h \
|
||||
backup/cd64.h backup/dex.h backup/doctor64.h \
|
||||
backup/doctor64jr.h backup/f2a.h backup/fal.h backup/ffe.h \
|
||||
backup/fig.h backup/gbx.h backup/gd.h backup/interceptor.h \
|
||||
backup/lynxit.h backup/mccl.h backup/mcd.h backup/md-pro.h \
|
||||
backup/mgd.h backup/msg.h backup/pce-pro.h backup/pl.h \
|
||||
backup/smc.h backup/smd.h backup/smsgg-pro.h backup/ssc.h \
|
||||
backup/swc.h backup/tototek.h backup/ufo.h backup/yoko.h \
|
||||
backup/z64.h \
|
||||
patch/aps.h patch/bsl.h patch/gg.h patch/ips.h patch/pal4u.h \
|
||||
patch/ppf.h patch/xps.h $(UCON64_STD_H)
|
||||
console/dc.obj: console/dc.h $(UCON64_STD_H)
|
||||
console/gb.obj: console/gb.h backup/mgd.h $(UCON64_STD_H)
|
||||
console/gba.obj: console/gba.h $(UCON64_STD_H)
|
||||
console/genesis.obj: console/genesis.h backup/smd.h backup/mgd.h $(UCON64_STD_H)
|
||||
console/jaguar.obj: console/jaguar.h $(UCON64_STD_H)
|
||||
console/lynx.obj: console/lynx.h $(UCON64_STD_H)
|
||||
console/n64.obj: console/n64.h $(UCON64_STD_H)
|
||||
console/neogeo.obj: console/neogeo.h $(UCON64_STD_H)
|
||||
console/nes.obj: console/nes.h $(UCON64_STD_H)
|
||||
console/ngp.obj: console/ngp.h $(UCON64_STD_H)
|
||||
console/pce.obj: console/pce.h backup/mgd.h $(UCON64_STD_H)
|
||||
console/psx.obj: console/psx.h $(UCON64_STD_H)
|
||||
console/sms.obj: console/sms.h backup/smd.h backup/mgd.h $(UCON64_STD_H)
|
||||
console/snes.obj: console/snes.h backup/mgd.h $(UCON64_STD_H)
|
||||
console/swan.obj: console/swan.h $(UCON64_STD_H)
|
||||
backup/cd64.obj: backup/cd64.h $(UCON64_STD_H)
|
||||
backup/cmc.obj: backup/cmc.h $(UCON64_STD_H)
|
||||
backup/dex.obj: backup/dex.h backup/psxpblib.h $(UCON64_STD_H)
|
||||
backup/doctor64.obj: backup/doctor64.h $(UCON64_STD_H)
|
||||
backup/doctor64jr.obj: backup/doctor64jr.h $(UCON64_STD_H)
|
||||
backup/f2a.obj: backup/f2a.h $(UCON64_STD_H)
|
||||
backup/fal.obj: backup/fal.h backup/cartlib.c $(UCON64_STD_H)
|
||||
backup/ffe.obj: backup/ffe.h $(UCON64_STD_H)
|
||||
backup/fig.obj: backup/fig.h console/snes.h $(UCON64_STD_H)
|
||||
backup/gd.obj: backup/gd.h console/snes.h $(UCON64_STD_H)
|
||||
backup/gbx.obj: backup/gbx.h $(UCON64_STD_H)
|
||||
backup/lynxit.obj: backup/lynxit.h $(UCON64_STD_H)
|
||||
backup/mcd.obj: backup/mcd.h $(UCON64_STD_H)
|
||||
backup/mccl.obj: backup/mccl.h $(UCON64_STD_H)
|
||||
backup/md-pro.obj: backup/md-pro.h backup/tototek.h $(UCON64_STD_H)
|
||||
backup/mgd.obj: backup/mgd.h $(UCON64_STD_H)
|
||||
backup/msg.obj: backup/msg.h backup/ffe.h $(UCON64_STD_H)
|
||||
backup/pce-pro.obj: backup/pce-pro.h backup/tototek.h $(UCON64_STD_H)
|
||||
backup/pl.obj: backup/pl.h $(UCON64_STD_H)
|
||||
backup/psxpblib.obj: backup/psxpblib.h $(UCON64_STD_H)
|
||||
backup/sflash.obj: backup/sflash.h backup/tototek.h $(UCON64_STD_H)
|
||||
backup/smc.obj: backup/smc.h backup/ffe.h $(UCON64_STD_H)
|
||||
backup/smd.obj: backup/smd.h backup/ffe.h $(UCON64_STD_H)
|
||||
backup/smsgg-pro.obj: backup/smsgg-pro.h backup/tototek.h $(UCON64_STD_H)
|
||||
backup/swc.obj: backup/swc.h backup/ffe.h console/snes.h $(UCON64_STD_H)
|
||||
backup/tototek.obj: backup/tototek.h $(UCON64_STD_H)
|
||||
backup/ufo.obj: backup/ufo.h $(UCON64_STD_H)
|
||||
backup/yoko.obj: backup/yoko.h $(UCON64_STD_H)
|
||||
backup/z64.obj: backup/z64.h $(UCON64_STD_H)
|
||||
patch/aps.obj: patch/aps.h $(UCON64_STD_H)
|
||||
patch/bsl.obj: patch/bsl.h $(UCON64_STD_H)
|
||||
patch/gg.obj: patch/gg.h $(UCON64_STD_H)
|
||||
patch/ips.obj: patch/ips.h $(UCON64_STD_H)
|
||||
patch/pal4u.obj: patch/pal4u.h $(UCON64_STD_H)
|
||||
patch/ppf.obj: patch/ppf.h $(UCON64_STD_H)
|
||||
patch/xps.obj: patch/xps.h $(UCON64_STD_H)
|
||||
@@ -1,118 +0,0 @@
|
||||
Legend for Code1:
|
||||
0 = seems to work without modification
|
||||
1 = needs crack (uCON64 option -k)
|
||||
2 = needs NTSC/PAL fix (uCON64 option -f)
|
||||
3 = needs backup unit header fix
|
||||
4 = seems to work, but doesn't work correctly
|
||||
5 = music doesn't work
|
||||
6 = copy protection screen
|
||||
7 = wrong television standard (NTSC/PAL) screen
|
||||
8 = corrupted/distorted graphics
|
||||
9 = doesn't work
|
||||
|
||||
|
||||
Legend for Code2:
|
||||
N1 = 3f 21 29/89 10 f0 3f 21 29/89 10 80
|
||||
N2 = ad 3f 21 29 10 d0 ad 3f 21 29 10 ea ea
|
||||
P3 = ad 3f 21 89 10 d0 ad 3f 21 89 10 80 - Terranigma
|
||||
N4 = ad 3f 21 89 10 d0 ad 3f 21 89 10 80/(ea ea) - Live A Live
|
||||
N5 = 3f 21 29/89 10 00 f0 3f 21 29/89 10 00 80 - Clock Tower
|
||||
N6 = 3f 21 29/89 10 00 d0 3f 21 29/89 10 00 ea ea - Mario no Super Picross
|
||||
P7 = ad 3f 21 29 10 00 d0 ad 3f 21 29 10 00 80
|
||||
P8 = ad 3f 21 89 10 00 d0 a9 10 00 89 10 00 d0 - Eric Cantona Football ?
|
||||
N9 = 3f 21 89 10 c2 XX f0 3f 21 89 10 c2 XX 80 - Front Mission - Gun Hazard
|
||||
N10 = 3f 21 89 10 c2 XX d0 3f 21 89 10 c2 XX ea ea - Robotrek
|
||||
N11 = 3f 21 29/89 10 c9 10 f0 3f 21 29/89 10 c9 10 80
|
||||
N12 = ad 3f 21 29 10 c9 00 f0 ad 3f 21 29 10 c9 00 80/(ea ea) <= original uCON used 80
|
||||
N13 = ad 3f 21 29 10 c9 00 d0 ad 3f 21 29 10 c9 00 80
|
||||
N14 = ad 3f 21 29 10 c9 10 d0 ad 3f 21 29 10 c9 10 ea ea
|
||||
P15 = ad 3f 21 29 10 cf bd ff XX f0 ad 3f 21 29 10 cf bd ff XX 80 - Pop'n Twinbee E
|
||||
N16 = 3f 21 29 10 cf XX YY 80 f0 3f 21 29 10 cf XX YY 80 80 - Gokujyou Parodius/Tokimeki Memorial
|
||||
N17 = ad 3f 21 8d XX YY 29 10 8d ad 3f 21 8d XX YY 29 00 8d - Dragon Ball Z - Super Butoden 2 ?
|
||||
N18 = 3f 21 00 29/89 10 f0 3f 21 00 29/89 10 80 - Kirby's Dream Course U
|
||||
P19 = af 3f 21 00 29 10 d0 af 3f 21 00 29 10 80
|
||||
N20 = af 3f 21 00 29/89 10 d0 af 3f 21 00 29/89 10 ea ea - Kirby no Kirakira Kids/Final Fight Guy
|
||||
P21 = af 3f 21 00 29 10 00 d0 af 3f 21 00 29 10 00 ea ea
|
||||
N22 = af 3f 21 00 29/89 10 00 f0 af 3f 21 00 29/89 10 00 80
|
||||
P23 = af 3f 21 00 29 XX c9 XX f0 af 3f 21 00 29 XX c9 XX 80 - Secret of Mana E
|
||||
N24 = af 3f 21 00 29 XX c9 XX f0 af 3f 21 00 29 XX c9 XX 80 - Seiken Densetsu 3
|
||||
N25 = af 3f 21 00 29 10 80 2d 00 1b af 3f 21 00 29 00 80 2d 00 1b - Seiken Densetsu 2/Secret of Mana U
|
||||
N26 = 3f 21 00 89 10 c2 XX f0 3f 21 00 89 10 c2 XX 80 - Dragon - The Bruce Lee Story U
|
||||
N27 = af 3f 21 00 XX YY 29 10 00 d0 af 3f 21 00 XX YY 29 10 00 ea ea - Fatal Fury Special ?
|
||||
N28 = 3f 21 c2 XX 29 10 00 f0 3f 21 c2 XX 29 10 00 80 - Metal Warriors
|
||||
N29 = 3f 21 c2 XX 29 10 00 d0 3f 21 c2 XX 29 10 00 ea ea - Dual Orb II
|
||||
N30 = af 3f 21 ea 89 10 00 d0 a9 00 00 ea 89 10 00 d0 - Super Famista 3 ?
|
||||
P31 = a2 18 01 bd 27 20 89 10 00 f0 01 a2 18 01 bd 27 20 89 10 00 ea ea - Donkey Kong Country E
|
||||
N32 = a2 18 01 bd 27 20 89 10 00 d0 01 a2 18 01 bd 27 20 89 10 00 ea ea - Donkey Kong Country U
|
||||
N33 = 29 10 00 a2 00 00 c9 10 00 d0 29 10 00 a2 00 00 c9 10 00 80 - Wolfenstein 3D U
|
||||
|
||||
|
||||
Comment:
|
||||
Code1 is valid for an SWC 2.8cc 32 Mbit PAL. For example Terranigma has a Code1
|
||||
of 0, but a Code2 of P3, because it runs without modification on a PAL SNES but
|
||||
needs an NTSC/PAL fix for an NTSC SNES.
|
||||
The prefix N indicates an NTSC protection code, the prefix P indicates a PAL
|
||||
protection code. Cracking or fixing an NTSC protection code makes a game run
|
||||
on a PAL SNES and vice versa.
|
||||
|
||||
|
||||
Code1 Code2 Game
|
||||
2 N5 Clock Tower (J) <= 0x29
|
||||
1 + 2 N1 Demon's Crest (U) <= (0xad) 0x29
|
||||
1 + 2 + 4 N6 Donkey Kong Country 2 - Diddy's Kong Quest (U) (V1.1) <= can't get past the first level; 0x29
|
||||
1 P31 Donkey Kong Country (E) (V1.0)
|
||||
1 P31 Donkey Kong Country (E) (V1.1)
|
||||
1 + 2 N32 Donkey Kong Country (U) (V1.0)
|
||||
1 + 2 N32 Donkey Kong Country (U) (V1.1)
|
||||
2 N26 Dragon - The Bruce Lee Story (U)
|
||||
2 N4 Dr. Mario (J) (NP) <= 0xea 0xea
|
||||
2 N29 Dual Orb II (J)
|
||||
1 + 2 N18 Earthbound (U) <= 0x29
|
||||
2 + 3 N1 Final Fight 3 (U) <= emulation mode select byte: 0x1c; (0xad) 0x29
|
||||
2 N20 Final Fight Guy (U) <= 0x89
|
||||
2 + 3 N1 Final Fight Tough (J) <= emulation mode select byte: 0x1c; (0xad) 0x29
|
||||
1 + 2 N9 Front Mission - Gun Hazard (J) <= modification protection; code 0 for NTSC SNES; 0x20
|
||||
2 N16 Gokujou Parodius (J) <= 0xad 0xff
|
||||
2 N1 Illusion of Gaia (U) <= (0xad) 0x89
|
||||
2 + 9 N16 Jikkyou Oshaberi Parodius (J) <= 0xad 0xff
|
||||
2 N1 Joe & Mac 2 - Lost in the Tropics (U) (35468) <= (0xad) 0x29
|
||||
2 N1 Joe & Mac 2 - Lost in the Tropics (U) (54227) <= (0xad) 0x29
|
||||
2 + 9 N5 Kaite Tukutte Asoberu Dezaemon (J) <= 0x89
|
||||
2 N20 Kirby no Kirakira Kids (J) (NP) <= 0x29
|
||||
1 + 2 N18 Kirby's Dream Course (U) <= 0x29
|
||||
2 N4 Live A Live (J) <= 0xea 0xea
|
||||
2 N28 Magical Pop'n (J)
|
||||
1 + 2 N6 Mario no Super Picross (J) <= 0x89
|
||||
2 N1 Mega Man's Soccer (U) <= (0xad) 0x89
|
||||
2 N1 Mega Man VII (U) <= (0xad) 0x29
|
||||
2 + 9 N1 Mega Man X 2 (U) <= the intro can be viewed; (0xad) 0x89
|
||||
1 + 2 N1 Mega Man X (U) (V1.0) <= (0xad) 0x89
|
||||
1 + 2 N1 Mega Man X (U) (V1.1) <= (0xad) 0x89
|
||||
2 N28 Metal Warriors (U)
|
||||
2 + 3 N1 + N2 Mickey to Donald Magical Adventure 3 (J) <= emulation mode select byte: 0x1c; (0xad) 0x29
|
||||
2 N2 Ninja Gaiden Trilogy (U)
|
||||
0 P15 Pop'n Twinbee (E) <= 0x80
|
||||
0 P15 Pop'n Twinbee - Rainbow Bell Adventures (E) <= 0x00
|
||||
2 N10 Robotrek (U) <= 0x20
|
||||
2 N18 Romancing Sa-Ga 2 (J) <= 0x89
|
||||
2 N18 Romancing Sa-Ga 3 (J) (V1.0) <= 0x89
|
||||
2 N18 Romancing Sa-Ga 3 (J) (V1.1) <= 0x89
|
||||
2 N25 Secret of Mana (U)
|
||||
0 P23 Secret of Mana (E) (V1.0) <= 0x10 0x10
|
||||
0 P23 Secret of Mana (E) (V1.1) <= 0x10 0x10
|
||||
2 N25 Seiken Densetsu 2 (J)
|
||||
2 N24 Seiken Densetsu 3 (J) <= 0x10 0x00
|
||||
2 N1 Street Fighter II Turbo (U) <= (0xad) 0x29
|
||||
1 + 2 N1 Super Mario All-Stars (U) <= (0xad) 0x89
|
||||
1 + 2 N1 Super Mario All-Stars & World (U) <= (0xad) 0x89
|
||||
1 + 2 N1 Super Mario Collection (J) (V1.1) <= (0xad) 0x89
|
||||
1 + 2 N1 Super Metroid (JU) <= (0xad) 0x89
|
||||
0 P3 Terranigma (E)
|
||||
1 P3 Tetris Attack (E)
|
||||
1 + 2 N1 Tetris Attack (U) <= (0xad) 0x89
|
||||
2 + 8 + 9 N16 Tokimeki Memorial - Densetsu no Ki no Shita de (J) (V1.1) <= the game halts after a while; 0xad 0xff
|
||||
2 N33 Wolfenstein 3D (U)
|
||||
2 N1 Yoshi's Safari (U) <= I don't have a Super Scope...; (0xad) 0x29
|
||||
2 N2 Ys V - Expert (J)
|
||||
|
||||
EOF
|
||||
@@ -1,419 +0,0 @@
|
||||
A Super Wild Card compatibility list
|
||||
Version: 1.27
|
||||
Author: dbjh "of uCON64" with great help from CL "of NSRT" and The Dumper
|
||||
Date: 30 November 2003
|
||||
Hardware: Super Wild Card 2.8cc 32 Mbit PAL
|
||||
Software: uCON64 1.9.8-3
|
||||
|
||||
|
||||
Legend:
|
||||
0 = seems to work without modification
|
||||
1 = needs crack (uCON64 option -k)
|
||||
2 = needs NTSC/PAL fix (uCON64 option -f)
|
||||
3 = needs backup unit header fix
|
||||
4 = seems to work, but doesn't work correctly
|
||||
5 = music doesn't work
|
||||
6 = copy protection screen
|
||||
7 = wrong television standard (NTSC/PAL) screen
|
||||
8 = corrupted/distorted graphics
|
||||
9 = doesn't work
|
||||
|
||||
|
||||
Comment:
|
||||
I use the word seems, because I have tested most games only for a few minutes
|
||||
or so. Even for games that I played from the beginning till the end I can't be
|
||||
sure if they run as they do from a cartridge.
|
||||
Of course I tried to crack or fix the games that displayed a copy protection
|
||||
screen. The games that have that code can't be cracked with uCON64.
|
||||
Non-playing music seems to be a BS-specific problem.
|
||||
For some games I put an extra comment after the character sequence "<=". In
|
||||
some comments I mention the so-called emulation mode select byte. This is the
|
||||
byte at offset 2 in the header. You can check the value of the emulation mode
|
||||
select byte by passing the command line option -dbuh to uCON64. You can change
|
||||
it with a hex(adecimal) editor or by using the uCON64 option -poke (new in
|
||||
version 1.9.8beta8). For example, to change the emulation mode select byte for
|
||||
Mickey to Donald Magical Adventure 3 (J).swc you would type:
|
||||
ucon64 -poke=2:1c "Mickey to Donald Magical Adventure 3 (J).swc"
|
||||
I have sent all games to the Super Wild Card via a parallel cable. Note that
|
||||
for LoROM games that don't use SRAM uCON64 adjusts the emulation mode select
|
||||
byte before sending the game. This causes that some games don't have code 3,
|
||||
because uCON64 already makes the required modification. For example, if Addams
|
||||
Family Values is loaded from diskette the emulation mode select byte should
|
||||
have the value 0x2c instead of the value 0x0c (before the file is split).
|
||||
For games marked with an asterisk uCON64 1.9.8-3 is required (or an updated
|
||||
version of snescopy.txt and/or snesntsc.txt/snespal.txt).
|
||||
|
||||
|
||||
Code Game
|
||||
0 - 7th Saga, The (U)
|
||||
0 - AAAHH!!! Real Monsters (U)
|
||||
8 + 9 - Ace wo Nerae! (J) <= it does work with Super Mario Kart (E) plugged in
|
||||
0 - ActRaiser 2 (E)
|
||||
4 - ActRaiser 2 (U) <= level(s?) (Industen) can't be entered
|
||||
0 - ActRaiser (U)
|
||||
0 - Addams Family, The (E)
|
||||
0 - Addams Family, The - Pugsley's Scavenger Hunt (Beta)
|
||||
0 - Addams Family, The - Pugsley's Scavenger Hunt (E)
|
||||
0 - Addams Family Values (E)
|
||||
0 - Adventures of Batman & Robin, The (E)
|
||||
0 - Aladdin (E)
|
||||
0 - Alcahest (J)
|
||||
0 - Alfred Chicken (E) (4285)
|
||||
0 - Alfred Chicken (E) (6937)
|
||||
0 - Alfred Chicken (U)
|
||||
0 - Alien 3 (E)
|
||||
0 - Alien vs. Predator (U)
|
||||
0 - Another World (E)
|
||||
0 - Arabian Nights - Sabaku no Seirei Ou (J)
|
||||
0 - Arcade's Greatest Hits (E)
|
||||
0 - Axelay (E)
|
||||
0 - Bahamut Lagoon (J)
|
||||
0 - Bastard!! Ankoku no Hakai-shin (J)
|
||||
0 - Batman Returns (E)
|
||||
0 - Batman Returns (J)
|
||||
3 - Batman - Revenge of the Joker (U) <= emulation mode select byte: 0x0c
|
||||
0 - Battletoads & Double Dragon - The Ultimate Team (U)
|
||||
0 - Battletoads in Battlemaniacs (U) (26454)
|
||||
0 - Beauty and the Beast (E)
|
||||
0 - Bishoujo Senshi Sailor Moon (J)
|
||||
0 - Brawl Brothers (U)
|
||||
1 - Breath of Fire II (E)
|
||||
0 - Breath of Fire (U)
|
||||
9 - BS Bandai Satellaview-X BIOS
|
||||
0 - BS Chrono Trigger - Character Library (J)
|
||||
0 - BS Chrono Trigger - Jet Bike Special (J)
|
||||
0 - BS Chrono Trigger - Music Library (J)
|
||||
8 - BS Dan Dan Belt Conveyor Ukulele no Maki (J) (NG-Dump Known)
|
||||
0 - BS Dr. Mario (J)
|
||||
0 - BS Dynami Tracer (J)
|
||||
0 - BS F-Zero Grand Prix 2 (J)
|
||||
0 - BS Koi ha Balance - Battle of Lovers (J)
|
||||
5 - BS Mario Collection 3 (J)
|
||||
8 - BS Pokekame Magajin (J)
|
||||
9 - BS Radical Dreamers (J) [f1] <= with the translation patch it does work
|
||||
9 - BS Radical Dreamers (J) <= idem
|
||||
0 - BS Super Earth Defense Force (J)
|
||||
0 - BS Super Famicom Wars (J) [h1]
|
||||
0 - BS Super Famicom Wars (J)
|
||||
5 - BS Super Mario USA 4 (J)
|
||||
8 - BS Treasure Conflix (J)
|
||||
0 - BS Wai Wai Check 3-7th (J)
|
||||
0 - BS Wario no Mori (J)
|
||||
0 - BS Yoshi no Panepon (J)
|
||||
0 - BS Zelda no Densetsu - Kamigami no Triforce (J)
|
||||
9 - BS Zelda no Densetsu Kodai no Sekiban Dai 1 Hanashi (J)
|
||||
9 - BS Zelda no Densetsu Kodai no Sekiban Dai 3 Hanashi (J)
|
||||
1 - BS Zelda no Densetsu Remix (J)
|
||||
0 - BS Zootto Mahjong! Event Version (J)
|
||||
0 - Bubsy II (U)
|
||||
0 - Bubsy in Claws Encounters of the Furred Kind (E)
|
||||
0 - Castlevania - Vampire's Kiss (E)
|
||||
0 - Choh Makai-Mura (J)
|
||||
0 - Choplifter III (U) (30545)
|
||||
0 - Chou Jikuu Yousai Macross - Scrambled Valkyrie (J)
|
||||
0 - Chrono Trigger - Kurono Toriga (J)
|
||||
0 - Chrono Trigger (U)
|
||||
0 - Chuck Rock (U)
|
||||
0 - Clay Fighter 2 - Judgment Clay (E)
|
||||
0 - Clay Fighter (E)
|
||||
7 - Clay Fighter (U)
|
||||
2 - Clock Tower (J)
|
||||
0 - Contra III - The Alien Wars (U)
|
||||
0 - Cybernator (U)
|
||||
0 - Daffy Duck - The Marvin Missions (U)
|
||||
7 - Dai-3-Ji Super Robot Taisen (J)
|
||||
9 - Daikaijuu Monogatari 2 (J) <= works on an SWC DX2 64 Mbit PAL
|
||||
0 - Darius Twin (E)
|
||||
0 - Darius Twin (U)
|
||||
1 + 2 - Demon's Crest (U)
|
||||
0 - Der Langrisser (J) (V1.1)
|
||||
0 - Desert Strike - Return to the Gulf (U)
|
||||
9 - Dirt Trax FX (E)
|
||||
0 - Donald Duck Mahou no Boushi (J)
|
||||
1 - Donkey Kong Country 2 - Diddy's Kong Quest (E)
|
||||
1+2+4 - Donkey Kong Country 2 - Diddy's Kong Quest (U) (V1.1) <= can't get past the first level
|
||||
1 - Donkey Kong Country 3 - Dixie Kong's Double Trouble (E)
|
||||
0 - Donkey Kong Country - Competition Cartridge (U)
|
||||
1 - Donkey Kong Country (E) (V1.0)
|
||||
1 - Donkey Kong Country (E) (V1.1)
|
||||
1 + 2 - Donkey Kong Country (U) (V1.0)
|
||||
1 + 2 - Donkey Kong Country (U) (V1.1)
|
||||
9 - Doom (U)
|
||||
0 - Doraemon - Nobita to Yosei no Kuni (J)
|
||||
0 - Dragon Quest I & II (J)
|
||||
0 - Dragon Quest III (J)
|
||||
0 - Dragon Quest VI (J)
|
||||
0 - Dragon Quest V (J)
|
||||
0 - Dragon's Lair (Beta)
|
||||
0 - Dragon's Lair (E)
|
||||
0 - Dragon - The Bruce Lee Story (E) [a1]
|
||||
2 - Dragon - The Bruce Lee Story (U)
|
||||
2 - Dr. Mario (J) (NP)
|
||||
2 - Dual Orb II (J)
|
||||
1 + 2 - Earthbound (U)
|
||||
0 - Earthworm Jim 2 (U)
|
||||
0 - Earthworm Jim (U)
|
||||
0 - Eek! The Cat (E)
|
||||
0 - E.V.O. Search For Eden (U)
|
||||
0 - F-1 Grand Prix (J)
|
||||
8 + 9 - F1 ROC II - Race of Champions (U) <= course is not visible
|
||||
0 - Final Fantasy III (U) (V1.0)
|
||||
0 - Final Fantasy III (U) (V1.1)
|
||||
0 - Final Fantasy II (U) (V1.0)
|
||||
0 - Final Fantasy IV (J)
|
||||
0 - Final Fantasy - Mystic Quest (U) (V1.0)
|
||||
0 - Final Fantasy VI (J)
|
||||
0 - Final Fantasy V (J)
|
||||
0 - Final Fight 2 (E)
|
||||
2 + 3 - Final Fight 3 (U) <= emulation mode select byte: 0x1c
|
||||
2 - Final Fight Guy (U)
|
||||
2 + 3 - Final Fight Tough (J) <= emulation mode select byte: 0x1c
|
||||
0 - Final Fight (U)
|
||||
0 - Flashback (E) (M2)
|
||||
0 - Frogger (U)
|
||||
1*+2* - Front Mission - Gun Hazard (J) <= modification protection; code 0 for NTSC SNES
|
||||
0 - Front Mission (J) (V1.0)
|
||||
0 - F-Zero (E)
|
||||
0 - Ganbare Goemon - Yuki hime Kyuushuutsu emaki (J) (V1.2)
|
||||
0 - Ganpuru - Gunman's Proof (J)
|
||||
2 - Gokujou Parodius (J)
|
||||
0 - Goof Troop (E)
|
||||
0 - Gradius III (U)
|
||||
0 - Harvest Moon (U)
|
||||
9 - Hayazashi Nidan Morita Shogi 2 (J) <= halts on "TRANSMIT WAIT"
|
||||
0 - Hebereke's Popoitto (E)
|
||||
9 - Hoshi no Kirby 3 (J)
|
||||
2 - Illusion of Gaia (U)
|
||||
0 - Illusion of Time (E)
|
||||
0 - International Superstar Soccer Deluxe (E)
|
||||
0 - International Superstar Soccer (E)
|
||||
0 - Itchy & Scratchy Game, The (E) <= was 8 + 9!?
|
||||
2 + 9 Jikkyou Oshaberi Parodius (J)
|
||||
2 - Joe & Mac 2 - Lost in the Tropics (U) (35468)
|
||||
2 - Joe & Mac 2 - Lost in the Tropics (U) (54227)
|
||||
0 - Joe & Mac - Caveman Ninja (E)
|
||||
0 - Joe & Mac (U)
|
||||
0 - J.R.R. Tolkien's The Lord of the Rings - Volume 1 (U)
|
||||
0 - Juutei Senki (J)
|
||||
2 + 9 - Kaite Tukutte Asoberu Dezaemon (J)
|
||||
0 - Kiki KaiKai - Nazo no Kuro Manto (J)
|
||||
1 - Killer Instinct (E)
|
||||
2 - Kirby no Kirakira Kids (J) (NP)
|
||||
1 - Kirby's Dream Course (E)
|
||||
1 + 2 - Kirby's Dream Course (U)
|
||||
9 - Kirby's Dream Land 3 (U)
|
||||
9 - Kirby's Fun Pak (E)
|
||||
0 - Kirby's Ghost Trap (E)
|
||||
0 - Krusty's Super Fun House (U) (V1.1)
|
||||
0 - Legend of The Mystical Ninja, The (E)
|
||||
0 - Legend of Zelda, The - A Link to the Past (E)
|
||||
0 - Legend of Zelda, The - A Link to the Past (U)
|
||||
0 - Lemmings (E)
|
||||
2 - Live A Live (J)
|
||||
0 - Lost Vikings II, The (E)
|
||||
0 - Lost Vikings, The (U)
|
||||
1 - Lufia II - Rise of the Sinistrals (H)
|
||||
1 - Lufia II - Rise of the Sinistrals (U)
|
||||
0 - Lufia & The Fortress of Doom (U)
|
||||
0 - Magical Drop (J)
|
||||
2 - Magical Pop'n (J)
|
||||
0 - Magical Quest Starring Mickey Mouse, The (Beta)
|
||||
0 - Magical Quest Starring Mickey Mouse, The (E)
|
||||
0 - Magical Quest Starring Mickey Mouse, The (U)
|
||||
1 + 2 - Mario no Super Picross (J)
|
||||
0 - Mario Paint (E) <= I don't have a SNES mouse...
|
||||
0 - Mario & Wario (J) <= idem
|
||||
9 - Masou Kishin - Super Robot Taisen Gaiden - The Lord of Elemental (J)
|
||||
2 - Mega Man's Soccer (U)
|
||||
2 - Mega Man VII (U)
|
||||
9 - Mega Man X 2 (E) <= the intro can be viewed
|
||||
2 + 9 - Mega Man X 2 (U) <= idem
|
||||
8 + 9 - Mega Man X 3 (U) <= game can be started, but sprites are not visible
|
||||
1 - Mega Man X (E)
|
||||
1 + 2 - Mega Man X (U) (V1.0)
|
||||
1 + 2 - Mega Man X (U) (V1.1)
|
||||
8 + 9 - Metal Combat - Falcon's Revenge (U) <= sprites are not visible
|
||||
2 - Metal Warriors (U)
|
||||
2 + 3 - Mickey to Donald Magical Adventure 3 (J) <= emulation mode select byte: 0x1c
|
||||
0 - Micro Machines 2 - Turbo Tournament (E)
|
||||
0 - Micro Machines (U)
|
||||
9 - Momotarou Dentetsu Happy (J) <= halts on "SPC7110 check program v3.0"
|
||||
0 - Mortal Kombat 3 (E)
|
||||
0 - Mortal Kombat (Beta)
|
||||
0 - Mortal Kombat (E)
|
||||
0 - Mortal Kombat II (E) (V1.0)
|
||||
0 - Mortal Kombat II (U) (V1.1)
|
||||
0 - NBA Jam (Beta)
|
||||
0 - NBA Jam (E) (V1.0)
|
||||
2 - Ninja Gaiden Trilogy (U)
|
||||
0 - Ogre Battle - The March of the Black Queen (U)
|
||||
0 - Out of This World (U)
|
||||
0 - Parodius Da! Shinwa kara Owarai he (J)
|
||||
0 - Parodius - Non-Sense Fantasy (E)
|
||||
0 - Phalanx - The Enforce Fighter A-144 (E)
|
||||
9 - Pilotwings (E) <= black screen as soon as the real flying begins
|
||||
9 - Pilotwings (U) <= with the DSP patch it does work with Super Mario Kart (E)
|
||||
0 - Pitfall - The Mayan Adventure (Beta)
|
||||
0 - Pitfall - The Mayan Adventure (E)
|
||||
0 - Pocky & Rocky 2 (U) (54250)
|
||||
0 - Pocky & Rocky (E)
|
||||
0 - Pop'n Twinbee (E)
|
||||
0 - Pop'n Twinbee - Rainbow Bell Adventures (E)
|
||||
0 - Primal Rage (E)
|
||||
0 - Primal Rage (U) (With Sound Test)
|
||||
0 - Prince of Persia 2 - The Shadow & The Flame (E)
|
||||
0 - Prince of Persia (E)
|
||||
0 - Prince of Persia (J)
|
||||
0 - Push-Over (E)
|
||||
0 - Puzzle Bobble (E)
|
||||
0 - Ranma Nibun no Ichi - Akanekodan no Hihou (J)
|
||||
0 - Ranma Nibun no Ichi - Hard Battle (U)
|
||||
2 - Robotrek (U)
|
||||
0 - Rockman & Forte (J)
|
||||
0 - Rock N' Roll Racing (E)
|
||||
0 - Romance of the Three Kingdoms IV - Wall of Fire (U)
|
||||
2 - Romancing Sa-Ga 2 (J)
|
||||
2 - Romancing Sa-Ga 3 (J) (V1.0)
|
||||
2 - Romancing Sa-Ga 3 (J) (V1.1)
|
||||
0 - Romancing Sa-Ga (J) (V1.0)
|
||||
0 - RPG Tsukuru 2 (J)
|
||||
0 - R-Type III - The Third Lightning (E) (21451)
|
||||
0 - Rudra no Hihou (J)
|
||||
0 - Sanrio World Smash Ball! (J)
|
||||
0 - Secret of Evermore (U)
|
||||
0 - Secret of Mana (E) (V1.0)
|
||||
0 - Secret of Mana (E) (V1.1)
|
||||
2 - Secret of Mana (U)
|
||||
2 - Seiken Densetsu 2 (J)
|
||||
0 - Seiken Densetsu 3 (J) (Sample)
|
||||
2 - Seiken Densetsu 3 (J)
|
||||
0 - Shadowrun (E)
|
||||
0 - Shin Megami Tensei (J) (V1.0)
|
||||
0 - Sim Ant (U) (37113)
|
||||
0 - Sim City (E)
|
||||
0 - Sim City (U)
|
||||
0 - Simpsons, The - Bart's Nightmare (U)
|
||||
0 - Smash Tennis (E)
|
||||
0 - Smurfs, The (E)
|
||||
0 - Soldiers of Fortune (U)
|
||||
0 - Sonic the Hedgehog (Unl) [p1][h1]
|
||||
0 - Soul Blazer (U)
|
||||
0 - Spider-Man and the X-Men in Arcade's Revenge (E)
|
||||
9 - Star Fox 2 (Beta)
|
||||
9 - Star Fox 2 (Beta TD)
|
||||
9 - Star Fox Super Weekend Competition (U)
|
||||
9 - Star Fox (U) (V1.0)
|
||||
9 - Star Fox (U) (V1.2)
|
||||
9 - Star Ocean (J)
|
||||
9 - StarWing (E) (V1.0)
|
||||
9 - StarWing (E) (V1.1)
|
||||
9 - Street Fighter Alpha 2 (E) [b1]
|
||||
9 - Street Fighter Alpha 2 (E)
|
||||
9 - Street Fighter Alpha 2 (U)
|
||||
0 - Street Fighter II Champ. Edition (Hack)
|
||||
0 - Street Fighter II - The World Warrior (E)
|
||||
0 - Street Fighter II - The World Warrior (U)
|
||||
0 - Street Fighter II Turbo (E) (V1.1)
|
||||
2 - Street Fighter II Turbo (U)
|
||||
9 - Street Fighter Zero 2 (J)
|
||||
0 - Street Racer (Beta)
|
||||
0 - Street Racer (E)
|
||||
0 - Strike Gunner (E)
|
||||
9 - Stunt Race FX (E)
|
||||
0 - Sunset Riders (E)
|
||||
0 - Super Adventure Island II (U)
|
||||
0 - Super Adventure Island (U)
|
||||
0 - Super Aleste (E)
|
||||
0 - Super Aleste (J)
|
||||
0 - Super Aleste (J) [t1]
|
||||
0 - Super Battletank - War in the Gulf (U) (V1.0)
|
||||
0 - Super Bomberman 2 (E)
|
||||
0 - Super Bomberman 3 (E)
|
||||
0 - Super Bomberman 4 (J)
|
||||
0 - Super Bomberman 5 (J)
|
||||
0 - Super Bomberman (E)
|
||||
0 - Super Castlevania IV (E)
|
||||
0 - Super Earth Defense Force (E)
|
||||
0 - Super Famicom Wars (J) (NP)
|
||||
0 - Super Ghouls 'N Ghosts (E)
|
||||
1 - Super Mario All-Stars (E)
|
||||
1 + 2 - Super Mario All-Stars (U)
|
||||
1 - Super Mario All-Stars & World (E)
|
||||
1 + 2 - Super Mario All-Stars & World (U)
|
||||
1 + 2 - Super Mario Collection (J) (V1.1)
|
||||
9 - Super Mario Kart (E) <= it does work with Super Mario Kart (E) plugged in
|
||||
9 - Super Mario Kart (U) <= idem
|
||||
9 - Super Mario RPG (J) (V1.0)
|
||||
9 - Super Mario RPG (J) (V1.1) (NG-Dump Known)
|
||||
9 - Super Mario RPG - Legend of the Seven Stars (U)
|
||||
9 - Super Mario World 2 - Yoshi's Island (E) (V1.0)
|
||||
0 - Super Mario World (E) (V1.1)
|
||||
0 - Super Mario World (U)
|
||||
1 - Super Metroid (E)
|
||||
1 + 2 - Super Metroid (JU)
|
||||
0 - Super NES Super Scope 6 (U) <= I don't have a Super Scope...
|
||||
0 - Super Off Road (U)
|
||||
0 - Super Power League 3 (J)
|
||||
9 - Super Power League 4 (J) <= halts on "SPC7110 check program v3.0"
|
||||
0 - Super Probotector - The Alien Rebels (E)
|
||||
0 - Super Punch-Out!! (U)
|
||||
0 - Super Puyo Puyo (J) (V1.2)
|
||||
0 - Super R-Type (E)
|
||||
0 - Super R-Type (U)
|
||||
0 - Super Smash T.V. (E)
|
||||
0 - Super Smash T.V. (U)
|
||||
0 - Super Star Wars (E)
|
||||
0 - Super Star Wars - Return of the Jedi (E)
|
||||
0 - Super Star Wars - The Empire Strikes Back (Beta)
|
||||
0 - Super Star Wars - The Empire Strikes Back (E)
|
||||
0 - Super Star Wars - The Empire Strikes Back (U) (V1.1)
|
||||
0 - Super Star Wars (U) (31438)
|
||||
0 - Super Street Fighter II - The New Challengers (E)
|
||||
0 - Super Tennis (E) (V1.0)
|
||||
0 - Super Turrican (E)
|
||||
0 - Syndicate (E)
|
||||
0 - T2 - The Arcade Game (U)
|
||||
0 - Tactics Ogre - Let Us Cling Together (J) (V1.2)
|
||||
9 - Tales of Phantasia (J) <= works on an SWC DX2 64 Mbit PAL
|
||||
0 - Teenage Mutant Hero Turtles IV - Turtles in Time (E)
|
||||
0 - Teenage Mutant Hero Turtles - Tournament Fighters (E)
|
||||
0 - Teenage Mutant Ninja Turtles IV - Turtles in Time (A)
|
||||
0 - Teenage Mutant Ninja Turtles IV - Turtles in Time (Beta)
|
||||
0 - Teenage Mutant Ninja Turtles - Turtles in Time (J)
|
||||
0 - Tenchi Muyou! Game Hen (J)
|
||||
9 - Tengai Makyou Zero (J)
|
||||
9 - Tengai Makyou Zero - Shounen Jump no Sho (J)
|
||||
0 - Terranigma (E)
|
||||
0 - Terranigma (S)
|
||||
0 - Test Drive II - The Duel (U) (20429)
|
||||
1 - Tetris Attack (E)
|
||||
1 + 2 - Tetris Attack (U)
|
||||
0 - Theme Park (E)
|
||||
0 - Thoroughbred Breeder III (J)
|
||||
0 - Tiny Toon Adventures - Buster Busts Loose! (E)
|
||||
2+8+9 - Tokimeki Memorial - Densetsu no Ki no Shita de (J) (V1.1) <= the game halts after a while
|
||||
0 - Tom & Jerry (U)
|
||||
0 - Top Racer (J)
|
||||
0 - Treasure Hunter G (J)
|
||||
0 - Ultimate Mortal Kombat 3 (U)
|
||||
0 - Ultima VII - The Black Gate (Beta)
|
||||
0 - Ultima VII - The Black Gate (U)
|
||||
1 - Uniracers (U)
|
||||
1 - Unirally (E)
|
||||
0 - U.N. Squadron (E)
|
||||
9 - Vortex (E)
|
||||
0 - Wario's Woods (U)
|
||||
0 - Wolfenstein 3D (E)
|
||||
2 - Wolfenstein 3D (U)
|
||||
0 - Wolverine - Adamantium Rage (U)
|
||||
0 - Worms (E)
|
||||
0 - WWF Super Wrestlemania (E)
|
||||
9 - X-Band Modem BIOS (U)
|
||||
0 - X-Men - Mutant Apocalypse (E)
|
||||
2 - Yoshi's Safari (U) <= I don't have a Super Scope...
|
||||
2 - Ys V - Expert (J)
|
||||
2 - Yuu Yuu Hakusho - Tokubetsuhen (J)
|
||||
0 - Zelda no Densetsu - Kamigami no Triforce (J) (V1.0)
|
||||
0 - Zombies (E)
|
||||
|
||||
EOF
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
backup.h - single header file for all backup unit functions
|
||||
|
||||
Copyright (c) 2003 NoisyB <noisyb@gmx.net>
|
||||
|
||||
|
||||
This program 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#ifndef BACKUP_H
|
||||
#define BACKUP_H
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_PARALLEL
|
||||
#include "cd64.h"
|
||||
#include "cmc.h"
|
||||
#include "dex.h"
|
||||
#include "doctor64.h"
|
||||
#include "doctor64jr.h"
|
||||
#include "fal.h"
|
||||
//#include "ffe.h"
|
||||
#include "fig.h"
|
||||
#include "gbx.h"
|
||||
#include "gd.h"
|
||||
#include "interceptor.h"
|
||||
#include "lynxit.h"
|
||||
#include "mccl.h"
|
||||
#include "mcd.h"
|
||||
#include "md-pro.h"
|
||||
#include "mgd.h"
|
||||
#include "msg.h"
|
||||
#include "pce-pro.h"
|
||||
#include "pl.h"
|
||||
//#include "psxpblib.h"
|
||||
#include "sflash.h"
|
||||
#include "smc.h"
|
||||
#include "smd.h"
|
||||
#include "smsgg-pro.h"
|
||||
#include "ssc.h"
|
||||
#include "swc.h"
|
||||
#include "ufo.h"
|
||||
#include "yoko.h"
|
||||
#include "z64.h"
|
||||
#endif // USE_PARALLEL
|
||||
#if defined USE_PARALLEL || defined USE_USB
|
||||
#include "f2a.h"
|
||||
#endif
|
||||
|
||||
#endif // BACKUP_H
|
||||
@@ -1,768 +0,0 @@
|
||||
/*
|
||||
cartlib.c - Flash Linker Advance support for uCON64
|
||||
|
||||
Copyright (c) 2001 Jeff Frohwein
|
||||
Copyright (c) 2002 - 2004 dbjh
|
||||
|
||||
|
||||
This program 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef USE_PARALLEL
|
||||
|
||||
// *** GBA flash cart support routines in GCC ***
|
||||
// This library allows programming FA/Visoly (both Turbo
|
||||
// and non-Turbo) and official Nintendo flash carts. They
|
||||
// can be used with the Flash Linker or can be called
|
||||
// from GBA code to allow in-system flash cart programming.
|
||||
// NOTE: ALL OF THESE ROUTINES MUST BE LOCATED IN GBA RAM
|
||||
// IF THIS LIBRARY IS USED FOR IN-SYSTEM PROGRAMMING.
|
||||
//
|
||||
// by Jeff Frohwein, Started 2001-Aug-29
|
||||
//
|
||||
// v1.0 - 2001-Sept-25 - Original release
|
||||
// v1.1 - 2001-Nov-13 - Slightly modified SetVisolyBackupRWMode by removing >>1.
|
||||
//
|
||||
// Routines -
|
||||
//
|
||||
// void SetFAFlashRWMode (void)
|
||||
//
|
||||
// Used to enable modifications of FA/Visoly cart flash chip(s)
|
||||
// and also used for CartTypeDetect routine. YOU MUST CALL THIS
|
||||
// ROUTINE BEFORE USING ANY OF THE OTHER FA/VISOLY ROUTINES.
|
||||
//
|
||||
// u8 CartTypeDetect (void)
|
||||
// Return a value indicating type of cart installed:
|
||||
// 0x00 = Hudson Cart, 0x2e = Standard ROM
|
||||
// 0xe2 = N Flash Cart, 0xff = Unknown
|
||||
// 0x17 = FA 64M, 0x96 = Turbo FA 64M
|
||||
// 0x18 = FA 128M, 0x97 = Turbo FA 128M
|
||||
//
|
||||
// u32 EraseNintendoFlashBlocks (u32 StartAddr, u32 BlockCount)
|
||||
//
|
||||
// Erase official Nintendo flash cart blocks.
|
||||
// Ex: EraseNintendoFlashBlocks (0x8000000, 1); // erase block 1
|
||||
// EraseNintendoFlashBlocks (0x8010000, 2); // erase blocks 2 & 3
|
||||
//
|
||||
// u32 EraseNonTurboFABlocks (u32 StartAddr, u32 BlockCount)
|
||||
//
|
||||
// Erase older (non-Turbo) Visoly flash cart blocks.
|
||||
// Ex: EraseNonTurboFABlocks (0x8000000, 1); // erase block 1
|
||||
// EraseNonTurboFABlocks (0x8020000, 2); // erase blocks 2 & 3
|
||||
//
|
||||
// u32 EraseTurboFABlocks (u32 StartAddr, u32 BlockCount)
|
||||
//
|
||||
// Erase newer (Turbo) Visoly flash cart blocks.
|
||||
// Ex: EraseTurboFABlocks (0x8000000, 1); // erase block 1
|
||||
// EraseTurboFABlocks (0x8040000, 2); // erase blocks 2 & 3
|
||||
//
|
||||
// u32 WriteNintendoFlashCart (u32 SrcAddr, u32 FlashAddr, u32 Length)
|
||||
//
|
||||
// Write 2 x Length bytes to official Nintendo flash cart.
|
||||
// Ex: WriteNintendoFlashCart (SrcAddr, 0x8000000, 2) // write 4 bytes
|
||||
//
|
||||
// u32 WriteNonTurboFACart (u32 SrcAddr, u32 FlashAddr, u32 Length)
|
||||
//
|
||||
// Write 32 x Length bytes to older (non-Turbo) Visoly flash cart.
|
||||
// Ex: WriteNonTurboFACart (SrcAddr, 0x8000000, 2) // write 64 bytes
|
||||
//
|
||||
// u32 WriteTurboFACart (u32 SrcAddr, u32 FlashAddr, u32 Length)
|
||||
//
|
||||
// Write 64 x Length bytes to newer (Turbo) Visoly flash cart.
|
||||
// Ex: WriteTurboFACart (SrcAddr, 0x8000000, 2) // write 128 bytes
|
||||
//
|
||||
// To reduce the library size and remove support for any
|
||||
// of the following types, comment out one or more of
|
||||
// the following lines using //
|
||||
#define NONTURBO_FA_SUPPORT 1 // Visoly Non-Turbo flash carts
|
||||
#define TURBO_FA_SUPPORT 1 // Visoly Turbo flash carts
|
||||
#define NOA_FLASH_CART_SUPPORT 1 // Official Nintendo flash carts
|
||||
//#define SET_CL_SECTION 1 // Enable setting code section for cartlib
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
#ifdef TURBO_FA_SUPPORT
|
||||
#define COMMON_FA_SUPPORT 1
|
||||
#endif
|
||||
#ifdef NONTURBO_FA_SUPPORT
|
||||
#define COMMON_FA_SUPPORT 1
|
||||
#endif
|
||||
|
||||
#ifdef FLINKER
|
||||
// FLinker programming defines
|
||||
#define _MEM_INC 1
|
||||
#define FP_TIMEOUT1 0x4000
|
||||
#define FP_TIMEOUT2 0x8000
|
||||
#define FP_TIMEOUT3 0x80000
|
||||
#define _CART_START 0
|
||||
#define FLINKER_SET l40226c ()
|
||||
#define READ_NTURBO_SR(a,b) WriteFlash (a, INTEL28F_READSR); \
|
||||
outpb (SPPCtrlPort, 0); \
|
||||
b = (PPReadWord() & 0xff)
|
||||
#define READ_NTURBO_S(a) outpb (SPPCtrlPort, 0); \
|
||||
a = (PPReadWord() & 0xff)
|
||||
#define READ_TURBO_SR(a) WriteFlash (0, INTEL28F_READSR); \
|
||||
PPWriteWord (INTEL28F_READSR); \
|
||||
outpb (SPPCtrlPort, 0); \
|
||||
a = PPReadWord() & 0xff; \
|
||||
a += (PPReadWord() & 0xff) << 8
|
||||
#define READ_TURBO_S(a) outpb (SPPCtrlPort, 0); \
|
||||
a = PPReadWord() & 0xff; \
|
||||
a += (PPReadWord() & 0xff) << 8
|
||||
#define READ_TURBO_S2(a,b,c) outpb (SPPCtrlPort, 0); \
|
||||
b = PPReadWord () & 0x80; \
|
||||
c = PPReadWord () & 0x80
|
||||
#define WRITE_FLASH_NEXT(a,b) PPWriteWord (b)
|
||||
#define SET_CART_ADDR(a) SetCartAddr (a); \
|
||||
l4021d0 (3)
|
||||
#define CTRL_PORT_0 outpb (SPPCtrlPort, 0)
|
||||
#define CTRL_PORT_1 outpb (SPPCtrlPort, 1)
|
||||
|
||||
void
|
||||
WriteRepeat (int addr, int data, int count)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < count; i++)
|
||||
WriteFlash (addr, data);
|
||||
}
|
||||
|
||||
#else
|
||||
// GBA in-system programming defines
|
||||
#define _MEM_INC 2
|
||||
#define FP_TIMEOUT1 0x4000 // Probably could be MUCH smaller
|
||||
#define FP_TIMEOUT2 0x8000 // Probably could be MUCH smaller
|
||||
#define FP_TIMEOUT3 0x80000 // Probably could be MUCH smaller
|
||||
#define INTEL28F_BLOCKERASE 0x20
|
||||
#define INTEL28F_CLEARSR 0x50
|
||||
#define INTEL28F_CONFIRM 0xD0
|
||||
#define INTEL28F_QUIRY 0x98
|
||||
#define INTEL28F_READARRAY 0xff
|
||||
#define INTEL28F_READSR 0x70
|
||||
#define INTEL28F_RIC 0x90
|
||||
#define INTEL28F_WRTOBUF 0xe8
|
||||
|
||||
#define SHARP28F_BLOCKERASE 0x20
|
||||
#define SHARP28F_CONFIRM 0xD0
|
||||
#define SHARP28F_WORDWRITE 0x10
|
||||
#define SHARP28F_READARRAY 0xff
|
||||
// typedef volatile unsigned char vu8;
|
||||
// typedef volatile unsigned short int vu16;
|
||||
// typedef volatile unsigned int vu32;
|
||||
// typedef volatile unsigned long long int vu64;
|
||||
|
||||
// typedef unsigned char u8;
|
||||
// typedef unsigned short int u16;
|
||||
// typedef unsigned int u32;
|
||||
// typedef unsigned long long int u64;
|
||||
|
||||
#define _CART_START 0x8000000
|
||||
#define _BACKUP_START 0xe000000
|
||||
#define FLINKER_SET {}
|
||||
#define READ_NTURBO_SR(a,b) *(vu16 *)a = INTEL28F_READSR; \
|
||||
b = *(vu16 *)a
|
||||
#define READ_NTURBO_S(a) a = *(vu16 *)_CART_START
|
||||
#define READ_TURBO_SR(a) *(vu16 *)_CART_START = INTEL28F_READSR; \
|
||||
*(vu16 *)(_CART_START+2) = INTEL28F_READSR; \
|
||||
a = *(vu16 *)_CART_START & 0xff; \
|
||||
a += (*(vu16 *)(_CART_START+2) & 0xff) << 8
|
||||
#define READ_TURBO_S(a) a = *(vu16 *)_CART_START & 0xff; \
|
||||
a += (*(vu16 *)(_CART_START+2) & 0xff) << 8
|
||||
#define READ_TURBO_S2(a,b,c) b = *(vu16 *)a & 0x80; \
|
||||
c = *(vu16 *)(a+2) & 0x80
|
||||
#define WRITE_FLASH_NEXT(a,b) WriteFlash (a, b)
|
||||
#define SET_CART_ADDR(a) {}
|
||||
#define CTRL_PORT_0 {}
|
||||
#define CTRL_PORT_1 {}
|
||||
#define CL_SECTION __attribute__ ((section (".iwram")))
|
||||
|
||||
#ifdef SET_CL_SECTION
|
||||
// Prototypes to allow placing routines in any section
|
||||
void
|
||||
WriteFlash (u32 addr, u16 data)
|
||||
CL_SECTION;
|
||||
u16 ReadFlash (u32 addr) CL_SECTION;
|
||||
void WriteRepeat (u32 addr, u16 data, u16 count) CL_SECTION;
|
||||
void VisolyModePreamble (void) CL_SECTION;
|
||||
void SetVisolyFlashRWMode (void) CL_SECTION;
|
||||
void SetVisolyBackupRWMode (int i) CL_SECTION;
|
||||
u8 CartTypeDetect (void) CL_SECTION;
|
||||
u32 EraseNintendoFlashBlocks (u32 StartAddr, u32 BlockCount) CL_SECTION;
|
||||
u32 EraseNonTurboFABlocks (u32 StartAddr, u32 BlockCount) CL_SECTION;
|
||||
u32 EraseTurboFABlocks (u32 StartAddr, u32 BlockCount) CL_SECTION;
|
||||
u32 WriteNintendoFlashCart (u32 SrcAddr, u32 FlashAddr,
|
||||
u32 Length) CL_SECTION;
|
||||
u32 WriteNonTurboFACart (u32 SrcAddr, u32 FlashAddr,
|
||||
u32 Length) CL_SECTION;
|
||||
u32 WriteTurboFACart (u32 SrcAddr, u32 FlashAddr, u32 Length) CL_SECTION;
|
||||
#endif
|
||||
|
||||
void WriteFlash (u32 addr, u16 data)
|
||||
{
|
||||
*(vu16 *) addr = data;
|
||||
}
|
||||
|
||||
u16
|
||||
ReadFlash (u32 addr)
|
||||
{
|
||||
return (*(vu16 *) addr);
|
||||
}
|
||||
|
||||
void
|
||||
WriteRepeat (u32 addr, u16 data, u16 count)
|
||||
{
|
||||
u16 i;
|
||||
for (i = 0; i < count; i++)
|
||||
*(vu16 *) (_CART_START + (addr << 1)) = data;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef COMMON_FA_SUPPORT
|
||||
void
|
||||
VisolyModePreamble (void) // 402438
|
||||
{
|
||||
FLINKER_SET;
|
||||
WriteRepeat (0x987654, 0x5354, 1);
|
||||
WriteRepeat (0x12345, 0x1234, 500);
|
||||
WriteRepeat (0x7654, 0x5354, 1);
|
||||
WriteRepeat (0x12345, 0x5354, 1);
|
||||
WriteRepeat (0x12345, 0x5678, 500);
|
||||
WriteRepeat (0x987654, 0x5354, 1);
|
||||
WriteRepeat (0x12345, 0x5354, 1);
|
||||
WriteRepeat (0x765400, 0x5678, 1);
|
||||
WriteRepeat (0x13450, 0x1234, 1);
|
||||
WriteRepeat (0x12345, 0xabcd, 500);
|
||||
WriteRepeat (0x987654, 0x5354, 1);
|
||||
}
|
||||
|
||||
void
|
||||
SetVisolyFlashRWMode (void)
|
||||
{
|
||||
VisolyModePreamble ();
|
||||
WriteRepeat (0xf12345, 0x9413, 1);
|
||||
}
|
||||
|
||||
void
|
||||
SetVisolyBackupRWMode (int i) // 402550
|
||||
{
|
||||
VisolyModePreamble ();
|
||||
WriteRepeat (0xa12345, i, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Cart Type Detect
|
||||
// Return a value indicating type of cart installed:
|
||||
// 0xdc = Hudson Cart, 0x2e = Standard ROM Cart
|
||||
// 0xe2 = N Flash Cart, 0xff = Unknown
|
||||
// 0x17 = FA 64M, 0x96 = Turbo FA 64M
|
||||
// 0x18 = FA 128M, 0x97 = Turbo FA 128M
|
||||
|
||||
u8
|
||||
CartTypeDetect (void)
|
||||
{
|
||||
u8 type = 0xff;
|
||||
u16 Manuf, Device;
|
||||
|
||||
WriteFlash (_CART_START, INTEL28F_RIC); // Read Identifier codes from flash.
|
||||
// Works for intel 28F640J3A & Sharp LH28F320BJE.
|
||||
Manuf = ReadFlash (_CART_START);
|
||||
Device = ReadFlash (_CART_START + _MEM_INC);
|
||||
|
||||
switch (Manuf)
|
||||
{
|
||||
case 0: // Hudson Cart
|
||||
type = 0xdc;
|
||||
break;
|
||||
case 0x2e: // Standard ROM
|
||||
type = (u8) Manuf;
|
||||
break;
|
||||
case 0x89: // Intel chips
|
||||
switch (Device)
|
||||
{
|
||||
case 0x16: // i28F320J3A
|
||||
case 0x17: // i28F640J3A
|
||||
case 0x18: // i28F128J3A
|
||||
type = (u8) Device;
|
||||
break;
|
||||
default:
|
||||
// Check to see if this is a Visoly "Turbo" cart
|
||||
Device = ReadFlash (_CART_START + _MEM_INC + _MEM_INC);
|
||||
switch (Device)
|
||||
{
|
||||
case 0x16: // 2 x i28F320J3A
|
||||
case 0x17: // 2 x i28F640J3A
|
||||
case 0x18: // 2 x i28F128J3A
|
||||
type = Device + 0x80;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0xb0: // Sharp chips
|
||||
switch (Device)
|
||||
{
|
||||
case 0xe2:
|
||||
type = (u8) Device;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
WriteFlash (_CART_START, INTEL28F_READARRAY); // Set flash to normal read mode
|
||||
return type;
|
||||
}
|
||||
|
||||
#ifdef NOA_FLASH_CART_SUPPORT
|
||||
// Erase official Nintendo flash cart blocks
|
||||
// Function returns true if erase was successful.
|
||||
// Each block represents 64k bytes.
|
||||
|
||||
u32
|
||||
EraseNintendoFlashBlocks (u32 StartAddr, u32 BlockCount)
|
||||
{
|
||||
int i = 0;
|
||||
int j, k;
|
||||
time_t starttime = time (NULL);
|
||||
|
||||
for (k = 0; k < (int) BlockCount; k++)
|
||||
{
|
||||
i = StartAddr + (k * 32768 * _MEM_INC);
|
||||
|
||||
do
|
||||
{
|
||||
READ_NTURBO_SR (i, j);
|
||||
}
|
||||
while ((j & 0x80) == 0);
|
||||
WriteFlash (i, SHARP28F_BLOCKERASE); // Erase a 64k byte block
|
||||
WriteFlash (i, SHARP28F_CONFIRM); // Comfirm block erase
|
||||
ucon64_gauge (starttime, (k + 1) * 64 * 1024, BlockCount * 64 * 1024);
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
READ_NTURBO_SR (i, j);
|
||||
}
|
||||
while ((j & 0x80) == 0);
|
||||
WriteFlash (i, SHARP28F_READARRAY); // Set normal read mode
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef NONTURBO_FA_SUPPORT
|
||||
// Erase older (non-Turbo) FA/Visoly flash cart blocks
|
||||
// (Single flash chip)
|
||||
// Function returns true if erase was successful.
|
||||
// Each block represents 128k bytes.
|
||||
|
||||
u32
|
||||
EraseNonTurboFABlocks (u32 StartAddr, u32 BlockCount)
|
||||
{
|
||||
u16 k;
|
||||
u16 Ready = 1;
|
||||
u32 i = 0;
|
||||
u32 Timeout;
|
||||
time_t starttime = time (NULL);
|
||||
|
||||
for (k = 0; k < BlockCount; k++)
|
||||
{
|
||||
i = StartAddr + (k * 65536 * _MEM_INC);
|
||||
|
||||
Ready = 0;
|
||||
Timeout = FP_TIMEOUT2;
|
||||
|
||||
while ((Ready == 0) && (Timeout != 0))
|
||||
{
|
||||
READ_NTURBO_SR (_CART_START, Ready);
|
||||
Ready &= 0x80;
|
||||
Timeout--;
|
||||
}
|
||||
|
||||
if (Ready)
|
||||
{
|
||||
WriteFlash (i, INTEL28F_BLOCKERASE); // Erase a 128k byte block
|
||||
Ready = 0;
|
||||
Timeout = FP_TIMEOUT3;
|
||||
|
||||
while ((!Ready) && (Timeout != 0))
|
||||
{
|
||||
READ_NTURBO_S (Ready);
|
||||
Ready = (Ready == 0x80);
|
||||
Timeout--;
|
||||
}
|
||||
|
||||
if (Ready)
|
||||
{
|
||||
WriteFlash (i, INTEL28F_CONFIRM); // Comfirm block erase
|
||||
Ready = 0;
|
||||
Timeout = FP_TIMEOUT3;
|
||||
|
||||
while ((!Ready) && (Timeout != 0))
|
||||
{
|
||||
READ_NTURBO_S (Ready);
|
||||
Ready = (Ready == 0x80);
|
||||
Timeout--;
|
||||
}
|
||||
|
||||
if (Ready)
|
||||
{
|
||||
READ_NTURBO_SR (_CART_START, Ready);
|
||||
Ready = (Ready == 0x80);
|
||||
|
||||
if (!Ready)
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
ucon64_gauge (starttime, (k + 1) * 128 * 1024,
|
||||
BlockCount * 128 * 1024);
|
||||
}
|
||||
|
||||
if (!Ready)
|
||||
{
|
||||
WriteFlash (i, INTEL28F_CLEARSR); // Clear flash status register
|
||||
}
|
||||
|
||||
WriteFlash (i, INTEL28F_READARRAY); // Set flash to normal read mode
|
||||
WriteFlash (i, INTEL28F_READARRAY); // Set flash to normal read mode
|
||||
|
||||
return Ready != 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TURBO_FA_SUPPORT
|
||||
// Erase newer (Turbo) FA/Visoly flash cart blocks
|
||||
// (Dual chip / Interleave)
|
||||
// Function returns true if erase was successful.
|
||||
// Each block represents 256k bytes.
|
||||
|
||||
u32
|
||||
EraseTurboFABlocks (u32 StartAddr, u32 BlockCount)
|
||||
{
|
||||
u16 j, k;
|
||||
u16 done1, done2;
|
||||
u16 Ready = 1;
|
||||
u32 i = 0;
|
||||
u32 Timeout;
|
||||
time_t starttime = time (NULL);
|
||||
|
||||
for (k = 0; k < BlockCount; k++)
|
||||
{
|
||||
i = StartAddr + (k * 131072 * _MEM_INC);
|
||||
|
||||
Ready = 0;
|
||||
Timeout = FP_TIMEOUT2;
|
||||
|
||||
while ((!Ready) && (Timeout != 0))
|
||||
{
|
||||
READ_TURBO_SR (j);
|
||||
Ready = (j == 0x8080);
|
||||
Timeout--;
|
||||
}
|
||||
|
||||
if (Ready)
|
||||
{
|
||||
done1 = 0;
|
||||
done2 = 0;
|
||||
Ready = 0;
|
||||
Timeout = FP_TIMEOUT3;
|
||||
|
||||
while ((!Ready) && (Timeout != 0))
|
||||
{
|
||||
if (done1 == 0)
|
||||
WriteFlash (i, INTEL28F_BLOCKERASE); // Erase a 128k byte block in flash #1
|
||||
if (done2 == 0)
|
||||
WriteFlash (i + _MEM_INC, INTEL28F_BLOCKERASE); // Erase a 128k byte block in flash #2
|
||||
|
||||
READ_TURBO_S2 (_CART_START, done1, done2);
|
||||
Ready = ((done1 + done2) == 0x100);
|
||||
|
||||
Timeout--;
|
||||
}
|
||||
|
||||
if (Ready)
|
||||
{
|
||||
WriteFlash (i, INTEL28F_CONFIRM); // Comfirm block erase in flash #1
|
||||
WriteFlash (i + _MEM_INC, INTEL28F_CONFIRM); // Comfirm block erase in flash #2
|
||||
|
||||
Ready = 0;
|
||||
Timeout = FP_TIMEOUT3;
|
||||
j = 0;
|
||||
|
||||
while (((j & 0x8080) != 0x8080) && (Timeout != 0))
|
||||
{
|
||||
READ_TURBO_S (j);
|
||||
Ready = (j == 0x8080);
|
||||
|
||||
Timeout--;
|
||||
}
|
||||
|
||||
if (!Ready)
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
ucon64_gauge (starttime, (k + 1) * 256 * 1024,
|
||||
BlockCount * 256 * 1024);
|
||||
}
|
||||
|
||||
if (!Ready)
|
||||
{
|
||||
WriteFlash (i, INTEL28F_CLEARSR);
|
||||
WriteFlash (i + _MEM_INC, INTEL28F_CLEARSR);
|
||||
}
|
||||
|
||||
WriteFlash (_CART_START, INTEL28F_READARRAY);
|
||||
WriteFlash (_CART_START + _MEM_INC, INTEL28F_READARRAY);
|
||||
WriteFlash (_CART_START, INTEL28F_READARRAY);
|
||||
WriteFlash (_CART_START + _MEM_INC, INTEL28F_READARRAY);
|
||||
|
||||
return Ready != 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef NOA_FLASH_CART_SUPPORT
|
||||
// Write 2 x Length bytes to official Nintendo flash cart.
|
||||
// Function returns true if write was successful.
|
||||
|
||||
u32
|
||||
WriteNintendoFlashCart (u32 SrcAddr, u32 FlashAddr, u32 Length)
|
||||
{
|
||||
int j;
|
||||
int LoopCount = 0;
|
||||
u16 *SrcAddr2 = (u16 *)
|
||||
#ifdef __LP64__
|
||||
(u64)
|
||||
#endif
|
||||
SrcAddr;
|
||||
|
||||
while (LoopCount < (int) Length)
|
||||
{
|
||||
do
|
||||
{
|
||||
READ_NTURBO_SR (FlashAddr, j);
|
||||
}
|
||||
while ((j & 0x80) == 0);
|
||||
|
||||
WriteFlash (FlashAddr, SHARP28F_WORDWRITE);
|
||||
WriteFlash (FlashAddr, *SrcAddr2);
|
||||
SrcAddr2 += 2;
|
||||
FlashAddr += _MEM_INC;
|
||||
LoopCount++;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
READ_NTURBO_SR (FlashAddr, j);
|
||||
}
|
||||
while ((j & 0x80) == 0);
|
||||
|
||||
WriteFlash (_CART_START, SHARP28F_READARRAY);
|
||||
// CTRL_PORT_0;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef NONTURBO_FA_SUPPORT
|
||||
// Write 32 x Length bytes to older (non-Turbo) FA/Visoly flash cart.
|
||||
// Function returns true if write was successful.
|
||||
|
||||
u32
|
||||
WriteNonTurboFACart (u32 SrcAddr, u32 FlashAddr, u32 Length)
|
||||
{
|
||||
int Ready = 0;
|
||||
int Timeout = 0;
|
||||
int LoopCount = 0;
|
||||
u16 *SrcAddr2 = (u16 *)
|
||||
#ifdef __LP64__
|
||||
(u64)
|
||||
#endif
|
||||
SrcAddr;
|
||||
|
||||
while (LoopCount < (int) Length)
|
||||
{
|
||||
Ready = 0;
|
||||
Timeout = FP_TIMEOUT1;
|
||||
|
||||
while ((Ready == 0) && (Timeout != 0))
|
||||
{
|
||||
WriteFlash (FlashAddr, INTEL28F_WRTOBUF);
|
||||
READ_NTURBO_S (Ready);
|
||||
Ready &= 0x80;
|
||||
|
||||
Timeout--;
|
||||
}
|
||||
|
||||
if (Ready)
|
||||
{
|
||||
int i;
|
||||
|
||||
WriteFlash (FlashAddr, 15); // Write 15+1 16bit words
|
||||
|
||||
SET_CART_ADDR (FlashAddr);
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
WRITE_FLASH_NEXT (FlashAddr, *SrcAddr2);
|
||||
SrcAddr2 += 2;
|
||||
FlashAddr += _MEM_INC;
|
||||
}
|
||||
|
||||
WRITE_FLASH_NEXT (FlashAddr, INTEL28F_CONFIRM);
|
||||
|
||||
Ready = 0;
|
||||
Timeout = FP_TIMEOUT1;
|
||||
|
||||
while ((Ready == 0) && (Timeout != 0))
|
||||
{
|
||||
READ_NTURBO_SR (_CART_START, i);
|
||||
Ready = i & 0x80;
|
||||
|
||||
Timeout--;
|
||||
}
|
||||
|
||||
if (Ready)
|
||||
{
|
||||
if (i & 0x7f)
|
||||
{
|
||||
// One or more status register error bits are set
|
||||
CTRL_PORT_1;
|
||||
WriteFlash (0, INTEL28F_CLEARSR);
|
||||
Ready = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CTRL_PORT_1;
|
||||
WriteFlash (0, INTEL28F_CLEARSR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
LoopCount++;
|
||||
}
|
||||
WriteFlash (_CART_START, INTEL28F_READARRAY); // Set flash to normal read mode
|
||||
WriteFlash (_CART_START, INTEL28F_READARRAY); // Set flash to normal read mode
|
||||
return Ready != 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TURBO_FA_SUPPORT
|
||||
// Write 64 x Length bytes to newer (Turbo) FA/Visoly flash cart.
|
||||
// Function returns true if write was successful.
|
||||
|
||||
u32
|
||||
WriteTurboFACart (u32 SrcAddr, u32 FlashAddr, u32 Length)
|
||||
{
|
||||
int i, k;
|
||||
int done1, done2;
|
||||
int Timeout;
|
||||
int Ready = 0;
|
||||
int LoopCount = 0;
|
||||
u16 *SrcAddr2 = (u16 *)
|
||||
#ifdef __LP64__
|
||||
(u64)
|
||||
#endif
|
||||
SrcAddr;
|
||||
|
||||
while (LoopCount < (int) Length)
|
||||
{
|
||||
done1 = 0;
|
||||
done2 = 0;
|
||||
Ready = 0;
|
||||
Timeout = 0x4000;
|
||||
|
||||
while ((!Ready) && (Timeout != 0))
|
||||
{
|
||||
if (done1 == 0)
|
||||
WriteFlash (FlashAddr, INTEL28F_WRTOBUF);
|
||||
if (done2 == 0)
|
||||
WriteFlash (FlashAddr + _MEM_INC, INTEL28F_WRTOBUF);
|
||||
|
||||
SET_CART_ADDR (FlashAddr);
|
||||
READ_TURBO_S2 (FlashAddr, done1, done2);
|
||||
|
||||
Ready = ((done1 + done2) == 0x100);
|
||||
|
||||
Timeout--;
|
||||
}
|
||||
|
||||
if (Ready)
|
||||
{
|
||||
WriteFlash (FlashAddr, 15); // Write 15+1 16bit words
|
||||
WRITE_FLASH_NEXT (FlashAddr + _MEM_INC, 15); // Write 15+1 16bit words
|
||||
|
||||
SET_CART_ADDR (FlashAddr);
|
||||
|
||||
for (i = 0; i < 32; i++)
|
||||
{
|
||||
WRITE_FLASH_NEXT (FlashAddr, *SrcAddr2);
|
||||
SrcAddr2 += 2;
|
||||
FlashAddr += _MEM_INC;
|
||||
}
|
||||
WRITE_FLASH_NEXT (FlashAddr, INTEL28F_CONFIRM);
|
||||
WRITE_FLASH_NEXT (FlashAddr + _MEM_INC, INTEL28F_CONFIRM);
|
||||
|
||||
Ready = 0;
|
||||
Timeout = 0x4000;
|
||||
k = 0;
|
||||
|
||||
while (((k & 0x8080) != 0x8080) && (Timeout != 0))
|
||||
{
|
||||
READ_TURBO_S (k);
|
||||
Ready = (k == 0x8080);
|
||||
|
||||
Timeout--;
|
||||
}
|
||||
|
||||
if (!Ready)
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
LoopCount++;
|
||||
}
|
||||
|
||||
WriteFlash (_CART_START, INTEL28F_READARRAY);
|
||||
CTRL_PORT_0;
|
||||
WriteFlash (_CART_START + _MEM_INC, INTEL28F_READARRAY);
|
||||
CTRL_PORT_0;
|
||||
|
||||
if (!Ready)
|
||||
{
|
||||
WriteFlash (_CART_START, INTEL28F_CLEARSR);
|
||||
WriteFlash (_CART_START + _MEM_INC, INTEL28F_CLEARSR);
|
||||
}
|
||||
return Ready != 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // USE_PARALLEL
|
||||
@@ -1,504 +0,0 @@
|
||||
/*
|
||||
cd64.c - CD64 support for uCON64
|
||||
|
||||
Copyright (c) 2004 dbjh
|
||||
|
||||
|
||||
This program 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <ultra64/host/cd64lib.h>
|
||||
#include "misc/misc.h"
|
||||
#include "misc/parallel.h"
|
||||
#ifdef USE_ZLIB
|
||||
#include "misc/archive.h"
|
||||
#endif
|
||||
#include "misc/getopt2.h" // st_getopt2_t
|
||||
#include "ucon64.h"
|
||||
#include "ucon64_dat.h"
|
||||
#include "ucon64_misc.h"
|
||||
#include "cd64.h"
|
||||
|
||||
|
||||
const st_getopt2_t cd64_usage[] =
|
||||
{
|
||||
{
|
||||
NULL, 0, 0, 0,
|
||||
NULL, "CD64"/*"19XX UFO http://www.cd64.com"*/,
|
||||
NULL
|
||||
},
|
||||
#if defined USE_PARALLEL && defined USE_LIBCD64
|
||||
{
|
||||
"xcd64", 0, 0, UCON64_XCD64,
|
||||
NULL, "send/receive ROM to/from CD64; " OPTION_LONG_S "port=PORT\n"
|
||||
"receives automatically (64 Mbits) when ROM does not exist",
|
||||
&ucon64_wf[WF_OBJ_N64_DEFAULT_STOP_NO_ROM]
|
||||
},
|
||||
{
|
||||
"xcd64c", 1, 0, UCON64_XCD64C,
|
||||
"N", "receive N Mbits of ROM from CD64; " OPTION_LONG_S "port=PORT",
|
||||
&ucon64_wf[WF_OBJ_N64_STOP_NO_ROM]
|
||||
},
|
||||
{
|
||||
"xcd64b", 0, 0, UCON64_XCD64B,
|
||||
NULL, "send boot emu to CD64; " OPTION_LONG_S "port=PORT",
|
||||
&ucon64_wf[WF_OBJ_N64_DEFAULT_STOP]
|
||||
},
|
||||
{
|
||||
"xcd64s", 0, 0, UCON64_XCD64S,
|
||||
NULL, "send/receive SRAM to/from CD64; " OPTION_LONG_S "port=PORT\n"
|
||||
"receives automatically when SRAM file does not exist",
|
||||
&ucon64_wf[WF_OBJ_N64_STOP_NO_ROM]
|
||||
},
|
||||
{
|
||||
"xcd64f", 0, 0, UCON64_XCD64F,
|
||||
NULL, "send/receive flash RAM to/from CD64; " OPTION_LONG_S "port=PORT\n"
|
||||
"receives automatically when flash RAM file does not exist",
|
||||
&ucon64_wf[WF_OBJ_N64_STOP_NO_ROM]
|
||||
},
|
||||
{
|
||||
"xcd64e", 0, 0, UCON64_XCD64E,
|
||||
NULL, "send/receive EEPROM data to/from CD64; " OPTION_LONG_S "port=PORT\n"
|
||||
"receives automatically when EEPROM file does not exist",
|
||||
&ucon64_wf[WF_OBJ_N64_STOP_NO_ROM]
|
||||
},
|
||||
{
|
||||
"xcd64m", 1, 0, UCON64_XCD64M,
|
||||
"INDEX", "send/receive memory pack data to/from CD64; " OPTION_LONG_S "port=PORT\n"
|
||||
"INDEX is ignored for CD64 BIOS protocol\n"
|
||||
"receives automatically when memory pack file does not exist",
|
||||
&ucon64_wf[WF_OBJ_N64_STOP_NO_ROM]
|
||||
},
|
||||
{
|
||||
"xcd64p", 1, 0, UCON64_XCD64P,
|
||||
"PROT", "use protocol PROT when communicating with CD64; " OPTION_LONG_S "port=PORT\n"
|
||||
"PROT=0 CD64 BIOS\n"
|
||||
"PROT=1 Ghemor\n"
|
||||
"PROT=2 UltraLink",
|
||||
&ucon64_wf[WF_OBJ_N64_SWITCH]
|
||||
},
|
||||
#endif // USE_PARALLEL && USE_LIBCD64
|
||||
{NULL, 0, 0, 0, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
#if defined USE_PARALLEL && defined USE_LIBCD64
|
||||
|
||||
static time_t cd64_starttime;
|
||||
|
||||
|
||||
static void
|
||||
cd64_progress (uint32_t current, uint32_t total)
|
||||
{
|
||||
ucon64_gauge (cd64_starttime, current, total);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
cd64_notice_helper (FILE *file, const char *prefix, const char *format,
|
||||
va_list argptr)
|
||||
{
|
||||
int n_chars;
|
||||
|
||||
fputs (prefix, file);
|
||||
n_chars = vfprintf (file, format, argptr);
|
||||
fputc ('\n', file);
|
||||
fflush (file);
|
||||
|
||||
return n_chars;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
cd64_notice (const char *format, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
int n_chars;
|
||||
|
||||
va_start (argptr, format);
|
||||
n_chars = cd64_notice_helper (stdout, "NOTE (libcd64): ", format, argptr);
|
||||
va_end (argptr);
|
||||
|
||||
return n_chars;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
cd64_notice2 (const char *format, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
int n_chars;
|
||||
|
||||
va_start (argptr, format);
|
||||
n_chars = cd64_notice_helper (stderr, "ERROR (libcd64): ", format, argptr);
|
||||
va_end (argptr);
|
||||
|
||||
return n_chars;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
fread_wrapper (void *io_id, void *buffer, uint32_t size)
|
||||
{
|
||||
return fread (buffer, 1, size, (FILE *) io_id);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
fwrite_wrapper (void *io_id, void *buffer, uint32_t size)
|
||||
{
|
||||
return fwrite (buffer, 1, size, (FILE *) io_id);
|
||||
}
|
||||
|
||||
|
||||
static int32_t
|
||||
ftell_wrapper (void *io_id)
|
||||
{
|
||||
return (int32_t) ftell ((FILE *) io_id);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
fseek_wrapper (void *io_id, int32_t offset, int whence)
|
||||
{
|
||||
return fseek ((FILE *) io_id, offset, whence);
|
||||
}
|
||||
|
||||
|
||||
static struct cd64_t *
|
||||
cd64_init (void)
|
||||
{
|
||||
struct cd64_t *cd64;
|
||||
#ifdef USE_PPDEV
|
||||
uint16_t port = strtol (&ucon64.parport_dev[strlen (ucon64.parport_dev) - 1], NULL, 10);
|
||||
method_t method = PPDEV;
|
||||
#else
|
||||
uint16_t port = ucon64.parport;
|
||||
method_t method = RAWIO;
|
||||
#endif
|
||||
int is_parallel = 1;
|
||||
|
||||
if ((cd64 = (struct cd64_t *) calloc (1, sizeof (struct cd64_t))) == NULL)
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[BUFFER_ERROR], sizeof (struct cd64_t));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
#ifndef USE_PPDEV
|
||||
if (ucon64.parport == UCON64_UNKNOWN)
|
||||
{
|
||||
fputs ("ERROR: No port or invalid port specified\n"
|
||||
"TIP: Specify one with --port or in the configuration file\n", stderr);
|
||||
exit (1);
|
||||
}
|
||||
if (port >= 0x300 && port <= 0x330)
|
||||
is_parallel = 0;
|
||||
#endif
|
||||
|
||||
cd64->notice_callback = cd64_notice;
|
||||
cd64->notice_callback2 = cd64_notice2;
|
||||
|
||||
if (!cd64_create (cd64, method, port, (protocol_t) ucon64.io_mode, is_parallel))
|
||||
{
|
||||
fputs ("ERROR: Could not initialise libcd64\n", stderr);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
cd64->read_callback = fread_wrapper; // actually f*2(), if zlib
|
||||
cd64->write_callback = fwrite_wrapper; // support is enabled
|
||||
cd64->tell_callback = ftell_wrapper;
|
||||
cd64->seek_callback = fseek_wrapper;
|
||||
cd64->progress_callback = cd64_progress;
|
||||
strcpy (cd64->io_driver_dir, ucon64.configdir);
|
||||
|
||||
// parport_print_info() displays a reasonable message (even if we're using a
|
||||
// comms link)
|
||||
parport_print_info ();
|
||||
|
||||
if (!cd64->devopen (cd64))
|
||||
{
|
||||
fputs ("ERROR: Could not open I/O device for CD64\n", stderr);
|
||||
exit (1);
|
||||
}
|
||||
#if defined __unix__ && !defined __MSDOS__
|
||||
drop_privileges ();
|
||||
#endif
|
||||
|
||||
return cd64;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cd64_read_rom (const char *filename, int size)
|
||||
{
|
||||
FILE *file;
|
||||
struct cd64_t *cd64 = cd64_init ();
|
||||
|
||||
if ((file = fopen (filename, "w+b")) == NULL) // cd64_download_cart() also
|
||||
{ // reads from file
|
||||
fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], filename);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
cd64_starttime = time (NULL);
|
||||
cd64_download_cart (cd64, file, size * MBIT, NULL);
|
||||
|
||||
cd64->devclose (cd64);
|
||||
fclose (file);
|
||||
free (cd64);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cd64_write_rom (const char *filename)
|
||||
{
|
||||
FILE *file;
|
||||
struct cd64_t *cd64 = cd64_init ();
|
||||
|
||||
if ((file = fopen (filename, "rb")) == NULL)
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], filename);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
cd64_starttime = time (NULL);
|
||||
cd64_upload_dram (cd64, file, ucon64.file_size, NULL, 1);
|
||||
|
||||
cd64->devclose (cd64);
|
||||
fclose (file);
|
||||
free (cd64);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cd64_write_bootemu (const char *filename)
|
||||
{
|
||||
FILE *file;
|
||||
struct cd64_t *cd64 = cd64_init ();
|
||||
|
||||
if ((file = fopen (filename, "rb")) == NULL)
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], filename);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
cd64_starttime = time (NULL);
|
||||
cd64_upload_bootemu (cd64, file, ucon64.file_size, NULL);
|
||||
|
||||
cd64->devclose (cd64);
|
||||
fclose (file);
|
||||
free (cd64);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cd64_read_sram (const char *filename)
|
||||
{
|
||||
FILE *file;
|
||||
struct cd64_t *cd64 = cd64_init ();
|
||||
|
||||
if ((file = fopen (filename, "wb")) == NULL)
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], filename);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
cd64_starttime = time (NULL);
|
||||
cd64_download_sram (cd64, file);
|
||||
|
||||
cd64->devclose (cd64);
|
||||
fclose (file);
|
||||
free (cd64);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cd64_write_sram (const char *filename)
|
||||
{
|
||||
FILE *file;
|
||||
struct cd64_t *cd64 = cd64_init ();
|
||||
|
||||
if ((file = fopen (filename, "rb")) == NULL)
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], filename);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
cd64_starttime = time (NULL);
|
||||
cd64_upload_sram (cd64, file);
|
||||
|
||||
cd64->devclose (cd64);
|
||||
fclose (file);
|
||||
free (cd64);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cd64_read_flashram (const char *filename)
|
||||
{
|
||||
FILE *file;
|
||||
struct cd64_t *cd64 = cd64_init ();
|
||||
|
||||
if ((file = fopen (filename, "wb")) == NULL)
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], filename);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
cd64_starttime = time (NULL);
|
||||
cd64_download_flashram (cd64, file);
|
||||
|
||||
cd64->devclose (cd64);
|
||||
fclose (file);
|
||||
free (cd64);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cd64_write_flashram (const char *filename)
|
||||
{
|
||||
FILE *file;
|
||||
struct cd64_t *cd64 = cd64_init ();
|
||||
|
||||
if ((file = fopen (filename, "rb")) == NULL)
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], filename);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
cd64_starttime = time (NULL);
|
||||
cd64_upload_flashram (cd64, file);
|
||||
|
||||
cd64->devclose (cd64);
|
||||
fclose (file);
|
||||
free (cd64);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cd64_read_eeprom (const char *filename)
|
||||
{
|
||||
FILE *file;
|
||||
struct cd64_t *cd64 = cd64_init ();
|
||||
|
||||
if ((file = fopen (filename, "wb")) == NULL)
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], filename);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
cd64_starttime = time (NULL);
|
||||
cd64_download_eeprom (cd64, file);
|
||||
|
||||
cd64->devclose (cd64);
|
||||
fclose (file);
|
||||
free (cd64);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cd64_write_eeprom (const char *filename)
|
||||
{
|
||||
FILE *file;
|
||||
struct cd64_t *cd64 = cd64_init ();
|
||||
|
||||
if ((file = fopen (filename, "rb")) == NULL)
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], filename);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
cd64_starttime = time (NULL);
|
||||
cd64_upload_eeprom (cd64, file);
|
||||
|
||||
cd64->devclose (cd64);
|
||||
fclose (file);
|
||||
free (cd64);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cd64_read_mempack (const char *filename, int index)
|
||||
{
|
||||
FILE *file;
|
||||
struct cd64_t *cd64 = cd64_init ();
|
||||
|
||||
if ((file = fopen (filename, "wb")) == NULL)
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], filename);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (ucon64.io_mode == CD64BIOS)
|
||||
index = -1;
|
||||
cd64_starttime = time (NULL);
|
||||
cd64_download_mempak (cd64, file, (int8_t) index);
|
||||
|
||||
cd64->devclose (cd64);
|
||||
fclose (file);
|
||||
free (cd64);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cd64_write_mempack (const char *filename, int index)
|
||||
{
|
||||
FILE *file;
|
||||
struct cd64_t *cd64 = cd64_init ();
|
||||
|
||||
if ((file = fopen (filename, "rb")) == NULL)
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], filename);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (ucon64.io_mode == CD64BIOS)
|
||||
index = -1;
|
||||
cd64_starttime = time (NULL);
|
||||
cd64_upload_mempak (cd64, file, (int8_t) index);
|
||||
|
||||
cd64->devclose (cd64);
|
||||
fclose (file);
|
||||
free (cd64);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // USE_PARALLEL && USE_LIBCD64
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
cd64.h - CD64 support for uCON64
|
||||
|
||||
Copyright (c) 2001 NoisyB <noisyb@gmx.net>
|
||||
Copyright (c) 2004 dbjh
|
||||
|
||||
|
||||
This program 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#ifndef CD64_H
|
||||
#define CD64_H
|
||||
|
||||
extern const st_getopt2_t cd64_usage[];
|
||||
|
||||
#if defined USE_PARALLEL && defined USE_LIBCD64
|
||||
extern int cd64_read_rom(const char *filename, int size);
|
||||
extern int cd64_write_rom(const char *filename);
|
||||
extern int cd64_write_bootemu (const char *filename);
|
||||
extern int cd64_read_sram(const char *filename);
|
||||
extern int cd64_write_sram(const char *filename);
|
||||
extern int cd64_read_flashram(const char *filename);
|
||||
extern int cd64_write_flashram(const char *filename);
|
||||
extern int cd64_read_eeprom(const char *filename);
|
||||
extern int cd64_write_eeprom(const char *filename);
|
||||
extern int cd64_read_mempack(const char *filename, int index);
|
||||
extern int cd64_write_mempack(const char *filename, int index);
|
||||
#endif // USE_PARALLEL && USE_LIBCD64
|
||||
|
||||
#endif // CD64_H
|
||||
@@ -1,985 +0,0 @@
|
||||
/*
|
||||
cmc.c - Cyan's Megadrive ROM copier support for uCON64
|
||||
|
||||
Copyright (c) 1999 - 2004 Cyan Helkaraxe
|
||||
|
||||
Special thanks to dbjh for helping with the uCON64 integration
|
||||
of this software, and providing the wrapping code.
|
||||
|
||||
CMC version: 2.5
|
||||
For hardware version 1.x
|
||||
|
||||
Copies Sega Megadrive/Genesis cartridges into .BIN format ROM files.
|
||||
|
||||
|
||||
This program 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
Additional information:
|
||||
This software is distributed in accordance with the GNU General
|
||||
Public License. The author of the hardware design/documentation and
|
||||
software, Cyan Helkaraxe, retains the copyright over the 'cmc' code
|
||||
('software'), the hardware design and construction documentation itself.
|
||||
Cyan grants you the rights of the GNU General Public License over
|
||||
the software, as stated above. The copyright does not affect your
|
||||
rights in relation to the 'cmc' code under the GNU General Public
|
||||
License in any way.
|
||||
Cyan Helkaraxe does NOT grant you any rights relating to the hardware
|
||||
design/documentation, over and above the right to build the device for
|
||||
personal, not-for-profit use. Likewise, the same applies to the ROM
|
||||
copier construction documentation, available at
|
||||
http://www.emulationzone.org/projects/cyan/docs/ for not-for-profit
|
||||
personal use.
|
||||
|
||||
Obviously, feel free to make changes to this software, but if you do so,
|
||||
*please* clearly mark the fact it is modified, to avoid confusion.
|
||||
A define is provided below this commented area, which should be edited
|
||||
as described. This is to inform users which version of the code they are
|
||||
using at runtime, and if they encounter a problem, it makes it far easier
|
||||
for me to help debug it. I have no evil nefarious intentions. =P
|
||||
|
||||
Obviously, your changes must adhere to the GNU GPL, and please keep the
|
||||
copyright, Cyan's name, e-mail and web site address in the comments
|
||||
somewhere.
|
||||
|
||||
If you wish to do anything with the hardware design or the documentation
|
||||
that goes beyond personal use, get in touch with Cyan first;
|
||||
cyan@emulationzone.org
|
||||
|
||||
Disclaimer / Warranty:
|
||||
This is to emphasise, not replace, any warranty information provided in
|
||||
the GNU GPL or uCON64.
|
||||
There is no warranty whatsoever, for either the software or accompanying
|
||||
hardware/design/documentation. This software is provided free of charge,
|
||||
AS-IS, in the hope that it may be useful.
|
||||
Use it at your own risk. The author does not make any guarantee that you
|
||||
will be able to use this software or accompanying
|
||||
hardware/design/documentation, or that it will perform smoothly. There is
|
||||
a possibility that damage or loss (including but not limited to financial
|
||||
loss, hardware or software damage, data corruption, privacy violation,
|
||||
or personal injury, suffering, legal action, imprisonment or death) may
|
||||
arise through the use of this software or the accompanying
|
||||
hardware/design/documentation, in addition to many other possible outcomes.
|
||||
You take sole responsibility for any outcomes; by using this software or
|
||||
accompanying hardware/design/ documentation, you agree that the author will
|
||||
not be held responsible for anything that may occur. If your jurisdiction
|
||||
does not allow the author to be isolated from responsibility, then you
|
||||
must *not* use this software or accompanying hardware/design/documentation.
|
||||
The author does not condone software piracy. You may not use this software
|
||||
to engage in piracy. The author is not responsible for anything you choose
|
||||
to use this software for, although the author strongly recommends that you
|
||||
use the software for the purpose for which it was intended to be used --
|
||||
primarily as an educational tool, and secondarily to make backup copies of
|
||||
your expensive/rare game cartridges, or a similarly harmless and legal
|
||||
purpose.
|
||||
Note that although the author isn't aware of any patent violations caused
|
||||
by this software/hardware/design/documentation, it is possible that
|
||||
there may be patents covering parts of this device. It is your
|
||||
responsibility to check this before building or using the hardware or
|
||||
software, and Cyan may not be held responsible in the event of an
|
||||
infringement.
|
||||
|
||||
That being said, if you do encounter any problems with the hardware or
|
||||
software, then feel free to get in touch with the author; use the subject
|
||||
line 'ROM Copier Technical Support'. No promises or guarantees are made,
|
||||
however.
|
||||
|
||||
Also note that the author is not affiliated with anyone involved with uCON64;
|
||||
therefore, only correspondence relating to this particular file (the 'cmc'
|
||||
code) or the accompanying hardware design should be directed to Cyan.
|
||||
If you have more general uCON64 questions, Cyan is *not* the person to ask.
|
||||
Likewise, the terms "the author" and "software" in this file (cmc.c, and
|
||||
additionally cmc.h), along with similar terms, apply only to Cyan, and the
|
||||
CMC software you see in this file. The disclaimer above, for example, relates
|
||||
exclusively to the CMC code.
|
||||
|
||||
All trademarks, indicated or otherwise, are the property of their
|
||||
respective owners.
|
||||
*/
|
||||
|
||||
/*
|
||||
NOTE!
|
||||
Please edit the following line, and remove the word "original" from it
|
||||
if you have made any modifications to this file. This reduces user
|
||||
confusion.
|
||||
*/
|
||||
#define INTRO_TEXT "Cyan's Megadrive Copier (c) 1999-2004 Cyan Helkaraxe\n" \
|
||||
"Software version 2.5 original, designed for hardware version 1.x\n\n"
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include "misc/bswap.h"
|
||||
#include "misc/misc.h"
|
||||
#include "misc/parallel.h"
|
||||
#ifdef USE_ZLIB
|
||||
#include "misc/archive.h"
|
||||
#endif
|
||||
#include "misc/getopt2.h" // st_getopt2_t
|
||||
#include "ucon64.h"
|
||||
#include "ucon64_misc.h"
|
||||
#include "cmc.h"
|
||||
|
||||
#ifdef USE_PARALLEL
|
||||
|
||||
#define RSLO 0x40 // reset line 1 d7
|
||||
#define RSHI 0x01 // reset line 2 d0
|
||||
#define CNLO 0x10 // counter line 1 d4
|
||||
#define CNHI 0x04 // counter line 2 d2
|
||||
#define INLO 0x40 // input 1 ack (int disabled)
|
||||
#define INHI 0x10 // input 2 selectin
|
||||
|
||||
#define MBYTE (1024 * 1024)
|
||||
#define DEFAULT_SPEED 3
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Visual C++ doesn't allow inline in C source code
|
||||
#define inline __inline
|
||||
#endif
|
||||
|
||||
|
||||
/************************
|
||||
* Internal functions *
|
||||
************************/
|
||||
|
||||
static inline void
|
||||
cyan_write_copier (unsigned char data, unsigned int parport)
|
||||
// write a value to the data register of the parallel port
|
||||
{
|
||||
outportb ((unsigned short) (parport + PARPORT_DATA), data);
|
||||
}
|
||||
|
||||
|
||||
static inline unsigned char
|
||||
cyan_read_copier (unsigned int parport)
|
||||
// read a value from the status register of the parallel port
|
||||
{
|
||||
return inportb ((unsigned short) (parport + PARPORT_STATUS));
|
||||
}
|
||||
|
||||
|
||||
static inline unsigned char
|
||||
cyan_verify_copier (unsigned int parport)
|
||||
// read a value back from the data register for verification
|
||||
{
|
||||
return inportb ((unsigned short) (parport + PARPORT_DATA));
|
||||
}
|
||||
|
||||
|
||||
/**** non-hardware, non-accessing ****/
|
||||
|
||||
static unsigned long
|
||||
cyan_calculate_rom_size (unsigned char *buffer, int test_mode)
|
||||
/*
|
||||
Calculate the ROM size, by looking at the ROM size entry in the ROM 'header',
|
||||
and the overall structure.
|
||||
This function always returns a value rounded to a power of two between 128
|
||||
kbytes and 4 Mbytes. It also inspects the ROM for 0's or ffh's. If test_mode
|
||||
is 1 it causes an error on that condition, frees the buffer and exits.
|
||||
*/
|
||||
{
|
||||
unsigned long i = 0x80000000, reported_size;
|
||||
|
||||
// look at reported size
|
||||
reported_size = (buffer[0x1a4] << 24) +
|
||||
(buffer[0x1a5] << 16) +
|
||||
(buffer[0x1a6] << 8) +
|
||||
buffer[0x1a7] + 1;
|
||||
// cap
|
||||
// there is a minimum valid size for ROMs, according to some sources
|
||||
if (reported_size < MBIT)
|
||||
reported_size = MBIT;
|
||||
if (reported_size > 4 * MBYTE)
|
||||
reported_size = 4 * MBYTE;
|
||||
// round
|
||||
if (reported_size & (reported_size - 1))
|
||||
{
|
||||
while (!(reported_size & 0x80000000))
|
||||
{
|
||||
i >>= 1;
|
||||
reported_size = (reported_size << 1) | 1;
|
||||
}
|
||||
reported_size = i << 1;
|
||||
}
|
||||
// calculate real size
|
||||
for (i = 2 * MBYTE; i >= 65536; i >>= 1)
|
||||
if (memcmp (buffer, buffer + i, i))
|
||||
{
|
||||
i >>= 1;
|
||||
break;
|
||||
}
|
||||
i <<= 2;
|
||||
if (reported_size < i)
|
||||
reported_size = i; // pick the safest (largest) of the two
|
||||
if (i == MBIT)
|
||||
{
|
||||
for (i = 0; i < MBIT; i++)
|
||||
if ((buffer[i] != 0xff) && (buffer[i] != 0x00))
|
||||
break;
|
||||
if (i == MBIT)
|
||||
{
|
||||
FILE *output;
|
||||
|
||||
if (test_mode)
|
||||
{
|
||||
output = stderr;
|
||||
fputs ("\nERROR: ", stderr);
|
||||
}
|
||||
else
|
||||
{
|
||||
output = stdout;
|
||||
fputs ("\nWARNING: ", stdout);
|
||||
}
|
||||
|
||||
// "WARNING: "
|
||||
fputs ( "The ROM file appears to consist of nothing but 0x00 / 0xff values.\n"
|
||||
" This usually indicates a serious problem. Perhaps your parallel port\n"
|
||||
" isn't configured correctly, or there is some problem with the ROM\n"
|
||||
" copier. Is it getting power? Is a cartridge inserted? Is it properly\n"
|
||||
" attached to the PC?\n",
|
||||
output);
|
||||
if (test_mode)
|
||||
{
|
||||
free (buffer);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return reported_size;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
cyan_checksum_rom (unsigned char *buffer)
|
||||
// return 0 on success, -1 on failure
|
||||
{
|
||||
unsigned char *buffer2 = buffer;
|
||||
unsigned short reported_sum, running_sum = 0;
|
||||
|
||||
reported_sum = (buffer2[0x18e] << 8) + buffer2[0x18f];
|
||||
buffer2 += ((buffer2[0x1a4] << 24) +
|
||||
(buffer2[0x1a5] << 16) +
|
||||
(buffer2[0x1a6] << 8) +
|
||||
(buffer2[0x1a7] & 0xfe)) + 2;
|
||||
if (buffer2 > buffer + 4 * MBYTE)
|
||||
buffer2 = buffer + 4 * MBYTE;
|
||||
buffer += 0x200;
|
||||
if (buffer2 < buffer + 2)
|
||||
return -1;
|
||||
|
||||
while (buffer2 != buffer)
|
||||
{
|
||||
running_sum += *--buffer2;
|
||||
running_sum += (*--buffer2) << 8;
|
||||
}
|
||||
|
||||
return (running_sum & 0xffff) != reported_sum ? -1 : 0;
|
||||
}
|
||||
|
||||
|
||||
static inline unsigned long
|
||||
cyan_get_address (unsigned long b)
|
||||
// return the true address (word -- 0 - 2 M) based on word input
|
||||
{
|
||||
return ((b & 0x000800) >> 11) | // bit 0
|
||||
((b & 0x002000) >> 12) | // bit 1
|
||||
((b & 0x004000) >> 12) | // bit 2
|
||||
((b & 0x000020) >> 2) | // bit 3
|
||||
((b & 0x100000) >> 16) | // bit 4
|
||||
((b & 0x020000) >> 12) | // bit 5
|
||||
((b & 0x000400) >> 4) | // bit 6
|
||||
((b & 0x000001) << 7) | // bit 7
|
||||
((b & 0x000002) << 7) | // bit 8
|
||||
((b & 0x000010) << 5) | // bit 9
|
||||
((b & 0x000040) << 4) | // bit 10
|
||||
((b & 0x040000) >> 7) | // bit 11
|
||||
((b & 0x080000) >> 7) | // bit 12
|
||||
((b & 0x000080) << 6) | // bit 13
|
||||
((b & 0x008000) >> 1) | // bit 14
|
||||
((b & 0x010000) >> 1) | // bit 15
|
||||
((b & 0x001000) << 4) | // bit 16
|
||||
((b & 0x000004) << 15) | // bit 17
|
||||
((b & 0x000008) << 15) | // bit 18
|
||||
((b & 0x000200) << 10) | // bit 19
|
||||
((b & 0x000100) << 12); // bit 20
|
||||
}
|
||||
|
||||
|
||||
/**** non-hardware, indirectly accessing ****/
|
||||
|
||||
static inline void
|
||||
cyan_delay (int speed, unsigned int parport)
|
||||
// Delays a certain amount of time depending on speed selected. 0=long delay,
|
||||
// used for reset and hi counter.
|
||||
{
|
||||
int i, scritch = 0;
|
||||
|
||||
switch (speed)
|
||||
{
|
||||
case 0:
|
||||
for (i = 0; i < 128; i++)
|
||||
scritch += cyan_read_copier (parport);
|
||||
case 1: // falling through
|
||||
for (i = 0; i < 64; i++)
|
||||
scritch += cyan_read_copier (parport);
|
||||
case 2: // falling through
|
||||
for (i = 0; i < 12; i++)
|
||||
scritch += cyan_read_copier (parport);
|
||||
case 3: // falling through
|
||||
scritch += cyan_read_copier (parport);
|
||||
scritch += cyan_read_copier (parport);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cyan_reset (unsigned int parport)
|
||||
// resets the copier
|
||||
{
|
||||
cyan_delay (0, parport);
|
||||
// zero all data outputs first, before going into SPP mode
|
||||
cyan_write_copier (0, parport);
|
||||
// reset the port to SPP, float all control lines high
|
||||
cyan_write_copier (0, parport + PARPORT_CONTROL);
|
||||
cyan_delay (0, parport);
|
||||
cyan_write_copier (RSLO | RSHI, parport); // both reset lines hi
|
||||
cyan_delay (0, parport);
|
||||
cyan_write_copier (0, parport); // both reset lines lo
|
||||
cyan_delay (0, parport);
|
||||
}
|
||||
|
||||
|
||||
static inline unsigned short
|
||||
cyan_get_word (int speed, unsigned int parport)
|
||||
// gets a byte pair from the ROM and return two bytes in big endian byte order
|
||||
{
|
||||
unsigned short value = 0;
|
||||
unsigned char tempz;
|
||||
|
||||
cyan_write_copier (0, parport);
|
||||
cyan_delay (speed, parport);
|
||||
tempz = cyan_read_copier (parport);
|
||||
value |= tempz & INLO; // bit 6
|
||||
value |= (tempz & INHI) << 8; // bit 12
|
||||
|
||||
cyan_write_copier (CNLO, parport);
|
||||
cyan_delay (speed, parport);
|
||||
tempz = cyan_read_copier (parport);
|
||||
value |= (tempz & INLO) >> 5; // bit 1
|
||||
value |= (tempz & INHI) << 9; // bit 13
|
||||
|
||||
cyan_write_copier (0, parport);
|
||||
cyan_delay (speed, parport);
|
||||
tempz = cyan_read_copier (parport);
|
||||
value |= (tempz & INLO) << 3; // bit 9
|
||||
value |= (tempz & INHI) << 10; // bit 14
|
||||
|
||||
cyan_write_copier (CNLO, parport);
|
||||
cyan_delay (speed, parport);
|
||||
tempz = cyan_read_copier (parport);
|
||||
value |= (tempz & INLO) >> 1; // bit 5
|
||||
value |= (tempz & INHI) << 11; // bit 15
|
||||
|
||||
cyan_write_copier (0, parport);
|
||||
cyan_delay (speed, parport);
|
||||
tempz = cyan_read_copier (parport);
|
||||
value |= (tempz & INLO) >> 4; // bit 2
|
||||
value |= (tempz & INHI) << 4; // bit 8
|
||||
|
||||
cyan_write_copier (CNLO, parport);
|
||||
cyan_delay (speed, parport);
|
||||
tempz = cyan_read_copier (parport);
|
||||
value |= (tempz & INLO) << 4; // bit 10
|
||||
value |= (tempz & INHI) >> 4; // bit 0
|
||||
|
||||
cyan_write_copier (0, parport);
|
||||
cyan_delay (speed, parport);
|
||||
tempz = cyan_read_copier (parport);
|
||||
value |= (tempz & INLO) >> 2; // bit 4
|
||||
value |= (tempz & INHI) << 3; // bit 7
|
||||
|
||||
cyan_write_copier (CNLO, parport);
|
||||
cyan_delay (speed, parport);
|
||||
tempz = cyan_read_copier (parport);
|
||||
value |= (tempz & INLO) >> 3; // bit 3
|
||||
value |= (tempz & INHI) << 7; // bit 11
|
||||
|
||||
return me2be_16 (value);
|
||||
}
|
||||
|
||||
|
||||
static inline int
|
||||
check_exit (void)
|
||||
// check for user abort
|
||||
{
|
||||
int temp;
|
||||
|
||||
if (ucon64.frontend)
|
||||
return 0;
|
||||
if (!kbhit ())
|
||||
return 0;
|
||||
temp = getch ();
|
||||
if (temp == 'q' || (temp == 27))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static unsigned char *
|
||||
cyan_read_rom (int speed, unsigned int parport, unsigned char *buffer)
|
||||
/*
|
||||
Read the ROM and return a pointer to a 4 MB area of memory containing all ROM
|
||||
data. Designed to be used from inside cyan_copy_rom(), although it can be
|
||||
called elsewhere if a raw (but decoded) dump is required.
|
||||
*/
|
||||
{
|
||||
unsigned long q;
|
||||
time_t t;
|
||||
|
||||
// allocate the dump area
|
||||
if (!buffer)
|
||||
if ((buffer = (unsigned char *) malloc (4 * MBYTE)) == NULL)
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[ROM_BUFFER_ERROR], 4 * MBYTE);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
cyan_reset (parport); // reset the copier
|
||||
|
||||
t = time (NULL);
|
||||
// copy routine
|
||||
for (q = 0; q < 2 * MBYTE; ) // loop through all words
|
||||
{
|
||||
// get a (16-bit) word from the ROM
|
||||
((unsigned short *) buffer)[cyan_get_address (q)] = cyan_get_word (speed, parport);
|
||||
|
||||
// periodically update progress bar, without hammering ucon64_gauge()
|
||||
if (!(q & (0xfff >> (5 - speed))))
|
||||
{
|
||||
if (check_exit ())
|
||||
{
|
||||
free (buffer);
|
||||
puts ("\n"
|
||||
"Copy aborted.\n"
|
||||
"Don't forget to turn the ROM copier off and never insert or remove a cartridge\n"
|
||||
"with the power on");
|
||||
break;
|
||||
}
|
||||
ucon64_gauge (t, q * 2, 4 * MBYTE);
|
||||
}
|
||||
|
||||
if (!(++q & 0x3ff)) // advance loop counter and carry to hi counter (11 bits)
|
||||
{
|
||||
cyan_delay (0, parport);
|
||||
cyan_write_copier (CNHI, parport);
|
||||
cyan_delay (0, parport);
|
||||
cyan_write_copier (0, parport);
|
||||
cyan_delay (0, parport);
|
||||
}
|
||||
}
|
||||
|
||||
// make sure it's left in a state where it's safe to remove the cart
|
||||
cyan_reset (parport);
|
||||
|
||||
if (q != 2 * MBYTE)
|
||||
return NULL;
|
||||
|
||||
ucon64_gauge (t, q * 2, 4 * MBYTE); // make the progress bar reach 100%
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cyan_test_parport (unsigned int parport)
|
||||
// Test the parallel port to see if it appears to be functioning correctly, and
|
||||
// terminate if there's an error.
|
||||
{
|
||||
unsigned short temp;
|
||||
|
||||
cyan_reset (parport);
|
||||
fputs ("Basic parallel port test: ", stdout);
|
||||
fflush (stdout);
|
||||
cyan_write_copier (170, parport);
|
||||
cyan_delay (0, parport);
|
||||
temp = cyan_verify_copier (parport) & 170;
|
||||
cyan_reset (parport);
|
||||
|
||||
// even in unidirectional mode, the parallel port is bidirectional; at
|
||||
// least, for a few short moments before the driver IC smokes
|
||||
if ((cyan_verify_copier (parport) & 170) != 0 || temp != 170)
|
||||
{
|
||||
puts ("FAILED");
|
||||
fputs ("ERROR: Parallel port error\n"
|
||||
" Check that your parallel port is configured properly, in the BIOS, OS,\n"
|
||||
" and uCON64, and check for short circuits on the parallel port connector.\n"
|
||||
" Also ensure that the ROM copier is getting power, and a cartridge is\n"
|
||||
" inserted\n",
|
||||
stderr);
|
||||
exit (1);
|
||||
}
|
||||
else
|
||||
puts ("Passed");
|
||||
|
||||
// discharge caps to see if we've got power
|
||||
cyan_reset (parport);
|
||||
cyan_reset (parport);
|
||||
cyan_write_copier (CNLO + CNHI, parport);
|
||||
cyan_delay (0, parport);
|
||||
for (temp = 0; temp < 1000; temp++)
|
||||
{
|
||||
cyan_write_copier (0, parport);
|
||||
cyan_delay (3, parport);
|
||||
cyan_write_copier (CNLO + CNHI, parport);
|
||||
cyan_delay (3, parport);
|
||||
}
|
||||
cyan_reset (parport);
|
||||
cyan_reset (parport);
|
||||
|
||||
fputs ("Parallel port output test: ", stdout);
|
||||
fflush (stdout);
|
||||
cyan_write_copier (255, parport);
|
||||
cyan_delay (0, parport);
|
||||
temp = (cyan_verify_copier (parport) != 255);
|
||||
cyan_write_copier (0, parport);
|
||||
cyan_delay (0, parport);
|
||||
temp |= (cyan_verify_copier (parport) != 0);
|
||||
cyan_write_copier (CNLO, parport);
|
||||
cyan_delay (0, parport);
|
||||
temp |= (cyan_verify_copier (parport) != CNLO);
|
||||
cyan_write_copier (CNHI, parport);
|
||||
cyan_delay (0, parport);
|
||||
temp |= (cyan_verify_copier (parport) != CNHI);
|
||||
cyan_write_copier (RSLO, parport);
|
||||
cyan_delay (0, parport);
|
||||
temp |= (cyan_verify_copier (parport) != RSLO);
|
||||
cyan_write_copier (RSHI, parport);
|
||||
cyan_delay (0, parport);
|
||||
temp |= (cyan_verify_copier (parport) != RSHI);
|
||||
cyan_reset (parport);
|
||||
|
||||
// if it's still okay after that, then try reading the first set of inputs
|
||||
// with lines high and low
|
||||
if (!temp)
|
||||
{
|
||||
fputs ("Passed\n"
|
||||
"Input crosstalk test: ",
|
||||
stdout);
|
||||
fflush (stdout);
|
||||
temp = cyan_read_copier (parport) & (INLO | INHI);
|
||||
cyan_write_copier (255 - CNLO, parport);
|
||||
cyan_delay (0, parport);
|
||||
temp = (temp != (cyan_read_copier (parport) & (INLO | INHI)));
|
||||
cyan_reset (parport);
|
||||
}
|
||||
|
||||
if (temp)
|
||||
{
|
||||
puts ("FAILED");
|
||||
fputs ("ERROR: Parallel port error\n"
|
||||
"Possible causes: ROM copier not getting power (check or replace battery)\n"
|
||||
" Short circuit or bad connection (on parallel port or board)\n"
|
||||
" Cartridge not inserted properly (or not inserted at all)\n"
|
||||
" Parallel port not configured correctly\n"
|
||||
" Orange, grey or green wire(s) soldered to the wrong locations\n"
|
||||
" Chips inserted backwards\n"
|
||||
"NOTE: Don't forget the ROM copier needs to be turned on before starting!\n",
|
||||
stderr);
|
||||
exit (1);
|
||||
}
|
||||
else
|
||||
puts ("Passed");
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
cyan_test_copier (int test, int speed, unsigned int parport)
|
||||
{
|
||||
unsigned char *buffer1, *buffer2 = NULL;
|
||||
int count = 1;
|
||||
|
||||
fputs (INTRO_TEXT, stdout);
|
||||
parport_print_info ();
|
||||
|
||||
switch (test)
|
||||
{
|
||||
// reliability test -- note: this test may be required to run for 8 hours or more
|
||||
case 1:
|
||||
printf ("Reliability test mode selected, speed %d\n", speed);
|
||||
cyan_test_parport (parport);
|
||||
puts ("\n"
|
||||
"Entering non-stop reliability test mode (press escape or q to exit, and turn\n"
|
||||
"ROM copier off immediately afterwards)\n"
|
||||
"\n"
|
||||
"Copy process will continue indefinitely until an error is encountered, at\n"
|
||||
"which point the program will terminate.\n"
|
||||
"A large number of passes suggests that the copier is working reliably at the\n"
|
||||
"selected speed\n");
|
||||
printf (" P %2d",
|
||||
count);
|
||||
fflush (stdout);
|
||||
if (ucon64.frontend)
|
||||
fputc ('\n', stdout);
|
||||
buffer1 = cyan_read_rom (speed, parport, NULL);
|
||||
if (!buffer1) // user abort
|
||||
exit (0);
|
||||
|
||||
// detect if ROM is all 0x00 or 0xff and print an error if so
|
||||
cyan_calculate_rom_size (buffer1, 1);
|
||||
|
||||
while (1)
|
||||
{
|
||||
clear_line (); // remove last gauge
|
||||
printf (" Pass %2d OK\n", count);
|
||||
count++;
|
||||
|
||||
// verify checksum of first pass
|
||||
if (count == 2) // check only in first iteration
|
||||
if (cyan_checksum_rom (buffer1)) // verify checksum
|
||||
puts ("\n"
|
||||
"WARNING: Checksum of ROM does not appear to be correct.\n"
|
||||
" This may be normal for this ROM, or it may indicate a bad copy\n");
|
||||
|
||||
printf (" P %2d",
|
||||
count);
|
||||
fflush (stdout);
|
||||
if (ucon64.frontend)
|
||||
fputc ('\n', stdout);
|
||||
buffer2 = cyan_read_rom (speed, parport, buffer2);
|
||||
if (!buffer2)
|
||||
{
|
||||
free (buffer1);
|
||||
exit (0);
|
||||
}
|
||||
if (memcmp (buffer1, buffer2, 4 * MBYTE))
|
||||
{
|
||||
// error
|
||||
printf ("\n"
|
||||
"\n"
|
||||
"Error detected on pass number %d\n"
|
||||
"\n",
|
||||
count);
|
||||
if (count == 2)
|
||||
puts ("A failure this early suggests a critical fault, such as a misconfigured or\n"
|
||||
"incompatible parallel port, extremely poor wiring, or power supply problems --\n"
|
||||
"you may wish to replace the battery or try another power supply, and use\n"
|
||||
"shorter cables.\n"
|
||||
"Try lowering the speed and running this test again, as a too high speed can\n"
|
||||
"often cause these symptoms.\n"
|
||||
"Alternatively, it may have been a one-time glitch; re-run the test to be sure.\n"
|
||||
"When (if?) you find a lower speed which works reliably, use that speed for\n"
|
||||
"copying ROMs\n");
|
||||
else
|
||||
puts ("The first couple of passes were successful. This indicates that you have a\n"
|
||||
"minor intermittent problem; most likely power supply problems, bad wiring, or\n"
|
||||
"some kind of one-time glitch.\n"
|
||||
"You may wish to replace the battery or try another power supply, and use\n"
|
||||
"shorter cables.\n"
|
||||
"Make sure no electrical appliances turn on or off during the copy.\n"
|
||||
"Re-run the test to be sure; it's recommended that you use a lower speed\n");
|
||||
free (buffer1);
|
||||
free (buffer2);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
free (buffer1);
|
||||
free (buffer2);
|
||||
break;
|
||||
// manual test
|
||||
case 2:
|
||||
cyan_reset (parport);
|
||||
cyan_write_copier (CNHI, parport);
|
||||
cyan_delay (0, parport);
|
||||
cyan_write_copier (0, parport);
|
||||
cyan_delay (0, parport);
|
||||
|
||||
if (speed != DEFAULT_SPEED)
|
||||
puts ("Ignoring specified speed; test bench mode does not require a speed setting");
|
||||
// print screen
|
||||
puts ("Entering manual test bench mode\n"
|
||||
"\n"
|
||||
"Probe the board and verify that the counters are being clocked, and are\n"
|
||||
"counting correctly. The upper counter should be one count ahead of the lower\n"
|
||||
"counter, with both clocked at the same rate.\n"
|
||||
"Inject logic levels into the multiplexers to verify that the data bits are\n"
|
||||
"being read correctly:\n"
|
||||
"*=high .=low, layout: L H L H L H L H (L=low multiplexer, H=high multiplexer)\n"
|
||||
"NOTE: The signals in question are the chip native signals; D0 below corresponds\n"
|
||||
"to D0 on the multiplexer, NOT D0 on the cartridge port. Likewise with the\n"
|
||||
"address lines. The input lines are in counter order, left to right.\n"
|
||||
"Press escape or q to exit; be sure to turn the ROM copier off immediately after\n"
|
||||
"exiting, to reset the device.\n"
|
||||
"\n"
|
||||
"If the above didn't make any sense to you, press escape or q and turn the ROM\n"
|
||||
"copier off immediately!\n"
|
||||
"This test is designed for advanced users only\n");
|
||||
while (1)
|
||||
{
|
||||
const char *status[2] = {"* ", ". "};
|
||||
|
||||
fputc ('\r', stdout);
|
||||
|
||||
cyan_write_copier (0, parport);
|
||||
cyan_delay (1, parport);
|
||||
count = cyan_read_copier (parport);
|
||||
fputs (status[((count ^ INLO) >> 6) & 1], stdout);
|
||||
fputs (status[((count ^ INHI) >> 4) & 1], stdout);
|
||||
|
||||
cyan_write_copier (CNLO | CNHI, parport);
|
||||
cyan_delay (1, parport);
|
||||
count = cyan_read_copier (parport);
|
||||
fputs (status[((count ^ INLO) >> 6) & 1], stdout);
|
||||
fputs (status[((count ^ INHI) >> 4) & 1], stdout);
|
||||
|
||||
cyan_write_copier (0, parport);
|
||||
cyan_delay (1, parport);
|
||||
count = cyan_read_copier (parport);
|
||||
fputs (status[((count ^ INLO) >> 6) & 1], stdout);
|
||||
fputs (status[((count ^ INHI) >> 4) & 1], stdout);
|
||||
|
||||
cyan_write_copier (CNLO | CNHI, parport);
|
||||
cyan_delay (1, parport);
|
||||
count = cyan_read_copier (parport);
|
||||
fputs (status[((count ^ INLO) >> 6) & 1], stdout);
|
||||
fputs (status[((count ^ INHI) >> 4) & 1], stdout);
|
||||
|
||||
cyan_write_copier (0, parport);
|
||||
cyan_delay (1, parport);
|
||||
count = cyan_read_copier (parport);
|
||||
fputs (status[((count ^ INLO) >> 6) & 1], stdout);
|
||||
fputs (status[((count ^ INHI) >> 4) & 1], stdout);
|
||||
|
||||
cyan_write_copier (CNLO | CNHI, parport);
|
||||
cyan_delay (1, parport);
|
||||
count = cyan_read_copier (parport);
|
||||
fputs (status[((count ^ INLO) >> 6) & 1], stdout);
|
||||
fputs (status[((count ^ INHI) >> 4) & 1], stdout);
|
||||
|
||||
cyan_write_copier (0, parport);
|
||||
cyan_delay (1, parport);
|
||||
count = cyan_read_copier (parport);
|
||||
fputs (status[((count ^ INLO) >> 6) & 1], stdout);
|
||||
fputs (status[((count ^ INHI) >> 4) & 1], stdout);
|
||||
|
||||
cyan_write_copier (CNLO | CNHI, parport);
|
||||
cyan_delay (1, parport);
|
||||
count = cyan_read_copier (parport);
|
||||
fputs (status[((count ^ INLO) >> 6) & 1], stdout);
|
||||
fputs (status[((count ^ INHI) >> 4) & 1], stdout);
|
||||
|
||||
cyan_write_copier (0, parport);
|
||||
cyan_delay (1, parport);
|
||||
fflush (stdout);
|
||||
|
||||
if (check_exit ())
|
||||
{
|
||||
cyan_reset (parport);
|
||||
puts ("\nUser aborted test");
|
||||
exit (0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default: // cmc_test() should only pass a correct speed value
|
||||
fputs ("INTERNAL ERROR: Invalid test number passed to cyan_test_copier()\n", stderr);
|
||||
exit (1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
cyan_copy_rom (const char *filename, int speed, unsigned int parport)
|
||||
/*
|
||||
Copy a ROM file -- this assumes the filename is valid and the file does not
|
||||
already exist, since it will blindly try to write (overwrite) the filename you
|
||||
give it.
|
||||
If the open failed due to an invalid filename or path, it prints an error.
|
||||
Speed setting should be between 1-4, 3 is default, and this is verified.
|
||||
*/
|
||||
{
|
||||
unsigned long romsize;
|
||||
unsigned char *buffer;
|
||||
FILE *f;
|
||||
|
||||
fputs (INTRO_TEXT, stdout);
|
||||
parport_print_info ();
|
||||
|
||||
if (!strlen (filename))
|
||||
{
|
||||
fputs ("ERROR: Filename not specified\n"
|
||||
" You must specify a filename on the commandline, as follows:\n"
|
||||
" ucon64 " OPTION_LONG_S "xcmc dump.bin\n", stderr);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
printf ("Speed %d selected\n", speed);
|
||||
cyan_test_parport (parport);
|
||||
printf ("Destination file: %s\n", filename);
|
||||
|
||||
if ((f = fopen (filename, "wb")) == NULL)
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], filename);
|
||||
exit (1);
|
||||
}
|
||||
fclose (f);
|
||||
|
||||
puts ("NOTE: Dumping copier's full address space (file will be automatically trimmed\n"
|
||||
" after dumping)\n"
|
||||
"Press escape or q to abort\n");
|
||||
|
||||
buffer = cyan_read_rom (speed, parport, NULL);
|
||||
if (!buffer)
|
||||
{
|
||||
remove (filename);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
fputc ('\n', stdout);
|
||||
romsize = cyan_calculate_rom_size (buffer, 0);
|
||||
|
||||
fputs ("Writing ROM to disk... ", stdout);
|
||||
fflush (stdout);
|
||||
if ((f = fopen (filename, "wb")) == NULL)
|
||||
{
|
||||
puts ("FAILED");
|
||||
fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], filename);
|
||||
free (buffer);
|
||||
exit (1);
|
||||
}
|
||||
if (fwrite (buffer, 1, romsize, f) != romsize)
|
||||
{
|
||||
puts ("FAILED");
|
||||
fprintf (stderr, ucon64_msg[WRITE_ERROR], filename);
|
||||
free (buffer);
|
||||
fclose (f);
|
||||
exit (1);
|
||||
}
|
||||
fclose (f);
|
||||
printf ("%d kBytes OK\n"
|
||||
"Verifying checksum... ", (int) (romsize / 1024));
|
||||
fflush (stdout);
|
||||
|
||||
if (cyan_checksum_rom (buffer))
|
||||
{
|
||||
puts ("FAILED\n"
|
||||
"WARNING: Checksum of ROM does not appear to be correct.\n"
|
||||
" This may be normal for this ROM, or it may indicate a bad copy.\n"
|
||||
" Please verify the ROM, and consider running a copier test");
|
||||
}
|
||||
else
|
||||
puts ("OK");
|
||||
|
||||
puts ("Copy complete!\n"
|
||||
"Don't forget to turn the ROM copier off, and never insert or remove a\n"
|
||||
"cartridge with the power on");
|
||||
|
||||
free (buffer);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
#endif // USE_PARALLEL
|
||||
|
||||
|
||||
/*******************
|
||||
* uCON64 wrapping *
|
||||
*******************/
|
||||
|
||||
const st_getopt2_t cmc_usage[] =
|
||||
{
|
||||
{
|
||||
NULL, 0, 0, 0,
|
||||
NULL, "Cyan's Megadrive ROM copier"/*"1999-2004 Cyan Helkaraxe"*/,
|
||||
NULL
|
||||
},
|
||||
#ifdef USE_PARALLEL
|
||||
{
|
||||
"xcmc", 0, 0, UCON64_XCMC,
|
||||
NULL, "receive ROM from Cyan's Megadrive ROM copier; " OPTION_LONG_S "port=PORT",
|
||||
&ucon64_wf[WF_OBJ_GEN_STOP_NO_ROM]
|
||||
},
|
||||
{
|
||||
"xcmct", 1, 0, UCON64_XCMCT,
|
||||
"TEST", "run test TEST\n"
|
||||
"TEST=1 burn-in reliability test (specify speed)\n"
|
||||
"TEST=2 testbench mode (experts only)",
|
||||
&ucon64_wf[WF_OBJ_GEN_STOP_NO_ROM]
|
||||
},
|
||||
{
|
||||
"xcmcm", 1, 0, UCON64_XCMCM,
|
||||
"SPEED", "specify transfer speed\n"
|
||||
"SPEED=1 slow (debug)\n"
|
||||
"SPEED=2 medium\n"
|
||||
"SPEED=3 fast (default)\n" // verify with value of DEFAULT_SPEED
|
||||
"SPEED=4 full speed (risky)",
|
||||
&ucon64_wf[WF_OBJ_GEN_SWITCH]
|
||||
},
|
||||
#endif // USE_PARALLEL
|
||||
{NULL, 0, 0, 0, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
#ifdef USE_PARALLEL
|
||||
|
||||
int
|
||||
cmc_read_rom (const char *filename, unsigned int parport, int speed)
|
||||
{
|
||||
#if (defined __unix__ || defined __BEOS__) && !defined __MSDOS__
|
||||
init_conio ();
|
||||
#endif
|
||||
|
||||
if (speed < 1 || speed > 4)
|
||||
speed = DEFAULT_SPEED;
|
||||
cyan_copy_rom (filename, speed, parport);
|
||||
|
||||
#if (defined __unix__ || defined __BEOS__) && !defined __MSDOS__
|
||||
deinit_conio ();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cmc_test (int test, unsigned int parport, int speed)
|
||||
{
|
||||
#if (defined __unix__ || defined __BEOS__) && !defined __MSDOS__
|
||||
init_conio ();
|
||||
#endif
|
||||
|
||||
if (test < 1 || test > 2)
|
||||
{
|
||||
fputs ("ERROR: Choose a test between 1 and 2 (inclusive)\n", stderr);
|
||||
exit (1);
|
||||
}
|
||||
if (speed < 1 || speed > 4)
|
||||
speed = DEFAULT_SPEED;
|
||||
cyan_test_copier (test, speed, parport);
|
||||
|
||||
#if (defined __unix__ || defined __BEOS__) && !defined __MSDOS__
|
||||
deinit_conio ();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // USE_PARALLEL
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
cmc.h - Cyan's Megadrive ROM copier support for uCON64
|
||||
|
||||
Copyright (c) 1999-2004 Cyan Helkaraxe
|
||||
|
||||
|
||||
This program 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
// See cmc.c for important information
|
||||
#ifndef CMC_H
|
||||
#define CMC_H
|
||||
|
||||
extern const st_getopt2_t cmc_usage[];
|
||||
|
||||
#ifdef USE_PARALLEL
|
||||
extern int cmc_read_rom (const char *filename, unsigned int parport, int speed);
|
||||
extern int cmc_test (int test, unsigned int parport, int speed);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,139 +0,0 @@
|
||||
/*
|
||||
dex.c - DexDrive support for uCON64
|
||||
|
||||
Copyright (c) 2002 NoisyB <noisyb@gmx.net>
|
||||
Copyright (c) 2004 dbjh
|
||||
|
||||
|
||||
This program 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "misc/misc.h"
|
||||
#include "misc/file.h"
|
||||
#ifdef USE_ZLIB
|
||||
#include "misc/archive.h"
|
||||
#endif
|
||||
#include "misc/getopt2.h" // st_getopt2_t
|
||||
#include "ucon64.h"
|
||||
#include "ucon64_misc.h"
|
||||
#include "dex.h"
|
||||
#include "psxpblib.h"
|
||||
#include "misc/parallel.h"
|
||||
|
||||
|
||||
const st_getopt2_t dex_usage[] =
|
||||
{
|
||||
{
|
||||
NULL, 0, 0, 0,
|
||||
NULL, "DexDrive"/*"19XX InterAct http://www.dexdrive.de"*/,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
"xdex", 1, 0, UCON64_XDEX,
|
||||
"N", "send/receive Block N to/from DexDrive; " OPTION_LONG_S "port=PORT\n"
|
||||
"receives automatically when SRAM does not exist",
|
||||
&ucon64_wf[WF_OBJ_ALL_DEFAULT_STOP_NO_ROM]
|
||||
},
|
||||
{NULL, 0, 0, 0, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
#ifdef USE_PARALLEL
|
||||
|
||||
#define CONPORT 1
|
||||
#define TAP 1
|
||||
#define DELAY 4
|
||||
#define FRAME_SIZE 128
|
||||
#define BLOCK_SIZE (64*FRAME_SIZE)
|
||||
|
||||
static int print_data;
|
||||
|
||||
|
||||
static unsigned char *
|
||||
read_block (int block_num)
|
||||
{
|
||||
return psx_memcard_read_block (print_data, CONPORT, TAP, DELAY, block_num);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
write_block (int block_num, unsigned char *data)
|
||||
{
|
||||
return psx_memcard_write_block (print_data, CONPORT, TAP, DELAY, block_num,
|
||||
data);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
char *
|
||||
read_frame (int frame, char *data)
|
||||
{
|
||||
return psx_memcard_read_frame (print_data, CONPORT, TAP, DELAY, frame);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
write_frame (int frame, char *data)
|
||||
{
|
||||
return psx_memcard_write_frame (print_data, CONPORT, TAP, DELAY, frame,
|
||||
data);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int
|
||||
dex_read_block (const char *filename, int block_num, unsigned int parport)
|
||||
{
|
||||
unsigned char *data;
|
||||
|
||||
print_data = parport;
|
||||
parport_print_info ();
|
||||
|
||||
if ((data = read_block (block_num)) == NULL)
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[PARPORT_ERROR]);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
ucon64_fwrite (data, 0, BLOCK_SIZE, filename, "wb");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
dex_write_block (const char *filename, int block_num, unsigned int parport)
|
||||
{
|
||||
unsigned char data[BLOCK_SIZE];
|
||||
|
||||
print_data = parport;
|
||||
parport_print_info ();
|
||||
|
||||
ucon64_fread (data, 0, BLOCK_SIZE, filename);
|
||||
|
||||
if (write_block (block_num, data) == -1)
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[PARPORT_ERROR]);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // USE_PARALLEL
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
dex.h - DexDrive support for uCON64
|
||||
|
||||
Copyright (c) 2002 NoisyB <noisyb@gmx.net>
|
||||
|
||||
|
||||
This program 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#ifndef DEX_H
|
||||
#define DEX_H
|
||||
|
||||
extern const st_getopt2_t dex_usage[];
|
||||
|
||||
#define DEX_HEADER_START 0
|
||||
#define DEX_HEADER_LEN 0
|
||||
|
||||
#ifdef USE_PARALLEL
|
||||
extern int dex_read_block (const char *filename, int block_num, unsigned int parport);
|
||||
extern int dex_write_block (const char *filename, int block_num, unsigned int parport);
|
||||
#endif // USE_PARALLEL
|
||||
|
||||
#endif
|
||||
@@ -1,399 +0,0 @@
|
||||
/*
|
||||
doctor64.c - Bung Doctor V64 support for uCON64
|
||||
|
||||
Copyright (c) 1999 - 2001 NoisyB <noisyb@gmx.net>
|
||||
|
||||
|
||||
This program 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include "misc/misc.h"
|
||||
#include "misc/file.h"
|
||||
#ifdef USE_ZLIB
|
||||
#include "misc/archive.h"
|
||||
#endif
|
||||
#include "misc/getopt2.h" // st_getopt2_t
|
||||
#include "ucon64.h"
|
||||
#include "ucon64_misc.h"
|
||||
#include "doctor64.h"
|
||||
#include "misc/parallel.h"
|
||||
|
||||
|
||||
const st_getopt2_t doctor64_usage[] =
|
||||
{
|
||||
{
|
||||
NULL, 0, 0, 0,
|
||||
NULL, "Doctor V64"/*"19XX Bung Enterprises Ltd http://www.bung.com.hk"*/,
|
||||
NULL
|
||||
},
|
||||
#ifdef USE_PARALLEL
|
||||
{
|
||||
"xv64", 0, 0, UCON64_XV64,
|
||||
NULL, "send/receive ROM to/from Doctor V64; " OPTION_LONG_S "port=PORT\n"
|
||||
"receives automatically when ROM does not exist",
|
||||
&ucon64_wf[WF_OBJ_N64_DEFAULT_STOP_NO_ROM]
|
||||
},
|
||||
#endif
|
||||
{NULL, 0, 0, 0, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
#ifdef USE_PARALLEL
|
||||
|
||||
#define SYNC_MAX_CNT 8192
|
||||
#define SYNC_MAX_TRY 32
|
||||
#define SEND_MAX_WAIT 0x300000
|
||||
#define REC_HIGH_NIBBLE 0x80
|
||||
#define REC_LOW_NIBBLE 0x00
|
||||
#define REC_MAX_WAIT SEND_MAX_WAIT
|
||||
|
||||
|
||||
static int
|
||||
parport_write (char src[], int len, unsigned int parport)
|
||||
{
|
||||
int maxwait, i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
maxwait = SEND_MAX_WAIT;
|
||||
if ((inportb ((unsigned short) (parport + 2)) & 1) == 0) // check ~strobe
|
||||
{
|
||||
while (((inportb ((unsigned short) (parport + 2)) & 2) != 0) && maxwait--)
|
||||
; // wait for
|
||||
if (maxwait <= 0)
|
||||
return 1; // auto feed == 0
|
||||
outportb ((unsigned short) parport, src[i]); // write data
|
||||
outportb ((unsigned short) (parport + 2), 5); // ~strobe = 1
|
||||
}
|
||||
else
|
||||
{
|
||||
while (((inportb ((unsigned short) (parport + 2)) & 2) == 0) && maxwait--)
|
||||
; // wait for
|
||||
if (maxwait <= 0)
|
||||
return 1; // auto feed == 1
|
||||
outportb ((unsigned short) parport, src[i]); // write data
|
||||
outportb ((unsigned short) (parport + 2), 4); // ~strobe = 0
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
parport_read (char dest[], int len, unsigned int parport)
|
||||
{
|
||||
int i, maxwait;
|
||||
unsigned char c;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
outportb ((unsigned short) parport, REC_HIGH_NIBBLE);
|
||||
maxwait = REC_MAX_WAIT;
|
||||
while (((inportb ((unsigned short) (parport + 1)) & 0x80) == 0) && maxwait--)
|
||||
; // wait for ~busy=1
|
||||
if (maxwait <= 0)
|
||||
return len - i;
|
||||
c = (inportb ((unsigned short) (parport + 1)) >> 3) & 0x0f; // ~ack, pe, slct, ~error
|
||||
|
||||
outportb ((unsigned short) parport, REC_LOW_NIBBLE);
|
||||
maxwait = REC_MAX_WAIT;
|
||||
while (((inportb ((unsigned short) (parport + 1)) & 0x80) != 0) && maxwait--)
|
||||
; // wait for ~busy=0
|
||||
if (maxwait <= 0)
|
||||
return len - i;
|
||||
c |= (inportb ((unsigned short) (parport + 1)) << 1) & 0xf0; // ~ack, pe, slct, ~error
|
||||
|
||||
dest[i] = c;
|
||||
}
|
||||
outportb ((unsigned short) parport, REC_HIGH_NIBBLE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
syncHeader (unsigned int baseport)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
outportb ((unsigned short) baseport, 0); // data = 00000000
|
||||
outportb ((unsigned short) (baseport + 2), 4); // ~strobe=0
|
||||
while (i < SYNC_MAX_CNT)
|
||||
{
|
||||
if ((inportb ((unsigned short) (baseport + 2)) & 8) == 0) // wait for select=0
|
||||
{
|
||||
outportb ((unsigned short) (baseport), 0xaa); // data = 10101010
|
||||
outportb ((unsigned short) (baseport + 2), 0); // ~strobe=0, ~init=0
|
||||
while (i < SYNC_MAX_CNT)
|
||||
{
|
||||
if ((inportb ((unsigned short) (baseport + 2)) & 8) != 0) // wait for select=1
|
||||
{
|
||||
outportb ((unsigned short) (baseport + 2), 4); // ~strobe=0
|
||||
while (i < SYNC_MAX_CNT)
|
||||
{
|
||||
if ((inportb ((unsigned short) (baseport + 2)) & 8) == 0) // w for select=0
|
||||
{
|
||||
outportb ((unsigned short) baseport, 0x55); // data = 01010101
|
||||
outportb ((unsigned short) (baseport + 2), 0); // ~strobe=0, ~init=0
|
||||
while (i < SYNC_MAX_CNT)
|
||||
{
|
||||
if ((inportb ((unsigned short) (baseport + 2)) & 8) != 0) // w select=1
|
||||
{
|
||||
outportb ((unsigned short) (baseport + 2), 4); // ~strobe=0
|
||||
while (i < SYNC_MAX_CNT)
|
||||
{
|
||||
if ((inportb ((unsigned short) (baseport + 2)) & 8) == 0) // select=0
|
||||
return 0;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
outportb ((unsigned short) (baseport + 2), 4);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
initCommunication (unsigned int port)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < SYNC_MAX_TRY; i++)
|
||||
{
|
||||
if (syncHeader (port) == 0)
|
||||
break;
|
||||
}
|
||||
if (i >= SYNC_MAX_TRY)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
checkSync (unsigned int baseport)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < SYNC_MAX_CNT; i++)
|
||||
{
|
||||
if (((inportb ((unsigned short) (baseport + 2)) & 3) == 3)
|
||||
|| ((inportb ((unsigned short) (baseport + 2)) & 3) == 0))
|
||||
{
|
||||
outportb ((unsigned short) baseport, 0); // ~strobe, auto feed
|
||||
for (j = 0; j < SYNC_MAX_CNT; j++)
|
||||
{
|
||||
if ((inportb ((unsigned short) (baseport + 1)) & 0x80) == 0) // wait for ~busy=0
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
sendFilename (unsigned int baseport, char name[])
|
||||
{
|
||||
int i;
|
||||
char *c, mname[12];
|
||||
|
||||
memset (mname, ' ', 11);
|
||||
c = (strrchr (name, FILE_SEPARATOR));
|
||||
if (c == NULL)
|
||||
{
|
||||
c = name;
|
||||
}
|
||||
else
|
||||
{
|
||||
c++;
|
||||
}
|
||||
for (i = 0; i < 8 && *c != '.' && *c != '\0'; i++, c++)
|
||||
mname[i] = toupper (*c);
|
||||
c = strrchr (c, '.');
|
||||
if (c != NULL)
|
||||
{
|
||||
c++;
|
||||
for (i = 8; i < 11 && *c != '\0'; i++, c++)
|
||||
mname[i] = toupper (*c);
|
||||
}
|
||||
|
||||
return parport_write (mname, 11, baseport);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
sendUploadHeader (unsigned int baseport, char name[], int len)
|
||||
{
|
||||
char mname[12], lenbuffer[4];
|
||||
static char protocolId[] = "GD6R\1";
|
||||
|
||||
if (parport_write (protocolId, strlen (protocolId), baseport) != 0)
|
||||
return 1;
|
||||
|
||||
lenbuffer[0] = (char) len;
|
||||
lenbuffer[1] = (char) (len >> 8);
|
||||
lenbuffer[2] = (char) (len >> 16);
|
||||
lenbuffer[3] = (char) (len >> 24);
|
||||
if (parport_write (lenbuffer, 4, baseport) != 0)
|
||||
return 1;
|
||||
|
||||
memset (mname, ' ', 11);
|
||||
if (sendFilename (baseport, name) != 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
sendDownloadHeader (unsigned int baseport, int *len)
|
||||
{
|
||||
char mname[12];
|
||||
static char protocolId[] = "GD6W";
|
||||
unsigned char recbuffer[15];
|
||||
|
||||
if (parport_write (protocolId, strlen (protocolId), baseport) != 0)
|
||||
return 1;
|
||||
memset (mname, ' ', 11);
|
||||
if (parport_write (mname, 11, baseport) != 0)
|
||||
return 1;
|
||||
if (checkSync (baseport) != 0)
|
||||
return 1;
|
||||
|
||||
if (parport_read ((char *) recbuffer, 1, baseport) != 0)
|
||||
return 1;
|
||||
if (recbuffer[0] != 1)
|
||||
return -1;
|
||||
if (parport_read ((char *) recbuffer, 15, baseport) != 0)
|
||||
return 1;
|
||||
*len = (int) recbuffer[0] |
|
||||
((int) recbuffer[1] << 8) |
|
||||
((int) recbuffer[2] << 16) |
|
||||
((int) recbuffer[3] << 24);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
doctor64_read (const char *filename, unsigned int parport)
|
||||
{
|
||||
char buf[MAXBUFSIZE];
|
||||
FILE *fh;
|
||||
int size, inittime, bytesreceived = 0;
|
||||
|
||||
parport_print_info ();
|
||||
if (initCommunication (parport) == -1)
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[PARPORT_ERROR]);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
inittime = time (0);
|
||||
|
||||
if (sendDownloadHeader (parport, &size) != 0)
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[PARPORT_ERROR]);
|
||||
exit (1);
|
||||
}
|
||||
if (!(fh = fopen (filename, "wb")))
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], filename);
|
||||
exit (1);
|
||||
}
|
||||
printf ("Receive: %d Bytes (%.4f Mb)\n\n", size, (float) size / MBIT);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (parport_read (buf, sizeof buf, parport) != 0)
|
||||
{
|
||||
fclose (fh);
|
||||
return 0;
|
||||
}
|
||||
bytesreceived += sizeof buf;
|
||||
fwrite (buf, 1, sizeof buf, fh);
|
||||
ucon64_gauge (inittime, bytesreceived, size);
|
||||
}
|
||||
sync ();
|
||||
fclose (fh);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
doctor64_write (const char *filename, int start, int len, unsigned int parport)
|
||||
{
|
||||
char buf[MAXBUFSIZE];
|
||||
FILE *fh;
|
||||
unsigned int size, inittime, pos, bytessend = 0;
|
||||
|
||||
parport_print_info ();
|
||||
size = len - start;
|
||||
if (initCommunication (parport) == -1)
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[PARPORT_ERROR]);
|
||||
exit (1);
|
||||
}
|
||||
inittime = time (0);
|
||||
|
||||
strcpy (buf, filename);
|
||||
if (sendUploadHeader (parport, buf, size) != 0)
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[PARPORT_ERROR]);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (!(fh = fopen (filename, "rb")))
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], filename);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
printf ("Send: %d Bytes (%.4f Mb)\n\n", size, (float) size / MBIT);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (!(pos = fread (buf, 1, sizeof buf, fh)))
|
||||
break;
|
||||
if (parport_write (buf, pos, parport) != 0)
|
||||
break;
|
||||
bytessend += sizeof buf;
|
||||
ucon64_gauge (inittime, bytessend, size);
|
||||
}
|
||||
fclose (fh);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // USE_PARALLEL
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
doctor64.h - Bung Doctor V64 support for uCON64
|
||||
|
||||
Copyright (c) 1999 - 2001 NoisyB <noisyb@gmx.net>
|
||||
|
||||
|
||||
This program 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#ifndef DOCTOR64_H
|
||||
#define DOCTOR64_H
|
||||
|
||||
extern const st_getopt2_t doctor64_usage[];
|
||||
|
||||
#ifdef USE_PARALLEL
|
||||
extern int doctor64_read (const char *filename, unsigned int parport);
|
||||
extern int doctor64_write (const char *filename, int start, int len, unsigned int parport);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,587 +0,0 @@
|
||||
/*
|
||||
doctor64jr.c - Bung Doctor V64 Junior support for uCON64
|
||||
|
||||
Copyright (c) 1999 - 2002 NoisyB <noisyb@gmx.net>
|
||||
Copyright (c) 2004 dbjh
|
||||
|
||||
|
||||
This program 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
drjr transfer protocol
|
||||
|
||||
|
||||
DB25 pin name
|
||||
p2~p9 pd[7:0] XXXXXXXXXXX ai XXXXX data XXXX
|
||||
p1 nwrite ~~~~~~~~~|_____________________|~~
|
||||
p14 ndstb ~~~~~~~~~~~~~~~~~~~~~~~~~|_|~~~~~~
|
||||
p17 nastb ~~~~~~~~~~~~~|_|~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
ai[]=0 r/w a[7..0]
|
||||
ai[]=1 r/w a[15..8]
|
||||
ai[]=2 r/w a[23..16]
|
||||
ai[]=3 w a[28..24]
|
||||
ai[]=3 r (rst,wdf,wcf,a[28..24])
|
||||
ai[]=4 r/w data
|
||||
ai[]=5 w mode
|
||||
ai[]=6 w en_1
|
||||
ai[]=7 w en_0
|
||||
*remark
|
||||
a[8..1] support page count up
|
||||
|
||||
ai[3]d7:0=N64 power off, 1=N64 power on
|
||||
d6:0=no dram data written, 1=dram data written
|
||||
d5:0=no data write in b4000000~b7ffffff, 1=some data written in b4000000~b7ffffff
|
||||
|
||||
mode d0:0=dram read only and clear wdf, 1=dram write enable
|
||||
d1:0=disable cartridge read and clear wcf flag,
|
||||
1=enable cartridge read(write b4000000~b7ffffff will switch off dram and cartridge will present at b0000000~b3ffffff)
|
||||
|
||||
en_0=05 and en_1=0a is enable port control
|
||||
|
||||
|
||||
mode:q0 0 1 0 1
|
||||
mode:q1 0 0 1 1
|
||||
b7ff ffff
|
||||
b400 0000 dram read only dram r/w cartridge read cartridge read(* write this area will switch off dram)
|
||||
|
||||
b3ff ffff
|
||||
b000 0000 dram read only dram r/w dram read only dram r/w
|
||||
|
||||
|
||||
eg:enable port control
|
||||
|
||||
DB25 pin name
|
||||
p2~p9 pd[7:0] XXXXXXXXXXX 07 XX 05 XXXX 06 XX 0a XXXXXXXXXXXX
|
||||
p1 nwrite ~~~~~~~~~|_____________________________|~~~~~~~
|
||||
p14 ndstb ~~~~~~~~~~~~~~~~~~|_|~~~~~~~~~~~|_|~~~~~~~~~~~~
|
||||
p17 nastb ~~~~~~~~~~~~|_|~~~~~~~~~~~|_|~~~~~~~~~~~~~~~~~~
|
||||
en_0=05 en_1=0a
|
||||
|
||||
|
||||
eg:write adr $b0123456, data $a55a,$1234..
|
||||
|
||||
DB25 pin name
|
||||
p2~p9 pd[7:0] XXXXXXXXXXX 00 XX 56 XXXX 01 XX 34 XXXX 02 XX 12 XXXX 03 XX b0 XXXXXX 04 XX 5a XX a5 XX 34 XX 12 XXXXXXXXXXX
|
||||
p1 nwrite ~~~~~~~~~|_______________________________________________________________________________________|~~~~~~~~~~
|
||||
p14 ndstb ~~~~~~~~~~~~~~~~~~|_|~~~~~~~~~~~|_|~~~~~~~~~~~|_|~~~~~~~~~~~|_|~~~~~~~~~~~~~|_|~~~|_|~~~|_|~~~|_|~~~~~~~~~~~
|
||||
p17 nastb ~~~~~~~~~~~~|_|~~~~~~~~~~~|_|~~~~~~~~~~~|_|~~~~~~~~~~~|_|~~~~~~~~~~~~~|_|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
set adr word low set adr word high wdata a55a wdata 1234 (after write adr=b012345a)
|
||||
|
||||
|
||||
eg:read adr $b0123400~$b01235ff, 512 data
|
||||
|
||||
DB25 pin name
|
||||
p2~p9 pd[7:0] XXXXXXXXXXX 00 XX 00 XXXX 01 XX 34 XXXX 02 XX 12 XXXX 03 XX b0 XXXXXX 04 XX data0 XX data1 X ... X data510 XX data511 XXXXX
|
||||
p1 nwrite ~~~~~~~~~|________________________________________________________________~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
p14 ndstb ~~~~~~~~~~~~~~~~~~|_|~~~~~~~~~~~|_|~~~~~~~~~~~|_|~~~~~~~~~~~|_|~~~~~~~~~~~~~~|_|~~~~~~|_|~~~ ~~~ ~~~~|_|~~~~~~~~|_|~~~~~~~~
|
||||
p17 nastb ~~~~~~~~~~~~|_|~~~~~~~~~~~|_|~~~~~~~~~~~|_|~~~~~~~~~~~|_|~~~~~~~~~~~~~|_|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
set adr word low set adr word high (after 512 read adr=b0123400)
|
||||
|
||||
|
||||
eg:dram write protect, disable N64 access to cartridge and disable port control
|
||||
|
||||
DB25 pin name
|
||||
p2~p9 pd[7:0] XXXXXXXXXXX 05 XX 00 XXXX 07 XX 00 XXXX 06 XX 00 XXXXXXXXXXXX
|
||||
p1 nwrite ~~~~~~~~~|________________________________________|~~~~~~~~~~
|
||||
p14 ndstb ~~~~~~~~~~~~~~~~~~|_|~~~~~~~~~~~|_|~~~~~~~~~~~|_|~~~~~~~~~~~~
|
||||
p17 nastb ~~~~~~~~~~~~|_|~~~~~~~~~~~|_|~~~~~~~~~~~|_|~~~~~~~~~~~~~~~~~~
|
||||
mode=00 en_0=00 en_1=00
|
||||
|
||||
|
||||
simple backup rountine for N64
|
||||
|
||||
void writePI(unsigned long addr, unsigned long value)
|
||||
{
|
||||
do {} while (*(volatile unsigned long *) (0xa4600010) & 3); // check parallel interface not busy
|
||||
addr &=0xbffffffc;
|
||||
*(unsigned long *)(addr)=value;
|
||||
}
|
||||
|
||||
unsigned long readPI(unsigned long addr)
|
||||
{
|
||||
do {} while (*(volatile unsigned long *) (0xa4600010) & 3); // check parallel interface not busy
|
||||
addr &=0xbffffffc;
|
||||
return *(unsigned long *)(addr);
|
||||
}
|
||||
|
||||
// MAIN -- START OF USER CODE
|
||||
void mainproc(void *arg) {
|
||||
u32 base_adr;
|
||||
for (base_adr=0;base_adr<0x1000000;base_adr++){ // backup 128Mbits
|
||||
writePI(0xb0000000+base_adr,readPI(0xb4000000 + base_adr)); // write data
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include "misc/misc.h"
|
||||
#include "misc/itypes.h"
|
||||
#ifdef USE_ZLIB
|
||||
#include "misc/archive.h"
|
||||
#endif
|
||||
#include "misc/getopt2.h" // st_getopt2_t
|
||||
#include "misc/parallel.h"
|
||||
#include "misc/file.h"
|
||||
#include "ucon64.h"
|
||||
#include "ucon64_misc.h"
|
||||
#include "doctor64jr.h"
|
||||
|
||||
|
||||
const st_getopt2_t doctor64jr_usage[] =
|
||||
{
|
||||
{
|
||||
NULL, 0, 0, 0,
|
||||
NULL, "Doctor V64 Junior"/*"19XX Bung Enterprises Ltd http://www.bung.com.hk"*/,
|
||||
NULL
|
||||
},
|
||||
#ifdef USE_PARALLEL
|
||||
{
|
||||
"xdjr", 0, 0, UCON64_XDJR,
|
||||
NULL, "send ROM to Doctor V64 Junior; " OPTION_LONG_S "port=PORT",
|
||||
&ucon64_wf[WF_OBJ_N64_DEFAULT_STOP_NO_ROM]
|
||||
},
|
||||
#if 0
|
||||
{
|
||||
"xdjrs", 0, 0, UCON64_XDJRS,
|
||||
NULL, "send/receive SRAM to/from Doctor V64 Junior; " OPTION_LONG_S "port=PORT\n"
|
||||
"receives automatically when SRAM does not exist",
|
||||
&ucon64_wf[WF_OBJ_N64_DEFAULT_STOP_NO_ROM]
|
||||
},
|
||||
#endif
|
||||
#endif // USE_PARALLEL
|
||||
{NULL, 0, 0, 0, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
#ifdef USE_PARALLEL
|
||||
|
||||
#define BUFFERSIZE 32768
|
||||
//#define set_ai_write outportb (port_a, 5); // ninit=1, nwrite=0
|
||||
#define set_data_write outportb (port_a, 1); // ninit=0, nwrite=0
|
||||
#define set_data_read outportb (port_a, 0); // ninit=0, nwrite=1
|
||||
//#define set_normal outportb (port_a, 4); // ninit=1, nwrite=1
|
||||
|
||||
static unsigned short int port_8, port_9, port_a, port_b, port_c,
|
||||
*buffer;
|
||||
static int wv_mode;
|
||||
|
||||
|
||||
static void
|
||||
set_ai (unsigned char ai)
|
||||
{
|
||||
outportb (port_a, 5); // ninit=1, nwrite=0
|
||||
outportb (port_b, ai);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_ai_data (unsigned char ai, unsigned char data)
|
||||
{
|
||||
set_ai (ai);
|
||||
set_data_write // ninit=0, nwrite=0
|
||||
outportb (port_c, data);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
init_port (int enable_write)
|
||||
{
|
||||
#ifndef USE_PPDEV
|
||||
outportb (port_9, 1); // clear EPP time flag
|
||||
#endif
|
||||
set_ai_data (6, 0x0a);
|
||||
set_ai_data (7, 0x05); // 6==0x0a, 7==0x05 is pc_control mode
|
||||
// set_ai (5);
|
||||
// set_data_read
|
||||
// enable_write = inportb (port_c);
|
||||
set_ai_data (5, (unsigned char) enable_write); // d0=0 is write protect mode
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
end_port (int enable_write)
|
||||
{
|
||||
set_ai_data (5, (unsigned char) enable_write); // d0=0 is write protect mode
|
||||
set_ai_data (7, 0); // release pc mode
|
||||
set_ai_data (6, 0); // 6==0x0a, 7==0x05 is pc_control mode
|
||||
outportb (port_a, 4); // ninit=1, nwrite=1
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
check_card (void)
|
||||
{
|
||||
set_ai_data (3, 0x12);
|
||||
set_ai_data (2, 0x34);
|
||||
set_ai_data (1, 0x56);
|
||||
set_ai_data (0, 0x78);
|
||||
|
||||
set_ai (3);
|
||||
set_data_read // ninit=0, nwrite=1
|
||||
if ((inportb (port_c) & 0x1f) != 0x12)
|
||||
return 1;
|
||||
|
||||
set_ai (2);
|
||||
set_data_read
|
||||
if (inportb (port_c) != 0x34)
|
||||
return 1;
|
||||
|
||||
set_ai (1);
|
||||
set_data_read
|
||||
if (inportb (port_c) != 0x56)
|
||||
return 1;
|
||||
|
||||
set_ai (0);
|
||||
set_data_read
|
||||
if (inportb (port_c) != 0x78)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
write_32k (unsigned short int hi_word, unsigned short int lo_word)
|
||||
{
|
||||
unsigned char unpass, pass1;
|
||||
unsigned short int i, j, fix;
|
||||
|
||||
set_ai_data (3, (unsigned char) (0x10 | (hi_word >> 8)));
|
||||
set_ai_data (2, (unsigned char) hi_word);
|
||||
for (i = 0; i < 0x40; i++)
|
||||
{
|
||||
unpass = 3;
|
||||
while (unpass)
|
||||
{
|
||||
set_ai_data (1, (unsigned char) ((i << 1) | lo_word));
|
||||
set_ai_data (0, 0);
|
||||
set_ai (4); // set address index=4
|
||||
set_data_write // ninit=0, nwrite=0
|
||||
fix = i << 8;
|
||||
for (j = 0; j < 256; j++)
|
||||
outportw (port_c, buffer[j + fix]);
|
||||
set_data_read // ninit=0, nwrite=1
|
||||
if (wv_mode)
|
||||
{
|
||||
for (j = 0; j < 256; j++)
|
||||
if (inportw (port_c) != buffer[j + fix])
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
pass1 = 1;
|
||||
for (j = 0; j < 4; j++)
|
||||
if (inportw (port_c) != buffer[j + fix])
|
||||
{
|
||||
pass1 = 0;
|
||||
break;
|
||||
}
|
||||
if (pass1)
|
||||
{
|
||||
set_ai_data (1, (unsigned char) ((i << 1) | lo_word | 1));
|
||||
set_ai_data (0, 0xf8);
|
||||
set_ai (4);
|
||||
set_data_read // ninit=0, nwrite=1
|
||||
for (j = 252; j < 256; j++)
|
||||
if (inportw (port_c) != buffer[j + fix])
|
||||
break;
|
||||
}
|
||||
}
|
||||
set_ai (0);
|
||||
set_data_read // ninit=0, nwrite=1
|
||||
if (inportb (port_c) != 0)
|
||||
{
|
||||
unpass--;
|
||||
outportb (port_a, 0x0b); // set all pin=0 for debug
|
||||
set_ai_data (3, (unsigned char) (0x10 | (hi_word >> 8)));
|
||||
set_ai_data (2, (unsigned char) hi_word);
|
||||
if (unpass == 0)
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
unpass = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
outportb (ai, 0);
|
||||
printf ("\na[7..0]=%02x\n", inportb (data));
|
||||
outportb (ai, 1);
|
||||
printf ("a[15..8]=%02x\n", inportb (data));
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#if 0 // not used
|
||||
static int
|
||||
verify_32k (unsigned short int hi_word, unsigned short int lo_word)
|
||||
{
|
||||
char unpass;
|
||||
unsigned short int i, j, fix;
|
||||
|
||||
set_ai_data (3, (unsigned char) (0x10 | (hi_word >> 8)));
|
||||
set_ai_data (2, (unsigned char) hi_word);
|
||||
for (i = 0; i < 0x40; i++)
|
||||
{
|
||||
unpass = 3;
|
||||
while (unpass)
|
||||
{
|
||||
set_ai_data (1, (unsigned char) ((i << 1) | lo_word));
|
||||
set_ai_data (0, 0);
|
||||
set_ai (4);
|
||||
set_data_read // ninit=0, nwrite=1
|
||||
fix = i << 8;
|
||||
for (j = 0; j < 256; j++)
|
||||
{
|
||||
if (inportw (port_c) != buffer[j + fix])
|
||||
{
|
||||
outportb (port_a, 0x0b); // all pin=0 for debug
|
||||
set_ai_data (3, (unsigned char) (0x10 | (hi_word >> 8)));
|
||||
set_ai_data (2, (unsigned char) hi_word);
|
||||
unpass--;
|
||||
if (unpass == 0)
|
||||
return 1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j == 256)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
outportb (ai,0);
|
||||
printf ("\na[7..0]=%02x\n", inportb (data));
|
||||
outportb (ai, 1);
|
||||
printf ("a[15..8]=%02x\n", inportb (data));
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gen_pat_32k (unsigned short int offset)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 0x4000; i++)
|
||||
buffer[i] = i + offset;
|
||||
}
|
||||
|
||||
|
||||
static unsigned short int
|
||||
test_dram (void)
|
||||
{
|
||||
int n_pages = 0, page;
|
||||
|
||||
gen_pat_32k (0x0000);
|
||||
write_32k (0, 0);
|
||||
|
||||
gen_pat_32k (0x8000);
|
||||
write_32k (0x100, 0);
|
||||
|
||||
gen_pat_32k (0x0000);
|
||||
if (verify_32k (0, 0) == 0) // find lower 128 Mbits
|
||||
n_pages = 0x100;
|
||||
gen_pat_32k (0x8000);
|
||||
if (verify_32k (0x100, 0) == 0) // find upper 128 Mbits
|
||||
n_pages = 0x200;
|
||||
|
||||
printf ("Testing DRAM...\n");
|
||||
|
||||
for (page = 0; page < n_pages; page++)
|
||||
{
|
||||
gen_pat_32k ((unsigned short int) (page * 2));
|
||||
if (write_32k (page, 0))
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
fputc ('w', stdout);
|
||||
fflush (stdout);
|
||||
}
|
||||
|
||||
gen_pat_32k ((unsigned short int) (page * 2 + 1));
|
||||
if (write_32k (page, 0x80))
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
fputc ('w', stdout);
|
||||
fflush (stdout);
|
||||
}
|
||||
}
|
||||
|
||||
fputc ('\n', stdout);
|
||||
for (page = 0; page < n_pages; page++)
|
||||
{
|
||||
gen_pat_32k ((unsigned short int) (page * 2));
|
||||
if (verify_32k (page, 0))
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
fputc ('v', stdout);
|
||||
fflush (stdout);
|
||||
}
|
||||
gen_pat_32k ((unsigned short int) (page * 2 + 1));
|
||||
if (verify_32k (page, 0x80))
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
fputc ('v', stdout);
|
||||
fflush (stdout);
|
||||
}
|
||||
}
|
||||
|
||||
return n_pages;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static unsigned long int
|
||||
get_address (void)
|
||||
{
|
||||
unsigned long int address;
|
||||
|
||||
set_ai_data (6, 0x0a); // enable pc mode
|
||||
set_ai_data (7, 0x05); // enable pc mode
|
||||
|
||||
set_ai (3);
|
||||
set_data_read // ninit=0, nwrite=1
|
||||
address = inportb (port_c) << 24;
|
||||
|
||||
set_ai (2);
|
||||
set_data_read
|
||||
address |= inportb (port_c) << 16;
|
||||
|
||||
set_ai (1);
|
||||
set_data_read
|
||||
address |= inportb (port_c) << 8;
|
||||
|
||||
set_ai (0);
|
||||
set_data_read
|
||||
address |= inportb (port_c);
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
doctor64jr_read (const char *filename, unsigned int parport)
|
||||
{
|
||||
(void) filename;
|
||||
(void) parport;
|
||||
return fprintf (stderr, "ERROR: The function for dumping a cartridge is not yet implemented for the\n"
|
||||
" Doctor V64 Junior\n");
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
doctor64jr_write (const char *filename, unsigned int parport)
|
||||
{
|
||||
unsigned int enable_write = 0, init_time, size, bytesread, bytessend = 0,
|
||||
n_pages;
|
||||
unsigned short int page;
|
||||
FILE *file;
|
||||
|
||||
parport_print_info ();
|
||||
|
||||
port_8 = parport;
|
||||
port_9 = parport + 1;
|
||||
port_a = parport + 2;
|
||||
port_b = parport + 3;
|
||||
port_c = parport + 4;
|
||||
|
||||
init_port (enable_write);
|
||||
|
||||
if (check_card () != 0)
|
||||
{
|
||||
fprintf (stderr, "ERROR: No Doctor V64 Junior card present\n");
|
||||
end_port (enable_write);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
wv_mode = 0;
|
||||
|
||||
if ((file = fopen (filename, "rb")) == NULL)
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], filename);
|
||||
exit (1);
|
||||
}
|
||||
if ((buffer = (unsigned short int *) malloc (BUFFERSIZE)) == NULL)
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[FILE_BUFFER_ERROR], BUFFERSIZE);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
size = fsizeof (filename);
|
||||
printf ("Send: %d Bytes (%.4f Mb)\n\n", size, (float) size / MBIT);
|
||||
|
||||
#if 0
|
||||
if (dram_test)
|
||||
{
|
||||
dram_size = test_dram ();
|
||||
if (dram_size)
|
||||
printf ("\nDRAM size=%dMbits\n", (dram_size / 2));
|
||||
else
|
||||
fprintf (stderr, "\nERROR: DRAM test failed\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
n_pages = (size + (64 * 1024 - 1)) / (64 * 1024); // "+ (64 * 1024 - 1)" to round up
|
||||
init_time = time (0);
|
||||
for (page = 0; page < n_pages; page++)
|
||||
{
|
||||
bytesread = fread ((unsigned char *) buffer, 1, BUFFERSIZE, file);
|
||||
if (write_32k (page, 0))
|
||||
{
|
||||
fprintf (stderr, "ERROR: Transfer failed at address 0x%8lx", get_address ());
|
||||
break;
|
||||
}
|
||||
|
||||
bytesread += fread ((unsigned char *) buffer, 1, BUFFERSIZE, file);
|
||||
if (write_32k (page, 0x80))
|
||||
{
|
||||
fprintf (stderr, "ERROR: Transfer failed at address 0x%8lx", get_address ());
|
||||
break;
|
||||
}
|
||||
|
||||
bytessend += bytesread;
|
||||
ucon64_gauge (init_time, bytessend, size);
|
||||
}
|
||||
fputc ('\n', stdout);
|
||||
|
||||
if (enable_write) // 1 or 3
|
||||
printf ("DRAM write protect disabled\n");
|
||||
if (enable_write & 2) // 3
|
||||
printf ("Run cartridge enabled\n");
|
||||
|
||||
// set_ai_data(5, enable_write); // d0=0 is write protect mode
|
||||
end_port (enable_write);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // USE_PARALLEL
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
doctor64jr.h - Bung Doctor V64 Junior support for uCON64
|
||||
|
||||
Copyright (c) 1999 - 2001 NoisyB <noisyb@gmx.net>
|
||||
|
||||
|
||||
This program 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#ifndef DOCTOR64JR_H
|
||||
#define DOCTOR64JR_H
|
||||
|
||||
extern const st_getopt2_t doctor64jr_usage[];
|
||||
|
||||
#ifdef USE_PARALLEL
|
||||
extern int doctor64jr_read (const char *filename, unsigned int parport);
|
||||
extern int doctor64jr_write (const char *filename, unsigned int parport);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
f2a.h - Flash 2 Advance support for uCON64
|
||||
|
||||
Copyright (c) 2003 Ulrich Hecht <uli@emulinks.de>
|
||||
Copyright (c) 2004 NoisyB <noisyb@gmx.net>
|
||||
|
||||
|
||||
This program 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#ifndef F2A_H
|
||||
#define F2A_H
|
||||
|
||||
extern const st_getopt2_t f2a_usage[];
|
||||
|
||||
#if defined USE_PARALLEL || defined USE_USB
|
||||
extern int f2a_read_rom (const char *filename, int size);
|
||||
extern int f2a_write_rom (const char *filename, int size);
|
||||
extern int f2a_read_sram (const char *filename, int bank);
|
||||
extern int f2a_write_sram (const char *filename, int bank);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
fal.h - Flash Linker Advance support for uCON64
|
||||
|
||||
Copyright (c) 2001 Jeff Frohwein
|
||||
Copyright (c) 2001 NoisyB <noisyb@gmx.net>
|
||||
Copyright (c) 2001 - 2002 dbjh
|
||||
|
||||
|
||||
This program 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#ifndef FAL_H
|
||||
#define FAL_H
|
||||
|
||||
extern const st_getopt2_t fal_usage[];
|
||||
|
||||
#ifdef USE_PARALLEL
|
||||
extern int fal_read_rom (const char *filename, unsigned int parport, int size);
|
||||
extern int fal_write_rom (const char *filename, unsigned int parport);
|
||||
extern int fal_read_sram (const char *filename, unsigned int parport, int bank);
|
||||
extern int fal_write_sram (const char *filename, unsigned int parport, int bank);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,316 +0,0 @@
|
||||
/*
|
||||
ffe.c - General Front Far East copier routines for uCON64
|
||||
|
||||
Copyright (c) 2002 - 2004 dbjh
|
||||
Copyright (c) 2003 JohnDie
|
||||
|
||||
|
||||
This program 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include "misc/misc.h" // kbhit(), getch()
|
||||
#include "misc/itypes.h"
|
||||
#ifdef USE_ZLIB
|
||||
#include "misc/archive.h"
|
||||
#endif
|
||||
#include "misc/getopt2.h" // st_getopt2_t
|
||||
#include "ucon64.h"
|
||||
#include "ucon64_misc.h"
|
||||
#include "ffe.h"
|
||||
#include "misc/parallel.h"
|
||||
|
||||
|
||||
#ifdef USE_PARALLEL
|
||||
|
||||
#define N_TRY_MAX 65536 // # times to test if copier ready
|
||||
|
||||
|
||||
static void ffe_sendb (unsigned char byte);
|
||||
static unsigned char ffe_wait_while_busy (void);
|
||||
|
||||
static int ffe_port;
|
||||
|
||||
|
||||
void
|
||||
ffe_init_io (unsigned int port)
|
||||
/*
|
||||
- sets global `ffe_port'. Then the send/receive functions don't need to pass `port' all
|
||||
the way to ffe_sendb()/ffe_receiveb().
|
||||
- calls init_conio(). Necessary for kbhit() and DOS-like behaviour of getch().
|
||||
*/
|
||||
{
|
||||
ffe_port = port;
|
||||
#if 0 // we want to support non-standard parallel port addresses
|
||||
if (ffe_port != 0x3bc && ffe_port != 0x378 && ffe_port != 0x278)
|
||||
{
|
||||
fprintf (stderr, "ERROR: PORT must be 0x3bc, 0x378 or 0x278\n");
|
||||
exit (1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (defined __unix__ || defined __BEOS__) && !defined __MSDOS__
|
||||
init_conio ();
|
||||
#endif
|
||||
|
||||
parport_print_info ();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ffe_deinit_io (void)
|
||||
{
|
||||
#if (defined __unix__ || defined __BEOS__) && !defined __MSDOS__
|
||||
deinit_conio ();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ffe_send_block (unsigned short address, unsigned char *buffer, int len)
|
||||
{
|
||||
int n;
|
||||
unsigned char checksum = 0x81;
|
||||
|
||||
ffe_send_command (0, address, (unsigned short) len);
|
||||
for (n = 0; n < len; n++)
|
||||
{
|
||||
ffe_sendb (buffer[n]);
|
||||
checksum ^= buffer[n];
|
||||
}
|
||||
ffe_sendb (checksum);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ffe_send_block2 (unsigned short address, unsigned char *buffer, int len)
|
||||
{
|
||||
int n;
|
||||
unsigned char checksum = 0x81;
|
||||
|
||||
ffe_send_command (2, address, (unsigned short) len);
|
||||
for (n = 0; n < len; n++)
|
||||
{
|
||||
ffe_sendb (buffer[n]);
|
||||
checksum ^= buffer[n];
|
||||
}
|
||||
ffe_sendb (checksum);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ffe_send_command0 (unsigned short address, unsigned char byte)
|
||||
// command 0 for 1 byte
|
||||
{
|
||||
ffe_send_command (0, address, 1);
|
||||
ffe_sendb (byte);
|
||||
ffe_sendb ((unsigned char) (0x81 ^ byte));
|
||||
}
|
||||
|
||||
|
||||
unsigned char
|
||||
ffe_send_command1 (unsigned short address)
|
||||
// command 1 for 1 byte
|
||||
{
|
||||
unsigned char byte;
|
||||
|
||||
ffe_send_command (1, address, 1);
|
||||
byte = ffe_receiveb ();
|
||||
if ((0x81 ^ byte) != ffe_receiveb ())
|
||||
puts ("received data is corrupt");
|
||||
|
||||
return byte;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ffe_send_command (unsigned char command_code, unsigned short a, unsigned short l)
|
||||
{
|
||||
ffe_sendb (0xd5);
|
||||
ffe_sendb (0xaa);
|
||||
ffe_sendb (0x96);
|
||||
ffe_sendb (command_code);
|
||||
ffe_sendb ((unsigned char) a); // low byte
|
||||
ffe_sendb ((unsigned char) (a >> 8)); // high byte
|
||||
ffe_sendb ((unsigned char) l); // low byte
|
||||
ffe_sendb ((unsigned char) (l >> 8)); // high byte
|
||||
ffe_sendb ((unsigned char) (0x81 ^ command_code ^ a ^ (a >> 8) ^ l ^ (l >> 8))); // check sum
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ffe_sendb (unsigned char byte)
|
||||
{
|
||||
ffe_wait_for_ready ();
|
||||
outportb ((unsigned short) (ffe_port + PARPORT_DATA), byte);
|
||||
outportb ((unsigned short) (ffe_port + PARPORT_CONTROL),
|
||||
(unsigned char) (inportb ((unsigned short) // invert strobe
|
||||
(ffe_port + PARPORT_CONTROL)) ^ PARPORT_STROBE));
|
||||
ffe_wait_for_ready (); // necessary if followed by ffe_receiveb()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ffe_receive_block (unsigned short address, unsigned char *buffer, int len)
|
||||
{
|
||||
volatile int n;
|
||||
int n_try = 0;
|
||||
unsigned char checksum1, checksum2;
|
||||
|
||||
do
|
||||
{
|
||||
checksum1 = 0x81;
|
||||
ffe_send_command (1, address, (unsigned short) len);
|
||||
for (n = 0; n < len; n++)
|
||||
{
|
||||
buffer[n] = ffe_receiveb ();
|
||||
checksum1 ^= buffer[n];
|
||||
}
|
||||
checksum2 = ffe_receiveb ();
|
||||
|
||||
for (n = 0; n < 65536; n++) // a delay is necessary here
|
||||
;
|
||||
|
||||
n_try++;
|
||||
}
|
||||
while ((checksum1 != checksum2) && (n_try < N_TRY_MAX));
|
||||
|
||||
if (checksum1 != checksum2)
|
||||
puts ("\nreceived data is corrupt");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ffe_receive_block2 (unsigned short address, unsigned char *buffer, int len)
|
||||
{
|
||||
volatile int n;
|
||||
int n_try = 0;
|
||||
unsigned char checksum1, checksum2;
|
||||
|
||||
do
|
||||
{
|
||||
checksum1 = 0x81;
|
||||
ffe_send_command (3, address, (unsigned short) len);
|
||||
for (n = 0; n < len; n++)
|
||||
{
|
||||
buffer[n] = ffe_receiveb ();
|
||||
checksum1 ^= buffer[n];
|
||||
}
|
||||
checksum2 = ffe_receiveb ();
|
||||
|
||||
for (n = 0; n < 65536; n++) // a delay is necessary here
|
||||
;
|
||||
|
||||
n_try++;
|
||||
}
|
||||
while ((checksum1 != checksum2) && (n_try < N_TRY_MAX));
|
||||
|
||||
if (checksum1 != checksum2)
|
||||
puts ("\nreceived data is corrupt");
|
||||
}
|
||||
|
||||
|
||||
unsigned char
|
||||
ffe_receiveb (void)
|
||||
{
|
||||
unsigned char byte;
|
||||
|
||||
byte = (unsigned char) ((ffe_wait_while_busy () & PARPORT_INPUT_MASK) >> 3); // receive low nibble
|
||||
outportb ((unsigned short) (ffe_port + PARPORT_CONTROL),
|
||||
(unsigned char) (inportb ((unsigned short) // invert strobe
|
||||
(ffe_port + PARPORT_CONTROL)) ^ PARPORT_STROBE));
|
||||
byte |= (unsigned char) ((ffe_wait_while_busy () & PARPORT_INPUT_MASK) << 1); // receive high nibble
|
||||
outportb ((unsigned short) (ffe_port + PARPORT_CONTROL),
|
||||
(unsigned char) (inportb ((unsigned short) // invert strobe
|
||||
(ffe_port + PARPORT_CONTROL)) ^ PARPORT_STROBE));
|
||||
|
||||
return byte;
|
||||
}
|
||||
|
||||
|
||||
unsigned char
|
||||
ffe_wait_while_busy (void)
|
||||
{
|
||||
unsigned char input;
|
||||
int n_try = 0;
|
||||
|
||||
do
|
||||
{
|
||||
input = inportb ((unsigned short) (ffe_port + PARPORT_STATUS));
|
||||
n_try++;
|
||||
}
|
||||
while (input & PARPORT_IBUSY && n_try < N_TRY_MAX);
|
||||
|
||||
#if 0
|
||||
/*
|
||||
VGS doesn't check for this, and it seems to happen quite regularly, so it
|
||||
is currently commented out
|
||||
*/
|
||||
if (n_try >= N_TRY_MAX)
|
||||
{
|
||||
fputs ("ERROR: The copier is not ready\n" // yes, "ready" :-)
|
||||
" Turn it off for a few seconds then turn it on and try again\n",
|
||||
stderr);
|
||||
exit (1);
|
||||
}
|
||||
#endif
|
||||
|
||||
// read port again to let data settle down and to delay a little bit - JohnDie
|
||||
return inportb ((unsigned short) (ffe_port + PARPORT_STATUS));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ffe_wait_for_ready (void)
|
||||
{
|
||||
unsigned char input;
|
||||
int n_try = 0;
|
||||
|
||||
do
|
||||
{
|
||||
input = inportb ((unsigned short) (ffe_port + PARPORT_STATUS));
|
||||
n_try++;
|
||||
}
|
||||
while (!(input & PARPORT_IBUSY) && n_try < N_TRY_MAX);
|
||||
|
||||
#if 0
|
||||
if (n_try >= N_TRY_MAX)
|
||||
{
|
||||
fputs ("ERROR: The copier is not ready\n"
|
||||
" Turn it off for a few seconds then turn it on and try again\n",
|
||||
stderr);
|
||||
exit (1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ffe_checkabort (int status)
|
||||
{
|
||||
if (((!ucon64.frontend) ? kbhit () : 0) && getch () == 'q')
|
||||
{
|
||||
// ffe_send_command (5, 0, 0); // VGS: when sending/receiving a SNES ROM
|
||||
puts ("\nProgram aborted");
|
||||
exit (status);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // USE_PARALLEL
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
ffe.h - General Front Far East copier routines for uCON64
|
||||
|
||||
Copyright (c) 2002 - 2004 dbjh
|
||||
|
||||
|
||||
This program 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#ifndef FFE_H
|
||||
#define FFE_H
|
||||
|
||||
/*
|
||||
0 - Low byte of 8 kB page count
|
||||
SMD: 16 kB page count
|
||||
1 - High byte of 8 kB page count
|
||||
SMD: File ID code 0 (3, not: high byte of 16 kB page count)
|
||||
Magic Griffin: Emulation mode select, first byte?
|
||||
2 - Emulation mode select (SWC/SMC/Magic Griffin, second byte?)
|
||||
Bit 7 6 5 4 3 2 1 0
|
||||
x : 1 = Run in mode 0 (JMP $8000) (higher precedence than bit 1)
|
||||
x : 0 = Last file of the ROM dump (multi-file)
|
||||
: 1 = Multi-file (there is another file to follow)
|
||||
x : SWC & SMC:
|
||||
0 = SRAM mapping mode 1 (LoROM)
|
||||
1 = mode 2 (HiROM)
|
||||
x : SWC & SMC:
|
||||
0 = DRAM mapping mode 20 (LoROM)
|
||||
1 = mode 21 (HiROM)
|
||||
x x : SWC & SMC (SRAM size):
|
||||
00 = 256 kb, 01 = 64 kb, 10 = 16 kb, 11 = no SRAM
|
||||
x : SWC & SMC:
|
||||
0 = Run in mode 3
|
||||
1 = Run in mode 2 (JMP RESET)
|
||||
x : 0 = Disable, 1 = Enable external cartridge memory
|
||||
image at bank 20-5F,A0-DF in system mode 2/3)
|
||||
3-7 - 0, reserved
|
||||
8 - File ID code 1 (0xaa)
|
||||
9 - File ID code 2 (0xbb)
|
||||
10 - File type; check this byte only if ID 1 & 2 match
|
||||
1 : Super Magic Card saver data
|
||||
2 : Magic Griffin program (PC-Engine)
|
||||
3 : Magic Griffin SRAM data
|
||||
4 : SNES program
|
||||
5 : SWC & SMC password, SRAM data
|
||||
6 : Mega Drive program
|
||||
7 : SMD SRAM data
|
||||
8 : SWC & SMC saver data
|
||||
11-511 - 0, reserved
|
||||
*/
|
||||
|
||||
#ifdef USE_PARALLEL
|
||||
|
||||
extern void ffe_init_io (unsigned int port);
|
||||
extern void ffe_deinit_io (void);
|
||||
extern void ffe_send_block (unsigned short address, unsigned char *buffer, int len);
|
||||
extern void ffe_send_block2 (unsigned short address, unsigned char *buffer, int len);
|
||||
extern void ffe_send_command0 (unsigned short address, unsigned char byte);
|
||||
extern unsigned char ffe_send_command1 (unsigned short address);
|
||||
extern void ffe_send_command (unsigned char command_code, unsigned short a, unsigned short l);
|
||||
extern void ffe_receive_block (unsigned short address, unsigned char *buffer, int len);
|
||||
extern void ffe_receive_block2 (unsigned short address, unsigned char *buffer, int len);
|
||||
extern unsigned char ffe_receiveb (void);
|
||||
extern void ffe_wait_for_ready (void);
|
||||
extern void ffe_checkabort (int status);
|
||||
|
||||
#endif // USE_PARALLEL
|
||||
|
||||
#endif // FFE_H
|
||||
@@ -1,739 +0,0 @@
|
||||
/*
|
||||
fig.c - Super PRO Fighter support for uCON64
|
||||
|
||||
Copyright (c) 1999 - 2002 NoisyB <noisyb@gmx.net>
|
||||
Copyright (c) 2001 - 2004 dbjh
|
||||
Copyright (c) 2003 - 2004 JohnDie
|
||||
|
||||
|
||||
This program 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include "misc/misc.h"
|
||||
#include "misc/itypes.h"
|
||||
#ifdef USE_ZLIB
|
||||
#include "misc/archive.h"
|
||||
#endif
|
||||
#include "misc/getopt2.h" // st_getopt2_t
|
||||
#include "misc/parallel.h"
|
||||
#include "misc/file.h"
|
||||
#include "ucon64.h"
|
||||
#include "ucon64_misc.h"
|
||||
#include "ffe.h"
|
||||
#include "fig.h"
|
||||
#include "console/snes.h" // for snes_get_snes_hirom()
|
||||
|
||||
|
||||
const st_getopt2_t fig_usage[] =
|
||||
{
|
||||
{
|
||||
NULL, 0, 0, 0,
|
||||
NULL, "Super Pro Fighter (Q/Q+)/Pro Fighter X (Turbo 2)/Double Pro Fighter (X Turbo)"
|
||||
/*"1993/1994/19XX China Coach Limited/CCL http://www.ccltw.com.tw"*/,
|
||||
NULL
|
||||
},
|
||||
#ifdef USE_PARALLEL
|
||||
{
|
||||
"xfig", 0, 0, UCON64_XFIG,
|
||||
NULL, "send/receive ROM to/from *Pro Fighter*/FIG; " OPTION_LONG_S "port=PORT\n"
|
||||
"receives automatically when ROM does not exist",
|
||||
&ucon64_wf[WF_OBJ_SNES_DEFAULT_STOP_NO_SPLIT_NO_ROM]
|
||||
},
|
||||
{
|
||||
"xfigs", 0, 0, UCON64_XFIGS,
|
||||
NULL, "send/receive SRAM to/from *Pro Fighter*/FIG; " OPTION_LONG_S "port=PORT\n"
|
||||
"receives automatically when SRAM does not exist",
|
||||
&ucon64_wf[WF_OBJ_SNES_STOP_NO_ROM]
|
||||
},
|
||||
{
|
||||
"xfigc", 0, 0, UCON64_XFIGC, NULL,
|
||||
"send/receive SRAM to/from cartridge in *Pro Fighter*/FIG;\n" OPTION_LONG_S "port=PORT\n"
|
||||
"receives automatically when SRAM does not exist",
|
||||
// "Press q to abort; ^C might cause invalid state of backup unit"
|
||||
&ucon64_wf[WF_OBJ_SNES_STOP_NO_ROM]
|
||||
},
|
||||
#endif
|
||||
{NULL, 0, 0, 0, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
#ifdef USE_PARALLEL
|
||||
|
||||
#define BUFFERSIZE 8192 // don't change, only 8192 works!
|
||||
|
||||
|
||||
static int receive_rom_info (unsigned char *buffer);
|
||||
static int get_rom_size (unsigned char *info_block);
|
||||
static int check1 (unsigned char *info_block, int index);
|
||||
static int check2 (unsigned char *info_block, int index, unsigned char value);
|
||||
static int check3 (unsigned char *info_block, int index1, int index2, int size);
|
||||
static void handle_swc_header (unsigned char *header);
|
||||
|
||||
static int hirom;
|
||||
|
||||
|
||||
#if BUFFERSIZE < 512
|
||||
#error receive_rom_info() and fig_read_sram() expect BUFFERSIZE to be at least \
|
||||
512 bytes.
|
||||
#endif
|
||||
int
|
||||
receive_rom_info (unsigned char *buffer)
|
||||
/*
|
||||
- returns size of ROM in Mb (128 kB) units
|
||||
- sets global `hirom'
|
||||
*/
|
||||
{
|
||||
int n, size;
|
||||
volatile int m;
|
||||
unsigned char byte;
|
||||
|
||||
ffe_send_command0 (0xe00c, 0);
|
||||
|
||||
if (UCON64_ISSET (ucon64.snes_hirom))
|
||||
hirom = ucon64.snes_hirom ? 1 : 0;
|
||||
else
|
||||
{
|
||||
ffe_send_command (5, 3, 0);
|
||||
byte = ffe_send_command1 (0xbfd5);
|
||||
if ((byte & 1 && byte != 0x23) || byte == 0x3a) // & 1 => 0x21, 0x31, 0x35
|
||||
hirom = 1;
|
||||
}
|
||||
|
||||
for (n = 0; n < (int) FIG_HEADER_LEN; n++)
|
||||
{
|
||||
for (m = 0; m < 65536; m++) // a delay is necessary here
|
||||
;
|
||||
ffe_send_command (5, (unsigned short) (0x200 + n), 0);
|
||||
buffer[n] = ffe_send_command1 (0xa0a0);
|
||||
}
|
||||
|
||||
size = get_rom_size (buffer);
|
||||
if (hirom)
|
||||
size <<= 1;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
get_rom_size (unsigned char *info_block)
|
||||
// returns size of ROM in Mb units
|
||||
{
|
||||
if (check1 (info_block, 0))
|
||||
return 0;
|
||||
if (check2 (info_block, 0x10, 0x84))
|
||||
return 0;
|
||||
if (check3 (info_block, 0, 0x20, 0x20))
|
||||
return 2;
|
||||
if (check3 (info_block, 0, 0x40, 0x20))
|
||||
return 4;
|
||||
if (check3 (info_block, 0x40, 0x60, 0x20))
|
||||
return 6;
|
||||
if (check3 (info_block, 0, 0x80, 0x10))
|
||||
return 8;
|
||||
if (check1 (info_block, 0x80))
|
||||
return 8;
|
||||
if (check3 (info_block, 0x80, 0x90, 0x10))
|
||||
return 8;
|
||||
if (check2 (info_block, 0x80, 0xa0))
|
||||
return 8;
|
||||
if (check3 (info_block, 0x80, 0xa0, 0x20))
|
||||
return 0xa;
|
||||
if (check1 (info_block, 0xc0))
|
||||
return 0xc;
|
||||
if (check2 (info_block, 0xc0, 0xb0))
|
||||
return 0xc;
|
||||
if (check3 (info_block, 0x80, 0xc0, 0x20))
|
||||
return 0xc;
|
||||
if (check3 (info_block, 0x100, 0, 0x10))
|
||||
return 0x10;
|
||||
if (check2 (info_block, 0x100, 0xc0))
|
||||
return 0x10;
|
||||
if (check3 (info_block, 0x100, 0x120, 0x10))
|
||||
return 0x12;
|
||||
if (check3 (info_block, 0x100, 0x140, 0x10))
|
||||
return 0x14;
|
||||
if (check2 (info_block, 0x140, 0xd0))
|
||||
return 0x14;
|
||||
if (check3 (info_block, 0x100, 0x180, 0x10))
|
||||
return 0x18;
|
||||
if (check2 (info_block, 0x180, 0xe0))
|
||||
return 0x18;
|
||||
if (check3 (info_block, 0x180, 0x1c0, 0x10))
|
||||
return 0x1c;
|
||||
if (check3 (info_block, 0x1f0, 0x1f0, 0x10))
|
||||
return 0x20;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
check1 (unsigned char *info_block, int index)
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; n < 16; n++)
|
||||
if (info_block[n + index] != info_block[index])
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
check2 (unsigned char *info_block, int index, unsigned char value)
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; n < 4; n++)
|
||||
if (info_block[n + index] != value)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
check3 (unsigned char *info_block, int index1, int index2, int size)
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; n < size; n++)
|
||||
if (info_block[n + index1] != info_block[n + index2])
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
handle_swc_header (unsigned char *header)
|
||||
{
|
||||
if ((header[2] & 0x10) == 0x10)
|
||||
{ // HiROM
|
||||
header[3] |= 0x80;
|
||||
|
||||
if ((header[2] & 0x0c) == 0x0c) // 0 Kbit SRAM
|
||||
{
|
||||
header[4] = 0x77;
|
||||
header[5] = 0x83;
|
||||
}
|
||||
else if (((header[2] & 0x0c) == 0x08) || // 16 *or* 64 Kbit SRAM
|
||||
((header[2] & 0x0c) == 0x04))
|
||||
{
|
||||
header[4] = 0xdd;
|
||||
header[5] = 0x82;
|
||||
}
|
||||
else // 256 Kbit SRAM
|
||||
{
|
||||
header[4] = 0xdd;
|
||||
header[5] = 0x02;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // LoROM
|
||||
header[3] &= 0x7f;
|
||||
|
||||
if ((header[2] & 0x0c) == 0x0c) // 0 Kbit SRAM
|
||||
{
|
||||
header[4] = 0x77;
|
||||
header[5] = 0x83;
|
||||
}
|
||||
else if (((header[2] & 0x0c) == 0x08) || // 16 *or* 64 Kbit SRAM
|
||||
((header[2] & 0x0c) == 0x04))
|
||||
{
|
||||
header[4] = 0x00;
|
||||
header[5] = 0x80;
|
||||
}
|
||||
else // 256 Kbit SRAM
|
||||
{
|
||||
header[4] = 0x00;
|
||||
header[5] = 0x00;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
fig_read_rom (const char *filename, unsigned int parport)
|
||||
{
|
||||
FILE *file;
|
||||
unsigned char *buffer;
|
||||
int n, size, blocksleft, bytesreceived = 0;
|
||||
unsigned short address1, address2;
|
||||
time_t starttime;
|
||||
st_rominfo_t rominfo;
|
||||
|
||||
ffe_init_io (parport);
|
||||
|
||||
if ((file = fopen (filename, "wb")) == NULL)
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], filename);
|
||||
exit (1);
|
||||
}
|
||||
if ((buffer = (unsigned char *) malloc (BUFFERSIZE)) == NULL)
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[FILE_BUFFER_ERROR], BUFFERSIZE);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
size = receive_rom_info (buffer);
|
||||
if (size == 0)
|
||||
{
|
||||
fprintf (stderr, "ERROR: There is no cartridge present in the Pro Fighter\n");
|
||||
fclose (file);
|
||||
remove (filename);
|
||||
exit (1);
|
||||
}
|
||||
blocksleft = size * 16; // 1 Mb (128 kB) unit == 16 8 kB units
|
||||
printf ("Receive: %d Bytes (%.4f Mb)\n", size * MBIT, (float) size);
|
||||
size *= MBIT; // size in bytes for ucon64_gauge() below
|
||||
|
||||
ffe_send_command (5, 0, 0);
|
||||
ffe_send_command0 (0xe00c, 0);
|
||||
ffe_send_command0 (0xe003, 0);
|
||||
// byte = ffe_send_command1 (0xbfd8);
|
||||
|
||||
memset (buffer, 0, FIG_HEADER_LEN);
|
||||
fwrite (buffer, 1, FIG_HEADER_LEN, file); // write temporary empty header
|
||||
|
||||
if (hirom)
|
||||
blocksleft >>= 1;
|
||||
|
||||
printf ("Press q to abort\n\n"); // print here, NOT before first FIG I/O,
|
||||
// because if we get here q works ;-)
|
||||
address1 = 0x300; // address1 = 0x100, address2 = 0 should
|
||||
address2 = 0x200; // also work
|
||||
starttime = time (NULL);
|
||||
while (blocksleft > 0)
|
||||
{
|
||||
if (hirom)
|
||||
for (n = 0; n < 4; n++)
|
||||
{
|
||||
ffe_send_command (5, address1, 0);
|
||||
ffe_receive_block (0x2000, buffer, BUFFERSIZE);
|
||||
address1++;
|
||||
fwrite (buffer, 1, BUFFERSIZE, file);
|
||||
|
||||
bytesreceived += BUFFERSIZE;
|
||||
ucon64_gauge (starttime, bytesreceived, size);
|
||||
ffe_checkabort (2);
|
||||
}
|
||||
|
||||
for (n = 0; n < 4; n++)
|
||||
{
|
||||
ffe_send_command (5, address2, 0);
|
||||
ffe_receive_block (0xa000, buffer, BUFFERSIZE);
|
||||
blocksleft--;
|
||||
address2++;
|
||||
fwrite (buffer, 1, BUFFERSIZE, file);
|
||||
|
||||
bytesreceived += BUFFERSIZE;
|
||||
ucon64_gauge (starttime, bytesreceived, size);
|
||||
ffe_checkabort (2);
|
||||
}
|
||||
}
|
||||
ffe_send_command (5, 0, 0);
|
||||
|
||||
// Create a correct header. We can't obtain the header from the Pro Fighter
|
||||
// unless a (the same) cartridge was just dumped to diskette...
|
||||
ucon64.rom = filename;
|
||||
ucon64.file_size = size + FIG_HEADER_LEN;
|
||||
// override everything we know for sure
|
||||
ucon64.console = UCON64_SNES;
|
||||
ucon64.buheader_len = FIG_HEADER_LEN;
|
||||
ucon64.split = 0;
|
||||
ucon64.snes_hirom = hirom ? SNES_HIROM : 0;
|
||||
ucon64.interleaved = 0;
|
||||
memset (&rominfo, 0, sizeof (st_rominfo_t));
|
||||
|
||||
fflush (file);
|
||||
snes_init (&rominfo);
|
||||
memset (buffer, 0, FIG_HEADER_LEN);
|
||||
snes_set_fig_header (&rominfo, (st_fig_header_t *) buffer);
|
||||
fseek (file, 0, SEEK_SET);
|
||||
fwrite (buffer, 1, FIG_HEADER_LEN, file); // write correct header
|
||||
|
||||
free (buffer);
|
||||
fclose (file);
|
||||
ffe_deinit_io ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
fig_write_rom (const char *filename, unsigned int parport)
|
||||
{
|
||||
FILE *file;
|
||||
unsigned char *buffer;
|
||||
int bytesread = 0, bytessend, totalblocks, blocksdone = 0, blocksleft, fsize,
|
||||
n, emu_mode_select;
|
||||
unsigned short address1, address2;
|
||||
time_t starttime;
|
||||
|
||||
ffe_init_io (parport);
|
||||
|
||||
if ((file = fopen (filename, "rb")) == NULL)
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], filename);
|
||||
exit (1);
|
||||
}
|
||||
if ((buffer = (unsigned char *) malloc (BUFFERSIZE)) == NULL)
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[FILE_BUFFER_ERROR], BUFFERSIZE);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
fsize = fsizeof (filename);
|
||||
printf ("Send: %d Bytes (%.4f Mb)\n", fsize, (float) fsize / MBIT);
|
||||
|
||||
ffe_send_command0 (0xc008, 0);
|
||||
fread (buffer, 1, FIG_HEADER_LEN, file);
|
||||
|
||||
if (snes_get_file_type () == SWC)
|
||||
handle_swc_header (buffer);
|
||||
emu_mode_select = buffer[2]; // this byte is needed later
|
||||
|
||||
ffe_send_command (5, 0, 0);
|
||||
ffe_send_block (0x400, buffer, FIG_HEADER_LEN); // send header
|
||||
bytessend = FIG_HEADER_LEN;
|
||||
|
||||
hirom = snes_get_snes_hirom ();
|
||||
if (hirom)
|
||||
ffe_send_command0 (0xe00f, 0); // seems to enable HiROM mode,
|
||||
// value doesn't seem to matter
|
||||
printf ("Press q to abort\n\n"); // print here, NOT before first FIG I/O,
|
||||
// because if we get here q works ;-)
|
||||
totalblocks = (fsize - FIG_HEADER_LEN + BUFFERSIZE - 1) / BUFFERSIZE; // round up
|
||||
blocksleft = totalblocks;
|
||||
address1 = 0x300;
|
||||
address2 = 0x200;
|
||||
starttime = time (NULL);
|
||||
while (blocksleft > 0)
|
||||
{
|
||||
if (hirom)
|
||||
for (n = 0; n < 4; n++)
|
||||
{
|
||||
bytesread = fread (buffer, 1, BUFFERSIZE, file);
|
||||
ffe_send_command0 ((unsigned short) 0xc010, (unsigned char) (blocksdone >> 9));
|
||||
ffe_send_command (5, address1, 0);
|
||||
ffe_send_block (0x0000, buffer, bytesread);
|
||||
address1++;
|
||||
blocksleft--;
|
||||
blocksdone++;
|
||||
|
||||
bytessend += bytesread;
|
||||
ucon64_gauge (starttime, bytessend, fsize);
|
||||
ffe_checkabort (2);
|
||||
}
|
||||
|
||||
for (n = 0; n < 4; n++)
|
||||
{
|
||||
bytesread = fread (buffer, 1, BUFFERSIZE, file);
|
||||
ffe_send_command0 ((unsigned short) 0xc010, (unsigned char) (blocksdone >> 9));
|
||||
ffe_send_command (5, address2, 0);
|
||||
ffe_send_block (0x8000, buffer, bytesread);
|
||||
address2++;
|
||||
blocksleft--;
|
||||
blocksdone++;
|
||||
|
||||
bytessend += bytesread;
|
||||
ucon64_gauge (starttime, bytessend, fsize);
|
||||
ffe_checkabort (2);
|
||||
}
|
||||
}
|
||||
|
||||
if (blocksdone > 0x200) // ROM dump > 512 8 kB blocks (=32 Mb (=4 MB))
|
||||
ffe_send_command0 (0xc010, 2);
|
||||
|
||||
ffe_send_command (5, 0, 0);
|
||||
ffe_send_command (6, (unsigned short) (1 | (emu_mode_select << 8)), 0);
|
||||
|
||||
ffe_wait_for_ready ();
|
||||
outportb ((unsigned short) (parport + PARPORT_DATA), 0);
|
||||
outportb ((unsigned short) (parport + PARPORT_CONTROL),
|
||||
(unsigned char) (inportb ((unsigned short) // invert strobe
|
||||
(parport + PARPORT_CONTROL)) ^ PARPORT_STROBE));
|
||||
|
||||
free (buffer);
|
||||
fclose (file);
|
||||
ffe_deinit_io ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
fig_read_sram (const char *filename, unsigned int parport)
|
||||
{
|
||||
FILE *file;
|
||||
unsigned char *buffer;
|
||||
int blocksleft, bytesreceived = 0;
|
||||
unsigned short address;
|
||||
time_t starttime;
|
||||
|
||||
ffe_init_io (parport);
|
||||
|
||||
if ((file = fopen (filename, "wb")) == NULL)
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], filename);
|
||||
exit (1);
|
||||
}
|
||||
if ((buffer = (unsigned char *) malloc (BUFFERSIZE)) == NULL)
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[FILE_BUFFER_ERROR], BUFFERSIZE);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
printf ("Receive: %d Bytes\n", 32 * 1024);
|
||||
memset (buffer, 0, FIG_HEADER_LEN);
|
||||
#if 0 // Not needed for FIG, as size is always 4 blocks
|
||||
buffer[0] = 4; // 32 kB == 4*8 kB, "size_high" is already 0
|
||||
#endif
|
||||
fwrite (buffer, 1, FIG_HEADER_LEN, file);
|
||||
|
||||
ffe_send_command (5, 0, 0);
|
||||
ffe_send_command0 (0xe00d, 0);
|
||||
ffe_send_command0 (0xc008, 0);
|
||||
|
||||
printf ("Press q to abort\n\n"); // print here, NOT before first FIG I/O,
|
||||
// because if we get here q works ;-)
|
||||
blocksleft = 4; // SRAM is 4*8 kB
|
||||
address = 0x100;
|
||||
starttime = time (NULL);
|
||||
while (blocksleft > 0)
|
||||
{
|
||||
ffe_send_command (5, address, 0);
|
||||
ffe_receive_block (0x2000, buffer, BUFFERSIZE);
|
||||
blocksleft--;
|
||||
address++;
|
||||
fwrite (buffer, 1, BUFFERSIZE, file);
|
||||
|
||||
bytesreceived += BUFFERSIZE;
|
||||
ucon64_gauge (starttime, bytesreceived, 32 * 1024);
|
||||
ffe_checkabort (2);
|
||||
}
|
||||
|
||||
free (buffer);
|
||||
fclose (file);
|
||||
ffe_deinit_io ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
fig_write_sram (const char *filename, unsigned int parport)
|
||||
{
|
||||
FILE *file;
|
||||
unsigned char *buffer;
|
||||
int bytesread, bytessend = 0, size;
|
||||
unsigned short address;
|
||||
time_t starttime;
|
||||
|
||||
ffe_init_io (parport);
|
||||
|
||||
if ((file = fopen (filename, "rb")) == NULL)
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], filename);
|
||||
exit (1);
|
||||
}
|
||||
if ((buffer = (unsigned char *) malloc (BUFFERSIZE)) == NULL)
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[FILE_BUFFER_ERROR], BUFFERSIZE);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
size = fsizeof (filename) - FIG_HEADER_LEN; // FIG SRAM is 4*8 kB, emu SRAM often not
|
||||
printf ("Send: %d Bytes\n", size);
|
||||
fseek (file, FIG_HEADER_LEN, SEEK_SET); // skip the header
|
||||
|
||||
ffe_send_command (5, 0, 0);
|
||||
ffe_send_command0 (0xe00d, 0);
|
||||
ffe_send_command0 (0xc008, 0);
|
||||
|
||||
printf ("Press q to abort\n\n"); // print here, NOT before first FIG I/O,
|
||||
// because if we get here q works ;-)
|
||||
address = 0x100;
|
||||
starttime = time (NULL);
|
||||
while ((bytesread = fread (buffer, 1, BUFFERSIZE, file)))
|
||||
{
|
||||
ffe_send_command (5, address, 0);
|
||||
ffe_send_block (0x2000, buffer, bytesread);
|
||||
address++;
|
||||
|
||||
bytessend += bytesread;
|
||||
ucon64_gauge (starttime, bytessend, size);
|
||||
ffe_checkabort (2);
|
||||
}
|
||||
|
||||
free (buffer);
|
||||
fclose (file);
|
||||
ffe_deinit_io ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
fig_read_cart_sram (const char *filename, unsigned int parport)
|
||||
{
|
||||
FILE *file;
|
||||
unsigned char *buffer, byte;
|
||||
int bytesreceived = 0, size;
|
||||
unsigned short address;
|
||||
time_t starttime;
|
||||
|
||||
ffe_init_io (parport);
|
||||
|
||||
if ((file = fopen (filename, "wb")) == NULL)
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], filename);
|
||||
exit (1);
|
||||
}
|
||||
if ((buffer = (unsigned char *) malloc (BUFFERSIZE)) == NULL)
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[FILE_BUFFER_ERROR], BUFFERSIZE);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
size = receive_rom_info (buffer);
|
||||
if (size == 0)
|
||||
{
|
||||
fprintf (stderr, "ERROR: There is no cartridge present in the Pro Fighter\n");
|
||||
fclose (file);
|
||||
remove (filename);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
ffe_send_command (5, 3, 0); // detect cartridge SRAM size because
|
||||
ffe_send_command0 (0xe00c, 0); // we don't want to read too few data
|
||||
byte = ffe_send_command1 (0xbfd8);
|
||||
|
||||
size = MAX ((byte ? 1 << (byte + 10) : 0), 32 * 1024);
|
||||
printf ("Receive: %d Bytes\n", size);
|
||||
|
||||
memset (buffer, 0, FIG_HEADER_LEN);
|
||||
#if 0 // Not needed for FIG, as size is always 4 blocks
|
||||
buffer[0] = 4; // 32 kB == 4*8 kB, "size_high" is already 0
|
||||
#endif
|
||||
fwrite (buffer, 1, FIG_HEADER_LEN, file);
|
||||
|
||||
ffe_send_command (5, 0, 0);
|
||||
ffe_send_command0 (0xe00c, 0);
|
||||
// ffe_send_command0 (0xc008, 0);
|
||||
|
||||
printf ("Press q to abort\n\n"); // print here, NOT before first FIG I/O,
|
||||
// because if we get here q works ;-)
|
||||
address = hirom ? 0x2c3 : 0x1c0;
|
||||
|
||||
starttime = time (NULL);
|
||||
while (bytesreceived < size)
|
||||
{
|
||||
ffe_send_command (5, address, 0);
|
||||
ffe_receive_block ((unsigned short) (hirom ? 0x6000 : 0x2000), buffer, BUFFERSIZE);
|
||||
fwrite (buffer, 1, BUFFERSIZE, file);
|
||||
address += hirom ? 4 : 1;
|
||||
|
||||
bytesreceived += BUFFERSIZE;
|
||||
ucon64_gauge (starttime, bytesreceived, size);
|
||||
ffe_checkabort (2);
|
||||
}
|
||||
|
||||
free (buffer);
|
||||
fclose (file);
|
||||
ffe_deinit_io ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
fig_write_cart_sram (const char *filename, unsigned int parport)
|
||||
{
|
||||
FILE *file;
|
||||
unsigned char *buffer, byte;
|
||||
int bytesread, bytessend = 0, size;
|
||||
unsigned short address;
|
||||
time_t starttime;
|
||||
|
||||
ffe_init_io (parport);
|
||||
|
||||
if ((file = fopen (filename, "rb")) == NULL)
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], filename);
|
||||
exit (1);
|
||||
}
|
||||
if ((buffer = (unsigned char *) malloc (BUFFERSIZE)) == NULL)
|
||||
{
|
||||
fprintf (stderr, ucon64_msg[FILE_BUFFER_ERROR], BUFFERSIZE);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
size = receive_rom_info (buffer);
|
||||
if (size == 0)
|
||||
{
|
||||
fprintf (stderr, "ERROR: There is no cartridge present in the Pro Fighter\n");
|
||||
fclose (file);
|
||||
remove (filename);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
ffe_send_command (5, 3, 0); // detect cartridge SRAM size because we don't
|
||||
ffe_send_command0 (0xe00c, 0); // want to write more data than necessary
|
||||
byte = ffe_send_command1 (0xbfd8);
|
||||
|
||||
size = fsizeof (filename) - FIG_HEADER_LEN; // FIG SRAM is 4*8 kB, emu SRAM often not
|
||||
size = MIN ((byte ? 1 << (byte + 10) : 0), size);
|
||||
|
||||
printf ("Send: %d Bytes\n", size);
|
||||
fseek (file, FIG_HEADER_LEN, SEEK_SET); // skip the header
|
||||
|
||||
ffe_send_command (5, 0, 0);
|
||||
ffe_send_command0 (0xe00c, 0);
|
||||
// ffe_send_command0 (0xc008, 0);
|
||||
|
||||
printf ("Press q to abort\n\n"); // print here, NOT before first FIG I/O,
|
||||
// because if we get here q works ;-)
|
||||
address = hirom ? 0x2c3 : 0x1c0;
|
||||
|
||||
starttime = time (NULL);
|
||||
while ((bytessend < size) && (bytesread = fread (buffer, 1, MIN (size, BUFFERSIZE), file)))
|
||||
{
|
||||
ffe_send_command (5, address, 0);
|
||||
ffe_send_block ((unsigned short) (hirom ? 0x6000 : 0x2000), buffer, bytesread);
|
||||
address += hirom ? 4 : 1;
|
||||
|
||||
bytessend += bytesread;
|
||||
ucon64_gauge (starttime, bytessend, size);
|
||||
ffe_checkabort (2);
|
||||
}
|
||||
|
||||
free (buffer);
|
||||
fclose (file);
|
||||
ffe_deinit_io ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // USE_PARALLEL
|
||||
@@ -1,100 +0,0 @@
|
||||
/*
|
||||
fig.h - Super PRO Fighter support for uCON64
|
||||
|
||||
Copyright (c) 1999 - 2002 NoisyB <noisyb@gmx.net>
|
||||
Copyright (c) 2001 - 2003 dbjh
|
||||
Copyright (c) 2003 JohnDie
|
||||
|
||||
|
||||
This program 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#ifndef FIG_H
|
||||
#define FIG_H
|
||||
|
||||
extern const st_getopt2_t fig_usage[];
|
||||
|
||||
#ifdef USE_PARALLEL
|
||||
#endif // USE_PARALLEL
|
||||
|
||||
/*
|
||||
Super Pro Fighter (FIG) Header Format
|
||||
Last edited: 19.06.2002
|
||||
|
||||
Offset | Content
|
||||
-------------+------------------------------------
|
||||
$0000 | Lo-Byte of 8K-Block#
|
||||
-------------+------------------------------------
|
||||
$0001 | Hi-Byte of 8K-Block#
|
||||
-------------+------------------------------------
|
||||
$0002 | $00 = Last File
|
||||
| $40 = More Files Present
|
||||
-------------+------------------------------------
|
||||
$0003 | $00 = LoROM
|
||||
| $80 = HiROM
|
||||
-------------+------------------------------------
|
||||
$0004-$0005 | $77 $83 = No SRAM (LoROM)
|
||||
| $00 $80 = 16 KBit (LoROM)
|
||||
| $00 $80 = 64 KBit (LoROM)
|
||||
| $00 $00 = 256 KBit (LoROM)
|
||||
| $47 $83 = No SRAM (LoROM) (DSP)
|
||||
| $11 $02 = 256 KBit (LoROM) (SFX)
|
||||
| $77 $83 = No SRAM (HiROM)
|
||||
| $DD $82 = 16 KBit (HiROM)
|
||||
| $DD $82 = 64 KBit (HiROM)
|
||||
| $DD $02 = 256 KBit (HiROM)
|
||||
| $F7 $83 = No SRAM (HiROM) (DSP)
|
||||
| $FD $82 = 16 KBit (HiROM) (DSP)
|
||||
-------------+------------------------------------
|
||||
$0006-$01FF | Reserved (=$00)
|
||||
|
||||
|
||||
|
||||
NOTE 1: The Super Pro Fighter does not distinguish between 16 KBit SRAM
|
||||
and 64 KBit SRAM.
|
||||
|
||||
NOTE 2: When splitting files, the SPF writes all relevant header fields
|
||||
to all files. So each file has the same header with exception of
|
||||
the last one, because it has $0002 set to $00 to indicate that it
|
||||
is the last file.
|
||||
*/
|
||||
typedef struct st_fig_header
|
||||
{
|
||||
/*
|
||||
Don't create fields that are larger than one byte! For example size_low and size_high
|
||||
could be combined in one unsigned short int. However, this gives problems with little
|
||||
endian vs. big endian machines (e.g. writing the header to disk).
|
||||
*/
|
||||
unsigned char size_low;
|
||||
unsigned char size_high;
|
||||
unsigned char multi;
|
||||
unsigned char hirom;
|
||||
unsigned char emulation1;
|
||||
unsigned char emulation2;
|
||||
unsigned char pad[506];
|
||||
} st_fig_header_t;
|
||||
|
||||
#define FIG_HEADER_START 0
|
||||
#define FIG_HEADER_LEN (sizeof (st_fig_header_t))
|
||||
|
||||
#ifdef USE_PARALLEL
|
||||
extern int fig_read_rom (const char *filename, unsigned int parport);
|
||||
extern int fig_write_rom (const char *filename, unsigned int parport);
|
||||
extern int fig_read_sram (const char *filename, unsigned int parport);
|
||||
extern int fig_write_sram (const char *filename, unsigned int parport);
|
||||
extern int fig_read_cart_sram (const char *filename, unsigned int parport);
|
||||
extern int fig_write_cart_sram (const char *filename, unsigned int parport);
|
||||
#endif
|
||||
|
||||
#endif // FIG_H
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
gbx.h - Game Boy Xchanger support for uCON64
|
||||
|
||||
Copyright (c) 1999 - 2001 NoisyB <noisyb@gmx.net>
|
||||
Copyright (c) 2001 - 2002 dbjh
|
||||
|
||||
|
||||
This program 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#ifndef GBX_H
|
||||
#define GBX_H
|
||||
|
||||
extern const st_getopt2_t gbx_usage[];
|
||||
|
||||
#ifdef USE_PARALLEL
|
||||
extern int gbx_read_rom (const char *filename, unsigned int parport);
|
||||
extern int gbx_write_rom (const char *filename, unsigned int parport);
|
||||
extern int gbx_read_sram (const char *filename, unsigned int parport, int bank);
|
||||
extern int gbx_write_sram (const char *filename, unsigned int parport, int bank);
|
||||
#endif
|
||||
|
||||
#endif // GBX_H
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
gd.h - Game Doctor support for uCON64
|
||||
|
||||
Copyright (c) 2002 John Weidman
|
||||
Copyright (c) 2002 dbjh
|
||||
|
||||
|
||||
This program 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#ifndef GD_H
|
||||
#define GD_H
|
||||
|
||||
extern const st_getopt2_t gd_usage[];
|
||||
|
||||
#define GD_HEADER_START 0
|
||||
#define GD_HEADER_LEN 512
|
||||
#define GD3_MAX_UNITS 16 // Maximum that the hardware supports
|
||||
// Each logical memory unit is 8 Mbit in size (internally it's 2*4 Mbit)
|
||||
|
||||
#ifdef USE_PARALLEL
|
||||
extern int gd3_read_rom (const char *filename, unsigned int parport);
|
||||
extern int gd3_write_rom (const char *filename, unsigned int parport,
|
||||
st_rominfo_t *rominfo);
|
||||
extern int gd6_read_rom (const char *filename, unsigned int parport);
|
||||
extern int gd6_write_rom (const char *filename, unsigned int parport,
|
||||
st_rominfo_t *rominfo);
|
||||
extern int gd3_read_sram (const char *filename, unsigned int parport);
|
||||
extern int gd3_write_sram (const char *filename, unsigned int parport);
|
||||
extern int gd6_read_sram (const char *filename, unsigned int parport);
|
||||
extern int gd6_write_sram (const char *filename, unsigned int parport);
|
||||
extern int gd3_read_saver (const char *filename, unsigned int parport);
|
||||
extern int gd3_write_saver (const char *filename, unsigned int parport);
|
||||
extern int gd6_read_saver (const char *filename, unsigned int parport);
|
||||
extern int gd6_write_saver (const char *filename, unsigned int parport);
|
||||
#endif // USE_PARALLEL
|
||||
|
||||
#endif // GD_H
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
interceptor.c - Mega Disk/Super Disk Interceptor support for uCON64
|
||||
|
||||
Copyright (c) 1999 - 2001 NoisyB <noisyb@gmx.net>
|
||||
|
||||
|
||||
This program 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include "misc/misc.h"
|
||||
#include "misc/itypes.h"
|
||||
#ifdef USE_ZLIB
|
||||
#include "misc/archive.h"
|
||||
#endif
|
||||
#include "misc/getopt2.h" // st_getopt2_t
|
||||
#include "ucon64.h"
|
||||
#include "interceptor.h"
|
||||
|
||||
|
||||
const st_getopt2_t interceptor_usage[] =
|
||||
{
|
||||
{
|
||||
NULL, 0, 0, 0,
|
||||
NULL, "Mega Disk/Super Disk (Interceptor),"/*"19XX Taiwan Sang Ting Co. Ltd."*/,
|
||||
NULL
|
||||
},
|
||||
{NULL, 0, 0, 0, NULL, NULL, NULL}
|
||||
};
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
interceptor.h - Mega Disk/Super Disk Interceptor support for uCON64
|
||||
|
||||
Copyright (c) 1999 - 2001 NoisyB <noisyb@gmx.net>
|
||||
|
||||
|
||||
This program 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#ifndef INTERCEPTOR_H
|
||||
#define INTERCEPTOR_H
|
||||
|
||||
extern const st_getopt2_t interceptor_usage[];
|
||||
|
||||
typedef struct st_interceptor_header
|
||||
{
|
||||
char pad[512];
|
||||
} st_interceptor_header_t;
|
||||
|
||||
#endif
|
||||
@@ -1,169 +0,0 @@
|
||||
CC=gcc
|
||||
|
||||
ifdef DEBUG
|
||||
# I think we only use gnu99 instead of c99 due to va_args extensions.
|
||||
CFLAGS=-I. -Wall -W -pg -g -pedantic -ansi -DDEBUG
|
||||
else
|
||||
CFLAGS=-I. -Wall -W -O6 -funroll-loops -fexpensive-optimizations
|
||||
endif
|
||||
|
||||
ifndef DJGPP
|
||||
# uname is not available by default under DOS
|
||||
OSTYPE=$(shell uname -s)
|
||||
else
|
||||
OSTYPE=DJGPP
|
||||
endif
|
||||
|
||||
GCC_WIN=0
|
||||
ifeq ($(findstring MINGW,$(OSTYPE)),MINGW)
|
||||
GCC_WIN=1
|
||||
endif
|
||||
ifeq ($(findstring CYGWIN,$(OSTYPE)),CYGWIN)
|
||||
GCC_WIN=1
|
||||
endif
|
||||
|
||||
ifdef DJGPP
|
||||
LDFLAGS=
|
||||
else
|
||||
ifeq ($(findstring BeOS,$(OSTYPE)),BeOS)
|
||||
LDFLAGS=-nostart
|
||||
else # Unix or Win GCC
|
||||
LDFLAGS=-shared
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(findstring DJGPP,$(OSTYPE)),)
|
||||
ifneq ($(GCC_WIN),1)
|
||||
CFLAGS+=-fPIC
|
||||
else
|
||||
# Cygwin and MinGW need an import library for a DLL
|
||||
LDFLAGS+=-Wl,--out-implib,libcd64dll.a
|
||||
endif
|
||||
endif
|
||||
|
||||
# The next check is not really specific to FreeBSD or OpenBSD -- the version of
|
||||
# gcc I use is just old.
|
||||
ifeq ($(findstring FreeBSD,$(OSTYPE)),)
|
||||
ifeq ($(findstring OpenBSD,$(OSTYPE)),)
|
||||
CFLAGS+=-std=gnu99
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
DEFAULT_BUILD=1
|
||||
|
||||
# If the user passed anything, we are not a default build.
|
||||
|
||||
ifdef LIBIEEE1284
|
||||
DEFAULT_BUILD=0
|
||||
else
|
||||
ifdef PPDEV
|
||||
DEFAULT_BUILD=0
|
||||
else
|
||||
ifdef PORTDEV
|
||||
DEFAULT_BUILD=0
|
||||
else
|
||||
ifdef RAWIO
|
||||
DEFAULT_BUILD=0
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(DEFAULT_BUILD),1)
|
||||
# Put default build options for each OS here
|
||||
|
||||
ifeq ($(findstring DJGPP,$(OSTYPE)),DJGPP)
|
||||
RAWIO=1
|
||||
endif
|
||||
|
||||
ifeq ($(findstring MINGW,$(OSTYPE)),MINGW)
|
||||
RAWIO=1
|
||||
endif
|
||||
|
||||
ifeq ($(findstring CYGWIN,$(OSTYPE)),CYGWIN)
|
||||
RAWIO=1
|
||||
endif
|
||||
|
||||
ifeq ($(findstring BeOS,$(OSTYPE)),BeOS)
|
||||
RAWIO=1
|
||||
endif
|
||||
|
||||
ifeq ($(findstring OpenBSD,$(OSTYPE)),OpenBSD)
|
||||
# i386_iopl() is located in libi386.a (note the .a)
|
||||
LIBS+=-L/usr/lib -li386
|
||||
RAWIO=1
|
||||
endif
|
||||
|
||||
ifeq ($(findstring FreeBSD,$(OSTYPE)),FreeBSD)
|
||||
RAWIO=1
|
||||
endif
|
||||
|
||||
ifeq ($(findstring Linux,$(OSTYPE)),Linux)
|
||||
ifeq ($(shell if test -r /usr/include/ieee1284.h; then echo 1; else echo 0; fi),1)
|
||||
LIBIEEE1284=1
|
||||
endif
|
||||
ifeq ($(shell if test -r /usr/include/linux/ppdev.h; then echo 1; else echo 0; fi),1)
|
||||
PPDEV=1
|
||||
endif
|
||||
PORTDEV=1
|
||||
RAWIO=1
|
||||
endif
|
||||
|
||||
endif # DEFAULT_BUILD = 1
|
||||
|
||||
# Now for backend-specific defs
|
||||
|
||||
ifdef LIBIEEE1284
|
||||
CFLAGS+=-DCD64_USE_LIBIEEE1284
|
||||
LIBS+=-lieee1284
|
||||
endif
|
||||
|
||||
ifdef PPDEV
|
||||
CFLAGS+=-DCD64_USE_PPDEV
|
||||
endif
|
||||
|
||||
ifdef PORTDEV
|
||||
CFLAGS+=-DCD64_USE_PORTDEV
|
||||
endif
|
||||
|
||||
ifdef RAWIO
|
||||
CFLAGS+=-DCD64_USE_RAWIO
|
||||
endif
|
||||
|
||||
default: all
|
||||
|
||||
ifeq ($(findstring DJGPP,$(OSTYPE)),DJGPP)
|
||||
all: libcd64.a
|
||||
else
|
||||
ifeq ($(GCC_WIN),1)
|
||||
all: libcd64.a cd64.dll
|
||||
else
|
||||
all: libcd64.a libcd64.so
|
||||
endif # GCC_WIN
|
||||
endif # DJGPP
|
||||
|
||||
# libcd64 stuff
|
||||
|
||||
cd64io.o: cd64io.c
|
||||
$(CC) $(CFLAGS) $^ -c -o $@
|
||||
|
||||
cd64lib.o: cd64lib.c
|
||||
$(CC) $(CFLAGS) $^ -c -o $@
|
||||
|
||||
libcd64.a: cd64lib.o cd64io.o
|
||||
ld -r $^ $(LIBS) -o $*.o
|
||||
# rm -f $@
|
||||
ar crs $@ $*.o
|
||||
|
||||
LDFLAGS+=$(LIBS)
|
||||
ifeq ($(GCC_WIN),1)
|
||||
cd64.dll: cd64lib.o cd64io.o
|
||||
else
|
||||
libcd64.so: cd64lib.o cd64io.o
|
||||
endif
|
||||
# rm -f $@
|
||||
$(CC) $^ $(LDFLAGS) -o $@
|
||||
|
||||
clean:
|
||||
rm -f *.o *.so *.dll *.a a.out
|
||||
@@ -1,62 +0,0 @@
|
||||
CC=cl.exe
|
||||
|
||||
!ifdef DEBUG
|
||||
CFLAGS=/nologo /I. /Zi /Oi /GZ /W3 /DDEBUG
|
||||
!else
|
||||
CFLAGS=/nologo /I. /W3 /O2
|
||||
!endif
|
||||
|
||||
DEFAULT_BUILD=1
|
||||
|
||||
# If the user passed anything, we are not a default build.
|
||||
|
||||
!ifdef LIBIEEE1284
|
||||
DEFAULT_BUILD=0
|
||||
!else
|
||||
!ifdef RAWIO
|
||||
DEFAULT_BUILD=0
|
||||
!endif
|
||||
!endif
|
||||
|
||||
!if $(DEFAULT_BUILD)==1
|
||||
# Put default build options here
|
||||
|
||||
RAWIO=1
|
||||
|
||||
!endif # DEFAULT_BUILD = 1
|
||||
|
||||
# Now for backend-specific defs
|
||||
|
||||
!ifdef LIBIEEE1284
|
||||
CFLAGS=$(CFLAGS) /DCD64_USE_LIBIEEE1284
|
||||
LIBS=$(LIBS) ieee1284.lib
|
||||
!endif
|
||||
|
||||
!ifdef RAWIO
|
||||
CFLAGS=$(CFLAGS) /DCD64_USE_RAWIO
|
||||
!endif
|
||||
|
||||
default: all
|
||||
|
||||
all: cd64.lib cd64.dll
|
||||
|
||||
# libcd64 stuff
|
||||
|
||||
cd64io.obj: cd64io.c
|
||||
$(CC) $(CFLAGS) $** /c /Fo$@
|
||||
|
||||
cd64lib.obj: cd64lib.c
|
||||
$(CC) $(CFLAGS) $** /c /Fo$@
|
||||
|
||||
cd64.lib: cd64lib.obj cd64io.obj
|
||||
lib.exe /NOLOGO $** $(LIBS) /OUT:$@
|
||||
|
||||
cd64.dll: cd64lib.obj cd64io.obj
|
||||
link.exe /NOLOGO /DLL $** $(LIBS) /DEF:cd64.def /IMPLIB:cd64dll.lib /OUT:$@
|
||||
|
||||
clean:
|
||||
del *.obj
|
||||
del *.exp
|
||||
del *.lib
|
||||
del *.dll
|
||||
del *.pdb
|
||||
@@ -1,28 +0,0 @@
|
||||
EXPORTS
|
||||
cd64_create
|
||||
cd64_send_byte
|
||||
cd64_send_dword
|
||||
cd64_grab_byte
|
||||
cd64_grab_dword
|
||||
cd64_trade_bytes
|
||||
cd64_bios_grab
|
||||
cd64_bios_send
|
||||
cd64_ghemor_grab
|
||||
cd64_ghemor_send
|
||||
cd64_upload_dram
|
||||
cd64_upload_ram
|
||||
cd64_upload_bootemu
|
||||
cd64_upload_sram
|
||||
cd64_upload_flashram
|
||||
cd64_upload_eeprom
|
||||
cd64_upload_mempak
|
||||
cd64_download_cart
|
||||
cd64_download_dram
|
||||
;cd64_download_ram
|
||||
cd64_download_sram
|
||||
cd64_download_flashram
|
||||
cd64_download_eeprom
|
||||
cd64_download_mempak
|
||||
cd64_run_dram
|
||||
cd64_run_cart
|
||||
cd64_download_header
|
||||
@@ -1,114 +0,0 @@
|
||||
#ifndef __CD64IO_H__
|
||||
#define __CD64IO_H__
|
||||
|
||||
#ifdef CD64_USE_LIBIEEE1284
|
||||
#include <ieee1284.h>
|
||||
int cd64_open_ieee1284(struct cd64_t *cd64);
|
||||
int cd64_close_ieee1284(struct cd64_t *cd64);
|
||||
int cd64_xfer_ieee1284(struct cd64_t *cd64, uint8_t *wr, uint8_t *rd, int delayms);
|
||||
#endif
|
||||
|
||||
#ifdef CD64_USE_PPDEV
|
||||
#ifndef __linux__
|
||||
#error ppdev can only be used on Linux
|
||||
#endif
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/parport.h>
|
||||
#include <linux/ppdev.h>
|
||||
int cd64_open_ppdev(struct cd64_t *cd64);
|
||||
int cd64_close_ppdev(struct cd64_t *cd64);
|
||||
int cd64_xfer_ppdev(struct cd64_t *cd64, uint8_t *wr, uint8_t *rd, int delayms);
|
||||
#endif
|
||||
|
||||
#ifdef CD64_USE_PORTDEV
|
||||
#ifndef __linux__
|
||||
#error portdev can only be used on Linux
|
||||
#endif
|
||||
int cd64_open_portdev(struct cd64_t *cd64);
|
||||
int cd64_close_portdev(struct cd64_t *cd64);
|
||||
int cd64_xfer_portdev(struct cd64_t *cd64, uint8_t *wr, uint8_t *rd, int delayms);
|
||||
#endif
|
||||
|
||||
#ifdef CD64_USE_RAWIO
|
||||
/* #define REALLY_SLOW_IO */
|
||||
#if defined __linux__ && (defined __i386__ || defined __x86_64__)
|
||||
#include <sys/io.h>
|
||||
#endif
|
||||
#ifdef __OpenBSD__
|
||||
#include <sys/types.h>
|
||||
#include <machine/sysarch.h>
|
||||
#include <i386/pio.h>
|
||||
/* pio.h defines several I/O functions & macros, including the macros inb() and
|
||||
* outb(). This shows that using a bit of inline assembly is not such a bad idea
|
||||
* at all. */
|
||||
#undef inb
|
||||
#define inb(port) __inb(port)
|
||||
#undef outb
|
||||
#define outb(data, port) __outb(port, data)
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
#include <fcntl.h>
|
||||
#include <machine/cpufunc.h>
|
||||
/* Almost the same story as under OpenBSD. cpufunc.h defines the macros inb()
|
||||
* and outb(). We redefine them. Be sure _POSIX_SOURCE is not defined before
|
||||
* including <machine/cpufunc.h>. */
|
||||
#undef inb
|
||||
#define inb(port) inbv(port)
|
||||
#undef outb
|
||||
#define outb(data, port) outbv(port, data)
|
||||
#endif
|
||||
#ifdef __BEOS__
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#ifdef _MSC_VER
|
||||
#include <conio.h> /* inp() & outp() */
|
||||
#include <io.h> /* access() */
|
||||
#define F_OK 0
|
||||
#endif
|
||||
#ifdef __MSDOS__
|
||||
#include <pc.h> /* inportb() & outportb() */
|
||||
#endif
|
||||
#if defined _WIN32 || defined __CYGWIN__
|
||||
#include <windows.h> /* defines _WIN32 (checks for */
|
||||
#include <string.h> /* __CYGWIN__ must come first) */
|
||||
#ifdef __CYGWIN__
|
||||
#include <exceptions.h>
|
||||
#include <dlfcn.h>
|
||||
#include <sys/cygwin.h>
|
||||
#endif
|
||||
#endif /* _WIN32 || __CYGWIN__ */
|
||||
|
||||
int cd64_open_rawio(struct cd64_t *cd64);
|
||||
int cd64_close_rawio(struct cd64_t *cd64);
|
||||
int cd64_xfer_rawio(struct cd64_t *cd64, uint8_t *wr, uint8_t *rd, int delayms);
|
||||
#endif
|
||||
|
||||
#if defined _WIN32 && !defined __CYGWIN__
|
||||
/* milliseconds */
|
||||
#include <windows.h>
|
||||
#define USLEEP(x) Sleep(x)
|
||||
#elif defined __MSDOS__
|
||||
/* milliseconds */
|
||||
#include <dos.h>
|
||||
#define USLEEP(x) delay(x)
|
||||
#elif defined __BEOS__
|
||||
/* microseconds */
|
||||
#include <OS.h>
|
||||
#define USLEEP(x) snooze(x)
|
||||
#else /* Unix & Cygwin */
|
||||
/* microseconds */
|
||||
#include <unistd.h>
|
||||
#define USLEEP(x) usleep(x)
|
||||
#endif
|
||||
|
||||
#if __STDC_VERSION__ >= 19990L && !defined DEBUG
|
||||
/* If DEBUG is defined the keyword inline is not recognised (syntax error). */
|
||||
#define INLINE inline
|
||||
#elif defined _MSC_VER
|
||||
/* Visual C++ doesn't allow inline in C source code */
|
||||
#define INLINE __inline
|
||||
#else
|
||||
#define INLINE
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,990 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* cd64lib.c
|
||||
*
|
||||
* Library routines for CD64 handling
|
||||
*
|
||||
* (c) 2004 Ryan Underwood
|
||||
* Portions (c) 2004 Daniel Horchner (Win32, read/write/seek callbacks)
|
||||
*
|
||||
* May be distributed under the terms of the GNU Lesser/Library General
|
||||
* Public License, or any later version of the same, as published by the Free
|
||||
* Software Foundation.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#if defined __unix__ || defined __BEOS__
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if (defined _WIN32 && !defined __CYGWIN__) || defined __MSDOS__
|
||||
#include <sys/timeb.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include <ultra64/host/cd64lib.h>
|
||||
#include <ultra64/rom.h>
|
||||
#include <ultra64/cartmem.h>
|
||||
|
||||
#include "cd64io.h"
|
||||
|
||||
static uint8_t *cd64_tmp_buf;
|
||||
static uint32_t cd64_tmp_buf_offset;
|
||||
|
||||
static int cd64_notice_helper(FILE *file, const char *format, va_list argptr) {
|
||||
|
||||
int n_chars;
|
||||
|
||||
fputs("libcd64: ", file);
|
||||
n_chars = vfprintf(file, format, argptr);
|
||||
fputc('\n', file);
|
||||
fflush(file);
|
||||
|
||||
return n_chars;
|
||||
}
|
||||
|
||||
int cd64_notice(const char *format, ...) {
|
||||
|
||||
va_list argptr;
|
||||
int n_chars;
|
||||
|
||||
va_start(argptr, format);
|
||||
n_chars = cd64_notice_helper(stdout, format, argptr);
|
||||
va_end(argptr);
|
||||
|
||||
return n_chars;
|
||||
}
|
||||
|
||||
int cd64_notice2(const char *format, ...) {
|
||||
|
||||
va_list argptr;
|
||||
int n_chars;
|
||||
|
||||
va_start(argptr, format);
|
||||
n_chars = cd64_notice_helper(stderr, format, argptr);
|
||||
va_end(argptr);
|
||||
|
||||
return n_chars;
|
||||
}
|
||||
|
||||
int cd64_read(void *io_id, void *buffer, uint32_t size) {
|
||||
return fread(buffer, 1, size, (FILE *) io_id);
|
||||
}
|
||||
|
||||
int cd64_write(void *io_id, void *buffer, uint32_t size) {
|
||||
return fwrite(buffer, 1, size, (FILE *) io_id);
|
||||
}
|
||||
|
||||
int32_t cd64_tell(void *io_id) {
|
||||
return (int32_t) ftell((FILE *) io_id);
|
||||
}
|
||||
|
||||
int cd64_seek(void *io_id, int32_t offset, int whence) {
|
||||
return fseek((FILE *) io_id, offset, whence);
|
||||
}
|
||||
|
||||
int cd64_create(struct cd64_t *cd64, method_t method,
|
||||
uint16_t port, protocol_t protocol, int ppa) {
|
||||
|
||||
cd64->using_ppa = (ppa)? 1 : 0;
|
||||
cd64->protocol = protocol;
|
||||
cd64->port = port;
|
||||
|
||||
if (!cd64->notice_callback) cd64->notice_callback = cd64_notice;
|
||||
if (!cd64->notice_callback2) cd64->notice_callback2 = cd64_notice2;
|
||||
|
||||
cd64->read_callback = cd64_read;
|
||||
cd64->write_callback = cd64_write;
|
||||
cd64->tell_callback = cd64_tell;
|
||||
cd64->seek_callback = cd64_seek;
|
||||
|
||||
#ifdef CD64_USE_LIBIEEE1284
|
||||
if (method == LIBIEEE1284) {
|
||||
cd64->devopen = cd64_open_ieee1284;
|
||||
cd64->xfer = cd64_xfer_ieee1284;
|
||||
cd64->devclose = cd64_close_ieee1284;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
#ifdef CD64_USE_PPDEV
|
||||
if (method == PPDEV) {
|
||||
cd64->devopen = cd64_open_ppdev;
|
||||
cd64->xfer = cd64_xfer_ppdev;
|
||||
cd64->devclose = cd64_close_ppdev;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
#ifdef CD64_USE_PORTDEV
|
||||
if (method == PORTDEV) {
|
||||
cd64->devopen = cd64_open_portdev;
|
||||
cd64->xfer = cd64_xfer_portdev;
|
||||
cd64->devclose = cd64_close_portdev;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
#ifdef CD64_USE_RAWIO
|
||||
if (method == RAWIO) {
|
||||
cd64->devopen = cd64_open_rawio;
|
||||
cd64->xfer = cd64_xfer_rawio;
|
||||
cd64->devclose = cd64_close_rawio;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
{
|
||||
switch (method) {
|
||||
case LIBIEEE1284:
|
||||
cd64->notice_callback2("libieee1284 not supported.");
|
||||
break;
|
||||
case PPDEV:
|
||||
cd64->notice_callback2("ppdev not supported.");
|
||||
break;
|
||||
case PORTDEV:
|
||||
cd64->notice_callback2("portdev not supported.");
|
||||
break;
|
||||
case RAWIO:
|
||||
cd64->notice_callback2("rawio not supported.");
|
||||
break;
|
||||
default:
|
||||
cd64->notice_callback2("unknown hw access method.");
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* CD64 BIOS routines */
|
||||
|
||||
static int cd64_bios_sync(struct cd64_t *cd64) {
|
||||
|
||||
unsigned char ret1 = 0, ret2 = 0;
|
||||
|
||||
cd64->notice_callback("Waiting for CD64 comms to come online...");
|
||||
|
||||
while (!(ret1 == 'R' && ret2 == 'W')) {
|
||||
if (cd64->abort) return 0;
|
||||
/* approximation here */
|
||||
cd64_send_byte(cd64, 'W');
|
||||
cd64_send_byte(cd64, 'B');
|
||||
cd64_trade_bytes(cd64, 'B', &ret1);
|
||||
cd64_trade_bytes(cd64, 'B', &ret2);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cd64_bios_grab(struct cd64_t *cd64, void *io_id, uint32_t addr,
|
||||
uint32_t length, int *elapsed) {
|
||||
|
||||
unsigned int i;
|
||||
unsigned short pc_csum = 0, n64_csum = 0;
|
||||
#if (defined _WIN32 && !defined __CYGWIN__) || defined __MSDOS__
|
||||
struct timeb tb;
|
||||
#else
|
||||
struct timeval tv;
|
||||
#endif
|
||||
unsigned long int sec = 0, usec = 0;
|
||||
uint8_t send, recv;
|
||||
uint8_t cmd = 0xff;
|
||||
uint8_t tmp;
|
||||
|
||||
if (!length || length&0x00000003 || addr&0x00000003) return 0;
|
||||
if (addr <= 0xa03fffff && addr+length <= 0xa03fffff) {
|
||||
cmd = BIOS_DUMP_N64;
|
||||
}
|
||||
else if (addr >= 0xa8000000 && addr <= 0xbfffffff
|
||||
&& addr+length <= 0xbfffffff) {
|
||||
cmd = BIOS_DUMP_PI;
|
||||
}
|
||||
|
||||
if (cmd == 0xff) {
|
||||
cd64->notice_callback2("Invalid memory range %lxh-%lxh for operation.",
|
||||
(long unsigned int) addr, (long unsigned int) addr+length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Try to get in sync with the CD64
|
||||
* We use a delay here to give the PPA a chance to power up. */
|
||||
send = 0xff;
|
||||
cd64->xfer(cd64, &send, NULL, 1000);
|
||||
cd64_bios_sync(cd64);
|
||||
|
||||
if (elapsed != NULL) {
|
||||
#if (defined _WIN32 && !defined __CYGWIN__) || defined __MSDOS__
|
||||
ftime(&tb);
|
||||
sec = tb.time;
|
||||
usec = tb.millitm*1000;
|
||||
#else
|
||||
gettimeofday(&tv, 0);
|
||||
sec = tv.tv_sec;
|
||||
usec = tv.tv_usec;
|
||||
#endif
|
||||
}
|
||||
|
||||
cd64_send_byte(cd64, cmd);
|
||||
cd64_send_dword(cd64, addr);
|
||||
cd64_send_dword(cd64, length);
|
||||
|
||||
/* dummy exchange, needed for some reason */
|
||||
cd64_grab_byte(cd64, &recv);
|
||||
|
||||
for (i = 1; i <= length; i++) {
|
||||
|
||||
if (cd64->abort) return 0;
|
||||
if (!cd64_grab_byte(cd64, &tmp)) return 0;
|
||||
if (!cd64->write_callback(io_id, &tmp, 1)) {
|
||||
cd64->notice_callback2("Error writing to output.");
|
||||
return 0;
|
||||
}
|
||||
pc_csum += tmp;
|
||||
if ((i % CD64_BUFFER_SIZE == 0) && cd64->progress_callback) {
|
||||
cd64->progress_callback(i, length);
|
||||
}
|
||||
}
|
||||
|
||||
if (cd64->progress_callback) {
|
||||
cd64->progress_callback(i, length);
|
||||
}
|
||||
|
||||
if (elapsed != NULL) {
|
||||
#if (defined _WIN32 && !defined __CYGWIN__) || defined __MSDOS__
|
||||
ftime(&tb);
|
||||
*elapsed = ((tb.time - sec)*1000000) + ((tb.millitm*1000) - usec);
|
||||
#else
|
||||
gettimeofday(&tv, 0);
|
||||
*elapsed = ((tv.tv_sec - sec)*1000000) + (tv.tv_usec - usec);
|
||||
#endif
|
||||
}
|
||||
|
||||
pc_csum &= 0xfff;
|
||||
cd64_trade_bytes(cd64, 0, &recv);
|
||||
n64_csum = recv << 8;
|
||||
cd64_trade_bytes(cd64, 0, &recv);
|
||||
n64_csum += recv;
|
||||
n64_csum &= 0xfff;
|
||||
|
||||
/* debug("\nVerifying checksum: pcsum = %d, n64sum = %d\n", pc_csum, n64_csum); */
|
||||
if (pc_csum^n64_csum) return -1;
|
||||
else return 1;
|
||||
}
|
||||
|
||||
int cd64_bios_send(struct cd64_t *cd64, void *io_id, uint32_t addr,
|
||||
uint32_t length, int *elapsed, int cmd) {
|
||||
|
||||
unsigned int i;
|
||||
uint16_t pc_csum = 0;
|
||||
#if (defined _WIN32 && !defined __CYGWIN__) || defined __MSDOS__
|
||||
struct timeb tb;
|
||||
#else
|
||||
struct timeval tv;
|
||||
#endif
|
||||
unsigned long int sec = 0, usec = 0;
|
||||
uint8_t send;
|
||||
uint8_t buf[4];
|
||||
int valid = 1;
|
||||
uint8_t send_bogus_csum = 0;
|
||||
uint8_t tmp;
|
||||
int32_t pos;
|
||||
|
||||
if (!io_id || !length || length&0x00000003 || addr&0x00000003) return 0;
|
||||
if (cmd != BIOS_TRANSFER_PI && cmd != BIOS_EXECUTE_PI && cmd != BIOS_TRANSFER_N64
|
||||
&& !(cd64->protocol == GHEMOR && cmd == GHEMOR_TRANSFER_PROGRAM)) return 0;
|
||||
|
||||
if (cmd == BIOS_TRANSFER_PI || cmd == BIOS_EXECUTE_PI) {
|
||||
if (addr < 0xa8000000 || addr > 0xbfffffff ||
|
||||
addr+length > 0xbfffffff) valid = 0;
|
||||
}
|
||||
else if (cmd == BIOS_TRANSFER_N64) {
|
||||
if (addr < 0xa0000000 || addr > 0xa03fffff
|
||||
|| addr+length > 0xa03fffff) valid = 0;
|
||||
|
||||
if (addr != BIOS_TEMP_RAM || length > 0x80000) {
|
||||
/* FIXME: is 0x80000 (512Kbit) really all the CD64
|
||||
* BIOS will copy from a mempak? See if it copies
|
||||
* 1Mbit from a 4x linear card. */
|
||||
|
||||
/* We are sending somewhere in RAM besides the CD64's
|
||||
* scratch area. We will send a bogus checksum so the
|
||||
* CD64 doesn't try to run it or copy it to a mempak.
|
||||
*/
|
||||
send_bogus_csum = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!valid) {
|
||||
cd64->notice_callback2("Invalid address %lxh for operation.",
|
||||
(long unsigned int) addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cd64->protocol == GHEMOR && addr != 0xb4000000 &&
|
||||
(cmd == BIOS_TRANSFER_PI || cmd == BIOS_EXECUTE_PI)) {
|
||||
/* They might try to send to Ghemor in BIOS mode, but
|
||||
* oh well. Warn them if we know it's Ghemor. */
|
||||
cd64->notice_callback("Ignoring address %lxh != 0xb4000000 for Ghemor.",
|
||||
(long unsigned int) addr);
|
||||
}
|
||||
if (cmd == GHEMOR_TRANSFER_PROGRAM) {
|
||||
cd64->notice_callback("Ghemor ignores this command currently...");
|
||||
}
|
||||
|
||||
|
||||
/* Try to get in sync with the CD64
|
||||
* We use a delay here to give the PPA a chance to power up. */
|
||||
send = 0xff;
|
||||
cd64->xfer(cd64, &send, NULL, 1000);
|
||||
cd64_bios_sync(cd64);
|
||||
|
||||
if (elapsed != NULL) {
|
||||
#if (defined _WIN32 && !defined __CYGWIN__) || defined __MSDOS__
|
||||
ftime(&tb);
|
||||
sec = tb.time;
|
||||
usec = tb.millitm*1000;
|
||||
#else
|
||||
gettimeofday(&tv, 0);
|
||||
sec = tv.tv_sec;
|
||||
usec = tv.tv_usec;
|
||||
#endif
|
||||
}
|
||||
|
||||
cd64_send_byte(cd64, (uint8_t) cmd);
|
||||
cd64_send_dword(cd64, addr); /* Ghemor ignores this */
|
||||
cd64_send_dword(cd64, length);
|
||||
|
||||
pos = cd64->tell_callback(io_id);
|
||||
|
||||
i = 0;
|
||||
while (i < length) {
|
||||
|
||||
if (cd64->abort) return 0;
|
||||
cd64->read_callback(io_id, &tmp, 1);
|
||||
pc_csum += tmp;
|
||||
pc_csum &= 0xfff;
|
||||
if (!cd64_send_byte(cd64, tmp)) {
|
||||
if (cd64->protocol == CD64BIOS) {
|
||||
/* Probably the BIOS was stupid and dropped a
|
||||
* send as it likes to. Try to recover from
|
||||
* a convenient point. */
|
||||
while (i % 4 != 0) i--;
|
||||
cd64->seek_callback(io_id, pos+i, SEEK_SET);
|
||||
cd64->read_callback(io_id, &tmp, 1);
|
||||
cd64->notice_callback("Trying to recover dropped send, waiting for CD64...");
|
||||
cd64_bios_sync(cd64);
|
||||
cd64_send_byte(cd64, (uint8_t) cmd);
|
||||
cd64_send_dword(cd64, addr+i);
|
||||
cd64_send_dword(cd64, length-i);
|
||||
|
||||
if (!cd64_send_byte(cd64, tmp)) {
|
||||
/* Oh well, at least we tried. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Unfortunately we can only calculate a checksum
|
||||
* from _this_ point onward. */
|
||||
pc_csum = tmp;
|
||||
|
||||
/* Now continue as if nothing ever happened. */
|
||||
}
|
||||
else {
|
||||
cd64->notice_callback2("Send dropped, unable to recover.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ((i % CD64_BUFFER_SIZE == 0) && cd64->progress_callback) {
|
||||
cd64->progress_callback(i, length);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (cd64->progress_callback) {
|
||||
cd64->progress_callback(i, length);
|
||||
}
|
||||
|
||||
if (elapsed != NULL) {
|
||||
#if (defined _WIN32 && !defined __CYGWIN__) || defined __MSDOS__
|
||||
ftime(&tb);
|
||||
*elapsed = ((tb.time - sec)*1000000) + ((tb.millitm*1000) - usec);
|
||||
#else
|
||||
gettimeofday(&tv, 0);
|
||||
*elapsed = ((tv.tv_sec - sec)*1000000) + (tv.tv_usec - usec);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* debug("checksum: 0x%x\n",pc_csum) */
|
||||
cd64_send_byte(cd64, (unsigned char)((pc_csum & 0xff00) >> 8));
|
||||
/* debug("Sent checksum high byte: 0x%x\n",(unsigned char)pc_csum>>8); */
|
||||
cd64_send_byte(cd64, (uint8_t) ((pc_csum & 0xff) + send_bogus_csum));
|
||||
/* debug("Sent checksum low byte: 0x%x\n",pc_csum); */
|
||||
cd64_grab_byte(cd64, &buf[2]);
|
||||
cd64_trade_bytes(cd64, 0, &buf[0]);
|
||||
cd64_trade_bytes(cd64, 0, &buf[1]);
|
||||
|
||||
/* debug("Got: (dummy) 0x%x, 0x%x (%c), 0x%x (%c)",buf[2], buf[0], buf[0], buf[1],buf[1]); */
|
||||
if (buf[0]=='O' && buf[1]=='K') return 1;
|
||||
else if (send_bogus_csum) {
|
||||
cd64->notice_callback("No way to verify integrity of data in N64 RAM.");
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int cd64_ghemor_grab(struct cd64_t *cd64, void *io_id, uint8_t slow, int *elapsed) {
|
||||
|
||||
int ret;
|
||||
uint8_t tmp;
|
||||
int sec = 0, usec = 0;
|
||||
#if (defined _WIN32 && !defined __CYGWIN__) || defined __MSDOS__
|
||||
struct timeb tb;
|
||||
#else
|
||||
struct timeval tv;
|
||||
#endif
|
||||
uint32_t len;
|
||||
uint16_t mycsum = 0;
|
||||
uint16_t cd64csum;
|
||||
unsigned int i;
|
||||
|
||||
if (slow) {
|
||||
cd64->notice_callback2("Ghemor slow receive feature not supported.");
|
||||
return 0;
|
||||
}
|
||||
if (elapsed != NULL) {
|
||||
#if (defined _WIN32 && !defined __CYGWIN__) || defined __MSDOS__
|
||||
ftime(&tb);
|
||||
sec = tb.time;
|
||||
usec = tb.millitm*1000;
|
||||
#else
|
||||
gettimeofday(&tv, 0);
|
||||
sec = tv.tv_sec;
|
||||
usec = tv.tv_usec;
|
||||
#endif
|
||||
}
|
||||
|
||||
cd64_send_byte(cd64, slow);
|
||||
i = 0;
|
||||
while (cd64_grab_byte(cd64, &tmp) && tmp != 1) {
|
||||
i++;
|
||||
if (i > 25) {
|
||||
cd64->notice_callback2("Ghemor was not ready.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
cd64_grab_dword(cd64, &len);
|
||||
cd64->notice_callback("Downloading %lu megabits via Ghemor.",
|
||||
(long unsigned int) len/BYTES_IN_MBIT);
|
||||
for (i = 0; i < len; i++) {
|
||||
if (!cd64_grab_byte(cd64, &tmp)) return 0;
|
||||
if (!cd64->write_callback(io_id, &tmp, 1)) {
|
||||
cd64->notice_callback2("Error writing to output.");
|
||||
return 0;
|
||||
}
|
||||
mycsum += tmp;
|
||||
mycsum &= 0xfff;
|
||||
if ((i % CD64_BUFFER_SIZE == 0) && cd64->progress_callback) {
|
||||
cd64->progress_callback(i, len);
|
||||
}
|
||||
}
|
||||
if (cd64->progress_callback) {
|
||||
cd64->progress_callback(i, len);
|
||||
}
|
||||
|
||||
cd64_grab_byte(cd64, &tmp);
|
||||
cd64csum = tmp << 8;
|
||||
cd64_grab_byte(cd64, &tmp);
|
||||
cd64csum |= tmp;
|
||||
if (mycsum^cd64csum) ret = -1;
|
||||
else ret = 1;
|
||||
if (elapsed != NULL) {
|
||||
#if (defined _WIN32 && !defined __CYGWIN__) || defined __MSDOS__
|
||||
ftime(&tb);
|
||||
*elapsed = ((tb.time - sec)*1000000) + ((tb.millitm*1000) - usec);
|
||||
#else
|
||||
gettimeofday(&tv, 0);
|
||||
*elapsed = ((tv.tv_sec - sec)*1000000) + (tv.tv_usec - usec);
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cd64_ghemor_send(struct cd64_t *cd64, void *io_id, uint32_t length,
|
||||
int *elapsed) {
|
||||
|
||||
int sec = 0, usec = 0;
|
||||
uint16_t mycsum = 0;
|
||||
unsigned int i;
|
||||
#if (defined _WIN32 && !defined __CYGWIN__) || defined __MSDOS__
|
||||
struct timeb tb;
|
||||
#else
|
||||
struct timeval tv;
|
||||
#endif
|
||||
uint8_t tmp;
|
||||
|
||||
if (elapsed != NULL) {
|
||||
#if (defined _WIN32 && !defined __CYGWIN__) || defined __MSDOS__
|
||||
ftime(&tb);
|
||||
sec = tb.time;
|
||||
usec = tb.millitm*1000;
|
||||
#else
|
||||
gettimeofday(&tv, 0);
|
||||
sec = tv.tv_sec;
|
||||
usec = tv.tv_usec;
|
||||
#endif
|
||||
}
|
||||
|
||||
cd64_send_byte(cd64, 0); /* No slow mode for sends */
|
||||
i = 0;
|
||||
while (cd64_grab_byte(cd64, &tmp) && tmp != 1) {
|
||||
i++;
|
||||
if (i > 25) {
|
||||
cd64->notice_callback2("Ghemor was not ready.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
cd64_send_dword(cd64, length);
|
||||
for (i = 0; i < length; i++) {
|
||||
if (!cd64->read_callback(io_id, &tmp, 1)) {
|
||||
cd64->notice_callback2("Error reading from input.");
|
||||
return 0;
|
||||
}
|
||||
if (!cd64_send_byte(cd64, tmp)) return 0;
|
||||
mycsum += tmp;
|
||||
mycsum &= 0xfff;
|
||||
if ((i % CD64_BUFFER_SIZE == 0) && cd64->progress_callback) {
|
||||
cd64->progress_callback(i, length);
|
||||
}
|
||||
}
|
||||
if (cd64->progress_callback) {
|
||||
cd64->progress_callback(i, length);
|
||||
}
|
||||
cd64_send_byte(cd64, (uint8_t)((mycsum << 8) & 0xff));
|
||||
cd64_send_byte(cd64, (uint8_t)(mycsum & 0xff));
|
||||
if (elapsed != NULL) {
|
||||
#if (defined _WIN32 && !defined __CYGWIN__) || defined __MSDOS__
|
||||
ftime(&tb);
|
||||
*elapsed = ((tb.time - sec)*1000000) + ((tb.millitm*1000) - usec);
|
||||
#else
|
||||
gettimeofday(&tv, 0);
|
||||
*elapsed = ((tv.tv_sec - sec)*1000000) + (tv.tv_usec - usec);
|
||||
#endif
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Generic API functions */
|
||||
|
||||
int cd64_upload_dram(struct cd64_t *cd64, FILE *source, uint32_t length,
|
||||
int *elapsed, int exec) {
|
||||
|
||||
if (cd64->protocol == CD64BIOS || cd64->protocol == GHEMOR) {
|
||||
int cmd;
|
||||
if (exec == 1) cmd = BIOS_EXECUTE_PI;
|
||||
else cmd = BIOS_TRANSFER_PI;
|
||||
|
||||
if (cd64->protocol == CD64BIOS && length == 0) {
|
||||
cd64->notice_callback2("CD64 BIOS needs a file length.");
|
||||
return 0;
|
||||
}
|
||||
if (cd64->protocol == CD64BIOS) {
|
||||
cd64->notice_callback("Choose CD64 Tools->Pro Comms Link.");
|
||||
}
|
||||
|
||||
return cd64_bios_send(cd64, source, 0xb4000000, length, elapsed, cmd);
|
||||
}
|
||||
cd64->notice_callback2("Operation not supported by protocol.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cd64_upload_bootemu(struct cd64_t *cd64, FILE *infile, uint32_t length, int *elapsed) {
|
||||
|
||||
if (cd64->protocol == CD64BIOS) {
|
||||
|
||||
if (cd64->protocol == CD64BIOS && length == 0) {
|
||||
cd64->notice_callback2("CD64 BIOS needs a file length.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
cd64->notice_callback("Choose CD64 Tools->Pro Comms Link.");
|
||||
return cd64_bios_send(cd64, infile, BIOS_TEMP_RAM, length, elapsed,
|
||||
BIOS_TRANSFER_N64);
|
||||
}
|
||||
else if (cd64->protocol == GHEMOR) {
|
||||
cd64_bios_sync(cd64);
|
||||
cd64_send_byte(cd64, GHEMOR_EXECUTE_BOOTEMU);
|
||||
return cd64_ghemor_send(cd64, infile, length, elapsed);
|
||||
}
|
||||
cd64->notice_callback2("Operation not supported by protocol.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cd64_upload_ram(struct cd64_t *cd64, FILE *infile, uint32_t length,
|
||||
int *elapsed, uint32_t address) {
|
||||
|
||||
if (cd64->protocol == CD64BIOS) {
|
||||
cd64->notice_callback("Choose CD64 Tools->Pro Comms Link.");
|
||||
return cd64_bios_send(cd64, infile, address, length,
|
||||
elapsed, BIOS_TRANSFER_N64);
|
||||
}
|
||||
cd64->notice_callback2("Operation not supported by protocol.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cd64_upload_mempak(struct cd64_t *cd64, FILE *infile, int8_t which) {
|
||||
|
||||
int32_t len;
|
||||
int32_t pos = cd64->tell_callback(infile);
|
||||
cd64->seek_callback(infile, 0, SEEK_END);
|
||||
len = cd64->tell_callback(infile);
|
||||
cd64->seek_callback(infile, pos, SEEK_SET);
|
||||
if (len != CONTROLLER_MEMPAK_LENGTH) {
|
||||
cd64->notice_callback("Mempack file must be %d bytes, not %d.",
|
||||
CONTROLLER_MEMPAK_LENGTH, len);
|
||||
}
|
||||
|
||||
if (cd64->protocol == CD64BIOS) {
|
||||
if (which != -1) {
|
||||
cd64->notice_callback2("CD64 BIOS doesn't let mempak index be chosen.");
|
||||
return 0;
|
||||
}
|
||||
cd64->notice_callback("Choose Memory Manager->Up/Download Pak.");
|
||||
return cd64_bios_send(cd64, infile, BIOS_TEMP_RAM, CONTROLLER_MEMPAK_LENGTH,
|
||||
NULL, BIOS_TRANSFER_N64);
|
||||
}
|
||||
else if (cd64->protocol == GHEMOR) {
|
||||
cd64_bios_sync(cd64);
|
||||
cd64_send_byte(cd64, GHEMOR_RESTORE_MEMPAK);
|
||||
cd64_send_byte(cd64, which);
|
||||
return cd64_ghemor_send(cd64, infile, CONTROLLER_MEMPAK_LENGTH, NULL);
|
||||
}
|
||||
cd64->notice_callback2("Operation not supported by protocol.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cd64_upload_sram(struct cd64_t *cd64, FILE *infile) {
|
||||
|
||||
if (cd64->protocol == CD64BIOS) {
|
||||
cd64->notice_callback("Choose CD64 Tools->Pro Comms Link.");
|
||||
return cd64_bios_send(cd64, infile, 0xa8000000, CART_SRAM_LENGTH,
|
||||
NULL, BIOS_TRANSFER_PI);
|
||||
}
|
||||
else if (cd64->protocol == GHEMOR) {
|
||||
cd64_bios_sync(cd64);
|
||||
cd64_send_byte(cd64, GHEMOR_RESTORE_SRAM);
|
||||
return cd64_ghemor_send(cd64, infile, CART_SRAM_LENGTH, NULL);
|
||||
}
|
||||
cd64->notice_callback2("Operation not supported by protocol.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cd64_upload_flashram(struct cd64_t *cd64, FILE *infile) {
|
||||
|
||||
/* Urm, we need to figure out if this really works. Probably, CTR
|
||||
* needs to release a new Ghemor version. Maybe it works with
|
||||
* CD64 BIOS but probably not. */
|
||||
|
||||
if (cd64->protocol == CD64BIOS) {
|
||||
cd64->notice_callback("Choose CD64 Tools->Pro Comms Link.");
|
||||
return cd64_bios_send(cd64, infile, 0xa8000000, CART_FLASHRAM_LENGTH,
|
||||
NULL, BIOS_TRANSFER_PI);
|
||||
}
|
||||
else if (cd64->protocol == GHEMOR) {
|
||||
cd64_bios_sync(cd64);
|
||||
cd64_send_byte(cd64, GHEMOR_RESTORE_FLASHRAM);
|
||||
return cd64_ghemor_send(cd64, infile, CART_FLASHRAM_LENGTH, NULL);
|
||||
}
|
||||
cd64->notice_callback2("Operation not supported by protocol.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cd64_upload_eeprom(struct cd64_t *cd64, FILE *infile) {
|
||||
|
||||
/* Check the size of the EEPROM data first */
|
||||
|
||||
int32_t origpos = cd64->tell_callback(infile);
|
||||
int32_t length;
|
||||
|
||||
if (cd64->protocol == CD64BIOS) {
|
||||
cd64->notice_callback2("CD64 BIOS can only transfer EEPROM through BRAM Manager.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
cd64->seek_callback(infile, 0, SEEK_END);
|
||||
length = cd64->tell_callback(infile);
|
||||
cd64->seek_callback(infile, origpos, SEEK_SET);
|
||||
|
||||
if (length != CART_EEPROM_LENGTH && length != CART_2XEEPROM_LENGTH) {
|
||||
cd64->notice_callback2("Wrong length of EEPROM data: %d bytes", (int) length);
|
||||
return 0;
|
||||
}
|
||||
else if (cd64->protocol == GHEMOR) {
|
||||
cd64_bios_sync(cd64);
|
||||
cd64_send_byte(cd64, GHEMOR_RESTORE_EEPROM);
|
||||
return cd64_ghemor_send(cd64, infile, length, NULL);
|
||||
}
|
||||
cd64->notice_callback2("Operation not supported by protocol.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cd64_write_mem(void *dummy, void *buffer, uint32_t size) {
|
||||
|
||||
(void) dummy;
|
||||
memcpy (cd64_tmp_buf + cd64_tmp_buf_offset, buffer, size);
|
||||
cd64_tmp_buf_offset += size;
|
||||
return size;
|
||||
}
|
||||
|
||||
int cd64_download_header(struct cd64_t *cd64, n64header_t *head, uint32_t location) {
|
||||
|
||||
if (cd64->protocol == CD64BIOS) {
|
||||
int size = sizeof(n64header_t);
|
||||
int ret;
|
||||
int (*org_write_cb)(void *, void *, uint32_t) = cd64->write_callback;
|
||||
|
||||
while (size % 4 != 0) size++;
|
||||
if (!head) return 0;
|
||||
cd64_tmp_buf = (uint8_t *) head;
|
||||
cd64_tmp_buf_offset = 0;
|
||||
cd64->write_callback = cd64_write_mem;
|
||||
ret = cd64_bios_grab(cd64, (void *) -1, location, size, NULL); /* -1 is just a random (non-zero) value */
|
||||
cd64->write_callback = org_write_cb; /* restore original callback */
|
||||
return 1;
|
||||
}
|
||||
cd64->notice_callback2("Operation not supported by protocol.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cd64_download_cart(struct cd64_t *cd64, FILE *outfile, uint32_t length,
|
||||
int *elapsed) {
|
||||
|
||||
if (cd64->protocol == CD64BIOS) {
|
||||
int ret;
|
||||
unsigned int i;
|
||||
int32_t curpos = 0;
|
||||
int32_t origpos = cd64->tell_callback(outfile);
|
||||
if (length == 0) {
|
||||
cd64->notice_callback2("CD64 BIOS needs a file length.");
|
||||
return 0;
|
||||
}
|
||||
cd64->notice_callback("Choose CD64 Tools->Pro Comms Link.");
|
||||
|
||||
ret = cd64_bios_grab(cd64, outfile, 0xb2000000, length, elapsed);
|
||||
/* Scan through the file at 8MBit intervals to
|
||||
* see if we overdumped. If we did, truncate the
|
||||
* file. */
|
||||
i = 0;
|
||||
cd64->seek_callback(outfile, origpos, SEEK_SET);
|
||||
cd64->notice_callback("Checking for overdump...");
|
||||
while (i < length) {
|
||||
int j = 0;
|
||||
int overdump = 1;
|
||||
uint8_t buf[4];
|
||||
|
||||
curpos = cd64->tell_callback(outfile);
|
||||
|
||||
while(i+j < length) {
|
||||
cd64->read_callback(outfile, &buf, 4);
|
||||
|
||||
/* To elaborate on what we are checking here:
|
||||
* When the CD64 accesses an address which is not
|
||||
* decoded, in each 32-bit word is the lower 16 bits
|
||||
* of the address of that 32-bit word, repeated twice.
|
||||
* The pattern therefore looks like:
|
||||
* 00 00 00 00 00 04 00 04 00 08 00 08 00 0c 00 0c
|
||||
* and continues on like that. This pattern is what
|
||||
* we are looking for here. It is possible, but
|
||||
* extremely unlikely, that this pattern appears in a
|
||||
* actual game and begins on a 8Mbit boundary too. */
|
||||
|
||||
if (
|
||||
((uint8_t*)buf)[0] != ((j >> 8) & 0xff)
|
||||
|| ((uint8_t*)buf)[1] != (j & 0xff)
|
||||
|| ((uint8_t*)buf)[2] != ((j >> 8) & 0xff)
|
||||
|| ((uint8_t*)buf)[3] != (j & 0xff)
|
||||
) {
|
||||
overdump = 0;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
j+=4;
|
||||
}
|
||||
}
|
||||
|
||||
if (overdump) {
|
||||
break;
|
||||
}
|
||||
i += 0x100000;
|
||||
cd64->seek_callback(outfile, curpos+0x100000, SEEK_SET);
|
||||
}
|
||||
|
||||
if (i < length) {
|
||||
cd64->notice_callback("File apparently overdumped.");
|
||||
#if (!defined _WIN32 || defined __CYGWIN__)
|
||||
/* Don't call ftruncate() if the user installed a callback, because
|
||||
* outfile may not be a real FILE *. */
|
||||
if (cd64->read_callback == cd64_read) {
|
||||
cd64->notice_callback("Truncating to %dMbits.", i/BYTES_IN_MBIT);
|
||||
ftruncate(fileno(outfile), curpos+i);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
else if (cd64->protocol == GHEMOR) {
|
||||
cd64_bios_sync(cd64);
|
||||
cd64_send_byte(cd64, GHEMOR_DUMP_CART);
|
||||
return cd64_ghemor_grab(cd64, outfile, 0, elapsed);
|
||||
}
|
||||
cd64->notice_callback2("Operation not supported by protocol.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cd64_download_dram(struct cd64_t *cd64, FILE *outfile, uint32_t start,
|
||||
uint32_t end, int *elapsed) {
|
||||
|
||||
if (cd64->protocol == CD64BIOS) {
|
||||
cd64->notice_callback("Choose CD64 Tools->Pro Comms Link.");
|
||||
return cd64_bios_grab(cd64, outfile, 0xb4000000, end-start, elapsed);
|
||||
}
|
||||
cd64->notice_callback2("Operation not supported by protocol.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cd64_download_sram(struct cd64_t *cd64, FILE *outfile) {
|
||||
|
||||
if (cd64->protocol == CD64BIOS) {
|
||||
cd64->notice_callback("Choose CD64 Tools->Pro Comms Link.");
|
||||
return cd64_bios_grab(cd64, outfile, CART_SRAM_ADDR, CART_SRAM_LENGTH, NULL);
|
||||
}
|
||||
else if (cd64->protocol == GHEMOR) {
|
||||
cd64_bios_sync(cd64);
|
||||
cd64_send_byte(cd64, GHEMOR_DUMP_SRAM);
|
||||
return cd64_ghemor_grab(cd64, outfile, 0, NULL);
|
||||
}
|
||||
cd64->notice_callback2("Operation not supported by protocol.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cd64_download_flashram(struct cd64_t *cd64, FILE *outfile) {
|
||||
|
||||
/* We might be able to support CD64 BIOS here. Needs testing. */
|
||||
if (cd64->protocol == GHEMOR) {
|
||||
cd64_bios_sync(cd64);
|
||||
cd64_send_byte(cd64, GHEMOR_DUMP_FLASH);
|
||||
return cd64_ghemor_grab(cd64, outfile, 0, NULL);
|
||||
}
|
||||
cd64->notice_callback2("Operation not supported by protocol.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cd64_download_eeprom(struct cd64_t *cd64, FILE *outfile) {
|
||||
|
||||
if (cd64->protocol == GHEMOR) {
|
||||
cd64_bios_sync(cd64);
|
||||
cd64_send_byte(cd64, GHEMOR_DUMP_EEPROM);
|
||||
return cd64_ghemor_grab(cd64, outfile, 0, NULL);
|
||||
}
|
||||
cd64->notice_callback2("Operation not supported by protocol.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cd64_download_mempak(struct cd64_t *cd64, FILE *outfile, int8_t which) {
|
||||
|
||||
if (cd64->protocol == CD64BIOS) {
|
||||
if (which != -1) {
|
||||
cd64->notice_callback2("CD64 BIOS doesn't let mempak index be chosen.");
|
||||
return 0;
|
||||
}
|
||||
cd64->notice_callback("Choose Memory Manager->Up/Download Pak.");
|
||||
return cd64_bios_grab(cd64, outfile, BIOS_TEMP_RAM, CONTROLLER_MEMPAK_LENGTH, NULL);
|
||||
}
|
||||
else if (cd64->protocol == GHEMOR) {
|
||||
cd64_bios_sync(cd64);
|
||||
cd64_send_byte(cd64, GHEMOR_DUMP_MEMPAK);
|
||||
cd64_send_byte(cd64, which);
|
||||
return cd64_ghemor_grab(cd64, outfile, 0, NULL);
|
||||
}
|
||||
cd64->notice_callback2("Operation not supported by protocol.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cd64_read_mem(void *dummy, void *buffer, uint32_t size) {
|
||||
|
||||
(void) dummy;
|
||||
memcpy (buffer, cd64_tmp_buf + cd64_tmp_buf_offset, size);
|
||||
cd64_tmp_buf_offset += size;
|
||||
return size;
|
||||
}
|
||||
|
||||
static int32_t cd64_tell_mem(void *dummy) {
|
||||
|
||||
(void) dummy;
|
||||
return cd64_tmp_buf_offset;
|
||||
}
|
||||
|
||||
static int cd64_seek_mem(void *dummy, int32_t offset, int whence) {
|
||||
|
||||
(void) dummy;
|
||||
(void) whence; /* only called with SEEK_SET */
|
||||
cd64_tmp_buf_offset = offset;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cd64_run_dram(struct cd64_t *cd64) {
|
||||
|
||||
if (cd64->protocol == GHEMOR) {
|
||||
cd64_bios_sync(cd64);
|
||||
cd64_send_byte(cd64, GHEMOR_RESET_DRAM);
|
||||
return 1;
|
||||
}
|
||||
else if (cd64->protocol == CD64BIOS) {
|
||||
/* Heh. Write some dummy bytes to the cart area. We
|
||||
* can't just send a zero length because the CD64
|
||||
* BIOS gives "File length error". */
|
||||
uint8_t dummy[4] = { 0, 0, 0, 0 };
|
||||
int ret;
|
||||
int (*org_read_cb)(void *, void *, uint32_t) = cd64->read_callback;
|
||||
int32_t (*org_tell_cb)(void *) = cd64->tell_callback;
|
||||
int (*org_seek_cb)(void *, int32_t, int) = cd64->seek_callback;
|
||||
|
||||
cd64->notice_callback("Choose CD64 Tools->Pro Comms Link.");
|
||||
cd64_tmp_buf = dummy;
|
||||
cd64_tmp_buf_offset = 0;
|
||||
cd64->read_callback = cd64_read_mem;
|
||||
cd64->tell_callback = cd64_tell_mem;
|
||||
cd64->seek_callback = cd64_seek_mem;
|
||||
ret = cd64_bios_send(cd64, (void *) -1, 0xb2000000, 4, NULL, BIOS_EXECUTE_PI); /* -1 is just a random (non-zero) value */
|
||||
cd64->read_callback = org_read_cb; /* restore original callbacks */
|
||||
cd64->tell_callback = org_tell_cb;
|
||||
cd64->seek_callback = org_seek_cb;
|
||||
return ret;
|
||||
}
|
||||
cd64->notice_callback2("Operation not supported by protocol.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cd64_run_cart(struct cd64_t *cd64) {
|
||||
|
||||
if (cd64->protocol == GHEMOR) {
|
||||
cd64_bios_sync(cd64);
|
||||
cd64_send_byte(cd64, GHEMOR_RESET_CART);
|
||||
return 1;
|
||||
}
|
||||
cd64->notice_callback2("Operation not supported by protocol.");
|
||||
return 0;
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
#ifndef __CARTMEM_H__
|
||||
#define __CARTMEM_H__
|
||||
|
||||
#define CART_EEPROM_LENGTH 0x200 /* 512 bytes */
|
||||
#define CART_2XEEPROM_LENGTH 0x800 /* 2048 bytes */
|
||||
#define CART_SRAM_LENGTH 0x8000 /* 32KB */
|
||||
#define CART_FLASHRAM_LENGTH 0x20000 /* 128KB */
|
||||
#define CONTROLLER_MEMPAK_LENGTH 0x8000 /* 32KB */
|
||||
|
||||
#define CART_SRAM_ADDR 0xa8000000
|
||||
#define CART_FLASHRAM_ADDR CART_SRAM_ADDR
|
||||
|
||||
#endif
|
||||
@@ -1,8 +0,0 @@
|
||||
#ifndef __ULTRA64__HOST__CARTINFO_H__
|
||||
#define __ULTRA64__HOST__CARTINFO_H__
|
||||
|
||||
#include <ultra64/rom.h>
|
||||
|
||||
void ultra64_header_info(n64header_t *carthead);
|
||||
|
||||
#endif
|
||||
@@ -1,189 +0,0 @@
|
||||
#ifndef __CD64LIB_H__
|
||||
#define __CD64LIB_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define CD64_BUFFER_SIZE 32768
|
||||
|
||||
/* This is the only public header file for cd64lib. */
|
||||
|
||||
#if __STDC_VERSION >= 19990L
|
||||
#include <stdint.h>
|
||||
#else
|
||||
#if !(defined __MSDOS__ || defined _MSC_VER)
|
||||
#include <inttypes.h>
|
||||
#else
|
||||
#ifndef OWN_INTTYPES
|
||||
#define OWN_INTTYPES /* signal that these are defined */
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short int uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#ifndef _MSC_VER /* _WIN32 */
|
||||
typedef unsigned long long int uint64_t;
|
||||
#else
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#endif
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int int16_t;
|
||||
typedef signed int int32_t;
|
||||
#ifndef _MSC_VER /* _WIN32 */
|
||||
typedef signed long long int int64_t;
|
||||
#else
|
||||
typedef signed __int64 int64_t;
|
||||
#endif
|
||||
#endif /* OWN_INTTYPES */
|
||||
#endif /* __MSDOS__ || _MSC_VER */
|
||||
#endif /* STDC_VERSION */
|
||||
|
||||
#include <stdio.h> /* FILE, FILENAME_MAX */
|
||||
#include <ultra64/rom.h>
|
||||
|
||||
typedef enum {
|
||||
CD64BIOS = 0,
|
||||
GHEMOR = 1,
|
||||
ULTRALINK = 2
|
||||
} protocol_t;
|
||||
|
||||
typedef enum {
|
||||
LIBIEEE1284 = 1,
|
||||
PPDEV = 2,
|
||||
PORTDEV = 3,
|
||||
RAWIO = 4
|
||||
} method_t;
|
||||
|
||||
/* When using this structure, be sure to calloc it or otherwise set it to
|
||||
* zero before setting values or calling library functions. */
|
||||
|
||||
struct cd64_t {
|
||||
int using_ppa;
|
||||
protocol_t protocol;
|
||||
|
||||
struct parport *ppdev; /* libieee1284 */
|
||||
int ppdevfd; /* ppdev */
|
||||
int portdevfd; /* /dev/port */
|
||||
|
||||
/* If using inb/outb or /dev/port, this is the I/O address
|
||||
* Otherwise it is the parport* number */
|
||||
int port;
|
||||
|
||||
/* Directory with io.dll or dlportio.dll. Used by the Windows ports. */
|
||||
char io_driver_dir[FILENAME_MAX];
|
||||
|
||||
/* A flag that can be set/read to determine whether
|
||||
* the current operation should be canceled. */
|
||||
int abort;
|
||||
|
||||
int (*devopen)(struct cd64_t *cd64);
|
||||
int (*xfer)(struct cd64_t *cd64, uint8_t *write, uint8_t *read, int delayms);
|
||||
int (*devclose)(struct cd64_t *cd64);
|
||||
|
||||
/* Progress callback is responsible for printing header info if the
|
||||
* user wants it */
|
||||
|
||||
void (*progress_callback)(uint32_t curbyte, uint32_t totalbytes);
|
||||
int (*notice_callback)(const char *format, ...);
|
||||
int (*notice_callback2)(const char *format, ...);
|
||||
|
||||
/* Callbacks for read, write and seek operations. By default they point to
|
||||
* callbacks in the library which just call fread(), fwrite(), ftell() and
|
||||
* fseek(). You can change them so that the library doesn't read from or
|
||||
* write to a FILE * (io_id). For example, a client can install its own
|
||||
* callback to make it possible to read from .zip files. */
|
||||
int (*read_callback)(void *io_id, void *buffer, uint32_t size);
|
||||
int (*write_callback)(void *io_id, void *buffer, uint32_t size);
|
||||
int32_t (*tell_callback)(void *io_id);
|
||||
int (*seek_callback)(void *io_id, int32_t offset, int whence);
|
||||
};
|
||||
|
||||
/* This function must be called and return successful before any of the
|
||||
* other functions may be used. */
|
||||
|
||||
int cd64_create(struct cd64_t *cd64, method_t method,
|
||||
uint16_t port, protocol_t protocol, int ppa);
|
||||
|
||||
/* The following five functions are wrappers above the I/O abstraction.
|
||||
* Use them to write code that works regardless of the underlying
|
||||
* transport. */
|
||||
|
||||
int cd64_send_byte(struct cd64_t *cd64, uint8_t what);
|
||||
int cd64_send_dword(struct cd64_t *cd64, uint32_t what);
|
||||
int cd64_grab_byte(struct cd64_t *cd64, uint8_t *val);
|
||||
int cd64_grab_dword(struct cd64_t *cd64, uint32_t *val);
|
||||
int cd64_trade_bytes(struct cd64_t *cd64, uint8_t give, uint8_t *recv);
|
||||
|
||||
/* Generic protocol handlers */
|
||||
|
||||
int cd64_bios_grab(struct cd64_t *cd64, void *io_id, uint32_t addr, uint32_t length,
|
||||
int *elapsed);
|
||||
int cd64_bios_send(struct cd64_t *cd64, void *io_id, uint32_t addr,
|
||||
uint32_t length, int *elapsed, int cmd);
|
||||
|
||||
int cd64_ghemor_grab(struct cd64_t *cd64, void *io_id, uint8_t slow, int *elapsed);
|
||||
int cd64_ghemor_send(struct cd64_t *cd64, void *io_id, uint32_t length,
|
||||
int *elapsed);
|
||||
|
||||
/* Functions for sending files to CD64 */
|
||||
int cd64_upload_dram(struct cd64_t *cd64, FILE *infile, uint32_t length,
|
||||
int *elapsed, int exec);
|
||||
int cd64_upload_ram(struct cd64_t *cd64, FILE *infile, uint32_t length,
|
||||
int *elapsed, uint32_t address);
|
||||
|
||||
int cd64_upload_bootemu(struct cd64_t *cd64, FILE *infile, uint32_t length, int *elapsed);
|
||||
|
||||
int cd64_upload_sram(struct cd64_t *cd64, FILE *infile);
|
||||
int cd64_upload_flashram(struct cd64_t *cd64, FILE *infile);
|
||||
int cd64_upload_eeprom(struct cd64_t *cd64, FILE *infile);
|
||||
int cd64_upload_mempak(struct cd64_t *cd64, FILE *infile, int8_t which);
|
||||
|
||||
/* Functions for receiving files from CD64 */
|
||||
int cd64_download_cart(struct cd64_t *cd64, FILE *outfile, uint32_t length,
|
||||
int *elapsed);
|
||||
int cd64_download_dram(struct cd64_t *cd64, FILE *outfile, uint32_t start,
|
||||
uint32_t end, int *elapsed);
|
||||
int cd64_download_ram(struct cd64_t *cd64, FILE *outfile, uint32_t length,
|
||||
int *elapsed, uint32_t address);
|
||||
|
||||
int cd64_download_sram(struct cd64_t *cd64, FILE *outfile);
|
||||
int cd64_download_flashram(struct cd64_t *cd64, FILE *outfile);
|
||||
int cd64_download_eeprom(struct cd64_t *cd64, FILE *outfile);
|
||||
int cd64_download_mempak(struct cd64_t *cd64, FILE *outfile, int8_t which);
|
||||
|
||||
/* Remote control functions */
|
||||
int cd64_run_dram(struct cd64_t *cd64);
|
||||
int cd64_run_cart(struct cd64_t *cd64);
|
||||
|
||||
/* This function simply gets the header from the cart and can be displayed
|
||||
* using ultra64_header_info() */
|
||||
|
||||
int cd64_download_header(struct cd64_t *cd64, n64header_t *head, uint32_t location);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define BIOS_TEMP_RAM 0xa0300000
|
||||
|
||||
#define BIOS_DUMP_N64 'D'
|
||||
#define BIOS_TRANSFER_N64 'B'
|
||||
|
||||
#define BIOS_DUMP_PI 'G'
|
||||
#define BIOS_TRANSFER_PI 'T'
|
||||
#define BIOS_EXECUTE_PI 'X'
|
||||
|
||||
#define GHEMOR_RESTORE_MEMPAK 1
|
||||
#define GHEMOR_RESTORE_EEPROM 2
|
||||
#define GHEMOR_RESTORE_SRAM 3
|
||||
#define GHEMOR_RESTORE_FLASHRAM 4
|
||||
#define GHEMOR_EXECUTE_BOOTEMU 5
|
||||
#define GHEMOR_TRANSFER_PROGRAM 6
|
||||
#define GHEMOR_DUMP_CART 7
|
||||
#define GHEMOR_DUMP_MEMPAK 8
|
||||
#define GHEMOR_DUMP_EEPROM 9
|
||||
#define GHEMOR_DUMP_SRAM 10
|
||||
#define GHEMOR_DUMP_FLASH 11
|
||||
#define GHEMOR_RESET_DRAM 12
|
||||
#define GHEMOR_RESET_CART 13
|
||||
|
||||
#endif
|
||||
@@ -1,60 +0,0 @@
|
||||
|
||||
#ifndef __ROM_H__
|
||||
#define __ROM_H__
|
||||
|
||||
/* Based on Daedalus header */
|
||||
|
||||
#define N64HEADER_SIZE 0x40
|
||||
#define BYTES_IN_MBIT 0x20000
|
||||
|
||||
#define SwapEndian(x) \
|
||||
((x >> 24)&0x000000FF) \
|
||||
| ((x >> 8 )&0x0000FF00) \
|
||||
| ((x << 8 )&0x00FF0000) \
|
||||
| ((x << 24)&0xFF000000)
|
||||
|
||||
typedef enum {
|
||||
UNKNOWN = 0,
|
||||
EEP4K = 1,
|
||||
EEP16K = 2,
|
||||
SRAM = 3,
|
||||
FLASHRAM = 4
|
||||
} savetype_t;
|
||||
|
||||
typedef struct { /* From Daedalus */
|
||||
unsigned char x1; /* initial PI_BSB_DOM1_LAT_REG value */
|
||||
unsigned char x2; /* initial PI_BSB_DOM1_PGS_REG value */
|
||||
unsigned char x3; /* initial PI_BSB_DOM1_PWD_REG value */
|
||||
unsigned char x4; /* initial PI_BSB_DOM1_RLS_REG value */
|
||||
|
||||
unsigned long int ClockRate;
|
||||
unsigned long int BootAddress;
|
||||
unsigned long int Release;
|
||||
unsigned long int CRC1;
|
||||
unsigned long int CRC2;
|
||||
unsigned long int Unknown0;
|
||||
unsigned long int Unknown1;
|
||||
char Name[20];
|
||||
unsigned long int Unknown2;
|
||||
unsigned short int Unknown3;
|
||||
unsigned char Unknown4;
|
||||
unsigned char Manufacturer;
|
||||
unsigned short int CartID;
|
||||
char CountryID;
|
||||
unsigned char Unknown5;
|
||||
} n64header_t;
|
||||
|
||||
typedef enum {
|
||||
OS_TV_NTSC = 0,
|
||||
OS_TV_PAL,
|
||||
OS_TV_MPAL
|
||||
} tv_type_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char nCountryID;
|
||||
char szName[15];
|
||||
unsigned long int nTvType;
|
||||
} CountryIDInfo_t;
|
||||
|
||||
#endif
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
lynxit.h - lynxit support for uCON64
|
||||
|
||||
Copyright (c) 1997 - ???? K. Wilkins
|
||||
Copyright (c) 2002 NoisyB <noisyb@gmx.net>
|
||||
|
||||
|
||||
This program 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#ifndef LYNXIT_H
|
||||
#define LYNXIT_H
|
||||
|
||||
extern const st_getopt2_t lynxit_usage[];
|
||||
|
||||
#ifdef USE_PARALLEL
|
||||
extern int lynxit_read_rom (const char *filename, unsigned int parport);
|
||||
#endif
|
||||
|
||||
#endif
|
||||