Compare commits
120 Commits
v0.1.2
...
godzil_dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
82998d7a48 | ||
|
|
32a0a50c54 | ||
|
|
b8d3b952ad | ||
|
|
e97396adc9 | ||
|
|
a72476ea6c | ||
|
|
d47858083a | ||
|
|
a7ac2f8900 | ||
|
|
c80bdfbf59 | ||
|
|
a9ea821c0d | ||
|
|
9baa4b7f9f | ||
|
|
2ef480f751 | ||
|
|
6b3a7eb4ae | ||
|
|
effa2a6972 | ||
|
|
9253cc45b0 | ||
|
|
9fbe61bad1 | ||
|
|
968c347986 | ||
|
|
c231c8b821 | ||
|
|
60d7a08117 | ||
|
|
7df6909266 | ||
|
|
006ea8c44a | ||
|
|
684e2c3b81 | ||
|
|
3af05cef91 | ||
|
|
a083d80ff9 | ||
|
|
8148f5567c | ||
|
|
1a52da6272 | ||
|
|
e33b2b2bc7 | ||
|
|
3530613349 | ||
|
|
0d02bfded7 | ||
|
|
576cedd285 | ||
|
|
e6f77c242b | ||
|
|
86d6f04870 | ||
|
|
e2af175f05 | ||
|
|
583309491c | ||
|
|
40099772f7 | ||
|
|
247e6591c4 | ||
|
|
1b77a6e7fa | ||
|
|
eede8b491b | ||
|
|
350b83e06b | ||
|
|
943a3d14bb | ||
|
|
5eae77f626 | ||
|
|
14a2136be7 | ||
|
|
45b67d0f1a | ||
|
|
e23a76d812 | ||
|
|
f4b8d57810 | ||
|
|
1be6885223 | ||
|
|
2eeaaefcef | ||
|
|
71aef898d2 | ||
|
|
d9e1680800 | ||
|
|
57bb6351e7 | ||
|
|
023901cab2 | ||
|
|
6038d94d0f | ||
|
|
aef19a2576 | ||
|
|
3db272662c | ||
|
|
91458011aa | ||
|
|
c062800386 | ||
|
|
61c7014f85 | ||
|
|
64b1b07333 | ||
|
|
723bf9eb95 | ||
|
|
9c84f01fd5 | ||
|
|
a5a02992e5 | ||
|
|
0f38935981 | ||
|
|
f44de5ba64 | ||
|
|
12deb9a0c7 | ||
|
|
a1ca5f1dad | ||
|
|
ae4af50dac | ||
|
|
034b39588c | ||
|
|
66f26c18b1 | ||
|
|
96e178df2e | ||
|
|
f28516ea1c | ||
|
|
242bde5684 | ||
|
|
8c2f74d8cd | ||
|
|
11bf7ffd5b | ||
|
|
b01388b670 | ||
|
|
1f9dbe7d4c | ||
|
|
798e23ec82 | ||
|
|
f9c8e62f10 | ||
|
|
c07b8f42c2 | ||
|
|
2a1ef40796 | ||
|
|
873bd84cd1 | ||
|
|
36dece67b8 | ||
|
|
de4308e3ba | ||
|
|
6cff0f66e0 | ||
|
|
dc478186e5 | ||
|
|
7109f9e030 | ||
|
|
e63658e2ad | ||
|
|
37a309fd0e | ||
|
|
f5caf21fac | ||
|
|
1b272a7a7d | ||
|
|
812a796568 | ||
|
|
0f3138124e | ||
|
|
ea82765686 | ||
|
|
e85ac8c0be | ||
|
|
ca5cbfd785 | ||
|
|
c9099f0aac | ||
|
|
53d7167630 | ||
|
|
17286a3075 | ||
|
|
7820db7329 | ||
|
|
d88fbb6124 | ||
|
|
424e1642ea | ||
|
|
e3f0e9fcc9 | ||
|
|
40a4979c32 | ||
|
|
d00b072e5f | ||
|
|
3ecf4954a0 | ||
|
|
4904dfe464 | ||
|
|
39f1548dbd | ||
|
|
37f725b5ea | ||
|
|
aabf0557af | ||
|
|
e840524bdd | ||
|
|
4a6b86341e | ||
|
|
d3fc44f93d | ||
|
|
349e209284 | ||
|
|
d0422005d0 | ||
|
|
8e7f77e49b | ||
|
|
e2f33c28c9 | ||
|
|
7eb65e35ce | ||
|
|
8d015f8080 | ||
|
|
8c0ca0ea05 | ||
|
|
f0a2e85c65 | ||
|
|
86a81bfa82 | ||
|
|
cb859f3bfb |
22
.gitignore
vendored
Normal file
22
.gitignore
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
*.cod
|
||||||
|
*.hex
|
||||||
|
*.lst
|
||||||
|
*.o
|
||||||
|
*.diff
|
||||||
|
.DS_Store
|
||||||
|
*.o65
|
||||||
|
*.ips
|
||||||
|
*.bin
|
||||||
|
*.map
|
||||||
|
*.o.d
|
||||||
|
*.log
|
||||||
|
*.smc
|
||||||
|
*.sfc
|
||||||
|
*~
|
||||||
|
*.old
|
||||||
|
*.elf
|
||||||
|
*.img
|
||||||
|
autoconf.h
|
||||||
|
utils/rle
|
||||||
|
utils/derle
|
||||||
|
*.bit
|
||||||
57
CHANGELOG
57
CHANGELOG
@@ -15,6 +15,7 @@ v0.1.1a (bugfix release)
|
|||||||
v0.1.2
|
v0.1.2
|
||||||
======
|
======
|
||||||
|
|
||||||
|
* New menu entry: "System Information"
|
||||||
* Auto region override (eliminate "This game pak is not designed..." messages)
|
* Auto region override (eliminate "This game pak is not designed..." messages)
|
||||||
* Improved mapper detection (fixes Batman vs. Joker and many PD ROMs)
|
* Improved mapper detection (fixes Batman vs. Joker and many PD ROMs)
|
||||||
* Improved data streaming performance
|
* Improved data streaming performance
|
||||||
@@ -22,3 +23,59 @@ v0.1.2
|
|||||||
* A and B buttons swapped in menu to match common key mappings
|
* A and B buttons swapped in menu to match common key mappings
|
||||||
* Fixes:
|
* Fixes:
|
||||||
- MSU1: Stop audio playback on end of audio file
|
- MSU1: Stop audio playback on end of audio file
|
||||||
|
|
||||||
|
|
||||||
|
v0.1.3
|
||||||
|
======
|
||||||
|
|
||||||
|
* Updated logo gfx with new version from klaptra
|
||||||
|
* Updated font to distinguish between 1 and I
|
||||||
|
* Menu layout adjusted to move status line up by 4 scanlines
|
||||||
|
* Run previously loaded game by pressing Start in the menu
|
||||||
|
* Auto-scroll file names that do not fit the screen
|
||||||
|
* SD access time measurement on System Information screen (takes a while!)
|
||||||
|
* Cx4 memory map: mirror ROM to 40-7e/c0-ff (fixes MMX3 Zero patch)
|
||||||
|
* Some FPGA configuration error detection (mainly useful for hardware diag)
|
||||||
|
* Fixes:
|
||||||
|
- FPGA-side SD clock pullup (increases reliability with some cards)
|
||||||
|
|
||||||
|
|
||||||
|
v0.1.4
|
||||||
|
======
|
||||||
|
|
||||||
|
* SPC Player (contributed by necronomfive/blargg)
|
||||||
|
* System Information screen now shows CPU/PPU revision (contributed by necronomfive)
|
||||||
|
* Satellaview: basic data transmission packet support (makes some more games boot, thanks to LuigiBlood for assistance and sample data packets)
|
||||||
|
* Number of supported files increased to 50000 per card / 16380 per directory
|
||||||
|
* Slight speedup of menu text rendering
|
||||||
|
* Reduce load time of menu
|
||||||
|
* Adjust Cx4 timing to be more faithful
|
||||||
|
(Mega Man now defeats the boss in attract mode in Mega Man X2)
|
||||||
|
* adapt ROM mirroring size to file size if header information is invalid
|
||||||
|
(fixes Super Noah's Ark 3D, possibly others)
|
||||||
|
* MSU1 interface changes suggested by byuu:
|
||||||
|
- Data offset 0 and audio track 0 are automatically requested on reset.
|
||||||
|
This causes the busy flags to become 0 shortly after reset/startup.
|
||||||
|
- $2000 bit 3 is now "audio error", becomes valid after "audio busy" -> 0
|
||||||
|
set when an error occurred while preparing playback of the requested audio track
|
||||||
|
* write LED stays on when SRAM content changes constantly
|
||||||
|
* Fixes:
|
||||||
|
- fix empty save files on FAT16 / incorrect free cluster count on FAT32
|
||||||
|
- correct directory sorting (force parent directory at top of list)
|
||||||
|
- fix text corruption when entering a directory with a scrollable name
|
||||||
|
- fix files/dirs count in system information
|
||||||
|
- make 'sd2snes' directory hiding case-insensitive
|
||||||
|
- improve DAC I²S timing
|
||||||
|
- fix occasional palette corruption in menu
|
||||||
|
- fix SD clock glitch on ROM loading (occasional glitches/crashes)
|
||||||
|
- fix memory write timing on ROM loading (occasional glitches/crashes)
|
||||||
|
- fix SPI timing (ROMs not loading; System Information not working)
|
||||||
|
- properly synchronize SNES control signals (occasional glitches/crashes)
|
||||||
|
- fix floating IRQ output (occasional glitches/slowdowns)
|
||||||
|
|
||||||
|
|
||||||
|
v0.1.4a (bugfix release)
|
||||||
|
========================
|
||||||
|
|
||||||
|
* Fix DMA initialization in the menu (could cause sprite corruption in some games)
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
The development branch was switched over from 'master' to 'develop'.
|
|
||||||
The master stream will be used for releases.
|
|
||||||
BIN
bin/bsxpage.bin
Normal file
BIN
bin/bsxpage.bin
Normal file
Binary file not shown.
6
cic/d411-seeds.txt
Normal file
6
cic/d411-seeds.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
key seed: b14f4b57fd61e98
|
||||||
|
110101111101010
|
||||||
|
|
||||||
|
lck seed: _9a185f11e10dec
|
||||||
|
_10101111010100
|
||||||
|
|
||||||
230
cic/d411.pseudo
Normal file
230
cic/d411.pseudo
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
map:
|
||||||
|
|
||||||
|
RAM:0x01~0x0f Seed 1 (own key seed)?
|
||||||
|
RAM:0x10 send/receive buffer?
|
||||||
|
RAM:0x11 Stream ID received from LOCK
|
||||||
|
RAM:0x12~0x1f Seed 2 (Stream ID part of lock seed)?
|
||||||
|
|
||||||
|
main:
|
||||||
|
goto initstream;
|
||||||
|
|
||||||
|
mainloop:
|
||||||
|
a=0x1;
|
||||||
|
mainloop2:
|
||||||
|
x=a;
|
||||||
|
for(x=a; x<16; x++) {
|
||||||
|
main_inner1:
|
||||||
|
bm=0x0;
|
||||||
|
call 34b(0x00+x) // prepare next stream bit (send)
|
||||||
|
bm=0x1;
|
||||||
|
call 34b(0x10+x) // prepare next stream bit (recv)
|
||||||
|
call 131 // bm=1; bl=0; a=P0
|
||||||
|
a=P0;
|
||||||
|
if(P0.0) die; // WTF? P0.0 is an output!
|
||||||
|
if(P0.1) die;
|
||||||
|
|
||||||
|
a=0x0;
|
||||||
|
a<->RAM[0x10]; // load A with next output stream bit (nibble)
|
||||||
|
P0=a; // LSB -> Key output
|
||||||
|
nop; // wait
|
||||||
|
a=P0; // read from lock
|
||||||
|
P0=0; // clear output port
|
||||||
|
RAM[0x10]=a; // store next input stream bit in RAM
|
||||||
|
bl=3; a=P3 // P3.0, which is usually UNCONNECTED,
|
||||||
|
// somehow determines how to deal with
|
||||||
|
// the input stream. This is SNES CIC specific.
|
||||||
|
// NOTE: For commonly used key operation / pin mapping we must assume
|
||||||
|
// that P3.0 is HIGH (1). (otherwise the key would die immediately)
|
||||||
|
bl=0
|
||||||
|
if(P3.0){
|
||||||
|
if(RAM[0x10].1) { // input stream bit set?
|
||||||
|
call 159 // bm=0; bl=0; a=P0 // switch "bank"
|
||||||
|
if(RAM[0x00].0) { // matches calculated bit?
|
||||||
|
goto 13d // then go on
|
||||||
|
} else goto 157 // DIE // else gtfo
|
||||||
|
} else goto input_stream_bit_clear // input stream bit clear, check
|
||||||
|
} else goto 175
|
||||||
|
|
||||||
|
input_stream_bit_clear: // input stream bit cleared
|
||||||
|
call 159 // bm=0; bl=0; a=P0 // switch "bank"
|
||||||
|
if(RAM[0x00].0) { // calculated bit doesn't match?
|
||||||
|
goto 157 // DIE // then die
|
||||||
|
} else goto 17a // nop; goto 13d // else go on
|
||||||
|
|
||||||
|
175:
|
||||||
|
if(RAM[0x10].0) { // this is essentially the same
|
||||||
|
call 159 // bm=0; bl=0; a=P0 // as above but
|
||||||
|
if(RAM[0x00].1) { // input stream bit is set in
|
||||||
|
goto 13d; // RAM[0x10].0 instead of .1 and
|
||||||
|
} else goto 157 // DIE // calculated from RAM[0x00].1
|
||||||
|
} else { // instead of .0, if P3.0 is 0.
|
||||||
|
call 159 // bm=0; bl=0; a=P0
|
||||||
|
if(RAM[0x00].1) {
|
||||||
|
goto 157 // DIE
|
||||||
|
} else goto 17a // nop; goto 13d
|
||||||
|
}
|
||||||
|
|
||||||
|
13d: // continue
|
||||||
|
a=x;
|
||||||
|
a++; // loop to next of 15 stream
|
||||||
|
if(!overflow) { // bits, afterwards:
|
||||||
|
x=a;
|
||||||
|
goto main_inner1;
|
||||||
|
}
|
||||||
|
} // for x=1 to 15
|
||||||
|
(x=0) //
|
||||||
|
call 04a // set Resets (dummy for key mode) // output reset levels
|
||||||
|
call 370 // "MANGLE BOTH" // calculate new seeds
|
||||||
|
call 370 // "MANGLE BOTH" // for both sides
|
||||||
|
call 370 // "MANGLE BOTH" // (lock+key) to exchange
|
||||||
|
// this is "SNES security": MANGLE is called THREE TIMES!
|
||||||
|
// as opposed to only once on the NES CICs.
|
||||||
|
a=RAM[0x13];
|
||||||
|
RAM[0x13]=RAM[0x17];
|
||||||
|
// set P3.0 to LSB of RAM[0x13]
|
||||||
|
P3 = (P3 & 0xe) | (RAM[0x13] & 0x1);
|
||||||
|
if(a.0==1) {
|
||||||
|
goto mainloop (seed offset=0x1)
|
||||||
|
} else goto mainloop2 (seed offset=a)
|
||||||
|
|
||||||
|
|
||||||
|
04a: // "RUN HOST"
|
||||||
|
call 37a // "skip if lock"
|
||||||
|
a=0x0;
|
||||||
|
P1=a;
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
P1=a;
|
||||||
|
return
|
||||||
|
|
||||||
|
mangle_both:
|
||||||
|
call mangle(bm=0);
|
||||||
|
goto mangle(bm=1);
|
||||||
|
|
||||||
|
mangle:
|
||||||
|
bl=0xf;
|
||||||
|
a=RAM[bm:0xf];
|
||||||
|
x=a;
|
||||||
|
carry=1;
|
||||||
|
bl=0x1;
|
||||||
|
a+=RAM[bm:0x1]+1;
|
||||||
|
RAM[bm:0x1]=a;
|
||||||
|
==> RAM[bm:0x1]+=RAM[bm:0xf]+1;
|
||||||
|
a=RAM[bm:0x1]; bl++;
|
||||||
|
a+=RAM[bm:0x2]+1;
|
||||||
|
a=~a;
|
||||||
|
RAM[bm:0x2]=a; bl++;
|
||||||
|
a+=RAM[bm:0x3]+1;
|
||||||
|
if(!overflow) {
|
||||||
|
RAM[bm:0x3]=a; bl++;
|
||||||
|
}
|
||||||
|
a+=RAM[bm:0x4];
|
||||||
|
RAM[bm:0x4]=a;
|
||||||
|
a=RAM[bm:0x4]; bl++;
|
||||||
|
carry=0;
|
||||||
|
a+=RAM[bm:0x5]+0;
|
||||||
|
RAM[bm:0x5]=a; bl++;
|
||||||
|
a+=8;
|
||||||
|
a+=RAM[bm:0x6]+0;
|
||||||
|
RAM[bm:0x6]=a; bl++;
|
||||||
|
mangle_inner1:
|
||||||
|
a++;
|
||||||
|
nop
|
||||||
|
a+=RAM[bm:0x7..0xf]+0;
|
||||||
|
RAM[bm:0x7..0xf]=a;
|
||||||
|
a=RAM[bm:0x7..0xf]; bl++;
|
||||||
|
if(!overflow) goto mangle_inner1
|
||||||
|
a<->x;
|
||||||
|
a+=0xf;
|
||||||
|
if(!overflow) return;
|
||||||
|
goto mangle
|
||||||
|
|
||||||
|
131:
|
||||||
|
bm=0x0;
|
||||||
|
call 37a
|
||||||
|
(if(!lock)bm=1);
|
||||||
|
return;
|
||||||
|
|
||||||
|
37a:
|
||||||
|
|
||||||
|
34b: input x='bl'
|
||||||
|
// take a nibble out of the seed (indexed by bm:x)
|
||||||
|
// and set [bm:0], i.e. RAM[0x00] or RAM[0x10] like this:
|
||||||
|
// if(seednibble&1) {
|
||||||
|
// result=0b0000;
|
||||||
|
// } else {
|
||||||
|
// if(P3.0) {
|
||||||
|
// result=0b0101;
|
||||||
|
// } else {
|
||||||
|
// result=0b0010;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
bl=x;
|
||||||
|
a=RAM[bm:x];
|
||||||
|
RAM[bm:0] = RAM[bm:x].0 ? 0x7 : 0x0;
|
||||||
|
|
||||||
|
a=P3; // WTF is P3????
|
||||||
|
bl=0;
|
||||||
|
if (P3.0==1) {
|
||||||
|
RAM[bm:0] &= 0b1101;
|
||||||
|
} else {
|
||||||
|
RAM[bm:0] &= 0b1010;
|
||||||
|
}
|
||||||
|
return
|
||||||
|
|
||||||
|
initstream:
|
||||||
|
if(P0.3==0) {
|
||||||
|
if(P0.3==0) {
|
||||||
|
A=RAM[0x11]; RAM[0x11]=0xf
|
||||||
|
input_stream_id_bit;
|
||||||
|
if !(A.1) RAM[0x11]&=0b0111
|
||||||
|
input_stream_id_bit;
|
||||||
|
if !(A.1) RAM[0x11]&=0b1110
|
||||||
|
input_stream_id_bit;
|
||||||
|
if !(A.1) RAM[0x11]&=0b1101
|
||||||
|
input_stream_id_bit;
|
||||||
|
if !(A.1) RAM[0x11]&=0b1011
|
||||||
|
nop
|
||||||
|
|
||||||
|
RAM[0x01]=0xb;
|
||||||
|
RAM[0x02]=0x1;
|
||||||
|
RAM[0x03]=0x4;
|
||||||
|
RAM[0x04]=0xf;
|
||||||
|
RAM[0x05]=0x4;
|
||||||
|
RAM[0x06]=0xb; // 0x6????
|
||||||
|
RAM[0x07]=0x5;
|
||||||
|
RAM[0x08]=0x7; // 0x8????
|
||||||
|
RAM[0x09]=0xf;
|
||||||
|
RAM[0x0a]=0xd; // 0xa????
|
||||||
|
RAM[0x0b]=0x6;
|
||||||
|
RAM[0x0c]=0x1; // 0xc????
|
||||||
|
RAM[0x0d]=0xe;
|
||||||
|
RAM[0x0e]=0x9;
|
||||||
|
RAM[0x0f]=0x8;
|
||||||
|
|
||||||
|
RAM[0x12]=0x9;
|
||||||
|
RAM[0x13]=0xa;
|
||||||
|
RAM[0x14]=0x1;
|
||||||
|
RAM[0x15]=0x8;
|
||||||
|
RAM[0x16]=0x5;
|
||||||
|
RAM[0x17]=0xf; // 0x7????
|
||||||
|
RAM[0x18]=0x1;
|
||||||
|
RAM[0x19]=0x1; // 0x9????
|
||||||
|
RAM[0x1a]=0xe;
|
||||||
|
RAM[0x1b]=0x1; // 0xb????
|
||||||
|
RAM[0x1c]=0x0;
|
||||||
|
RAM[0x1d]=0xd;
|
||||||
|
RAM[0x1e]=0xe;
|
||||||
|
RAM[0x1f]=0xc;
|
||||||
|
|
||||||
|
mainloop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
input_stream_id_bit:
|
||||||
|
wait 6 cycles
|
||||||
|
A=P0
|
||||||
|
ret
|
||||||
101
cic/mangle.c
Normal file
101
cic/mangle.c
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
void printseed(unsigned char* data) {
|
||||||
|
int i;
|
||||||
|
for(i=1;i<16;i++) {
|
||||||
|
printf("%x ", data[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void printstream(unsigned char* data, int restart) {
|
||||||
|
int i;
|
||||||
|
for(i=restart;i<16;i++) {
|
||||||
|
printf("%d ", data[i]&1);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
#define CARRY if(a>0x0f) {\
|
||||||
|
a &= 0xf;\
|
||||||
|
carry=1;\
|
||||||
|
} else carry=0;
|
||||||
|
|
||||||
|
void mangle(unsigned char* data) {
|
||||||
|
unsigned char a,x,temp,i,offset,carry=0;
|
||||||
|
a=data[0xf];
|
||||||
|
do {
|
||||||
|
x=a;
|
||||||
|
offset=1;
|
||||||
|
carry=1;
|
||||||
|
a+=data[offset]+carry;
|
||||||
|
data[offset]=a&0xf;
|
||||||
|
a=data[offset++];
|
||||||
|
a+=data[offset]+carry;
|
||||||
|
a=(~a)&0xf;
|
||||||
|
temp=a; a=data[offset]; data[offset++]=temp&0xf;
|
||||||
|
a+=data[offset]+carry;
|
||||||
|
if(a<0x10) {
|
||||||
|
temp=a; a=data[offset]; data[offset++]=temp&0xf;
|
||||||
|
}
|
||||||
|
a+=data[offset];
|
||||||
|
data[offset]=a&0xf;
|
||||||
|
a=data[offset++];
|
||||||
|
carry=0;
|
||||||
|
a+=data[offset]+carry;
|
||||||
|
temp=a; a=data[offset]; data[offset++]=temp&0xf;
|
||||||
|
a+=8;
|
||||||
|
if(a<0x10) {
|
||||||
|
a+=data[offset]+carry;
|
||||||
|
}
|
||||||
|
temp=a; a=data[offset]; data[offset++]=temp&0xf;
|
||||||
|
|
||||||
|
while(offset<0x10) {
|
||||||
|
a++;
|
||||||
|
a+=data[offset]+carry;
|
||||||
|
data[offset]=a&0xf;
|
||||||
|
a=data[offset++];
|
||||||
|
}
|
||||||
|
offset &= 0xf;
|
||||||
|
a=x;
|
||||||
|
a+=0xf;
|
||||||
|
CARRY;
|
||||||
|
} while(carry);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
unsigned char restart=1;
|
||||||
|
unsigned char keyseed[16]= {0x0, // dummy
|
||||||
|
0xb,0x1,0x4,0xf,
|
||||||
|
0x4,0xb,0x5,0x7,
|
||||||
|
0xf,0xd,0x6,0x1,
|
||||||
|
0xe,0x9,0x8};
|
||||||
|
unsigned char lockseed[16]={0x0, // dummy
|
||||||
|
0x0,0x9,0xa,0x1,
|
||||||
|
0x8,0x5,0xf,0x1,
|
||||||
|
0x1,0xe,0x1,0x0,
|
||||||
|
0xd,0xe,0xc};
|
||||||
|
|
||||||
|
printseed(keyseed);
|
||||||
|
printseed(lockseed);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
printf("\n");
|
||||||
|
printstream(keyseed, restart);
|
||||||
|
printstream(lockseed, restart);
|
||||||
|
mangle(keyseed);
|
||||||
|
mangle(keyseed);
|
||||||
|
mangle(keyseed);
|
||||||
|
mangle(lockseed);
|
||||||
|
mangle(lockseed);
|
||||||
|
mangle(lockseed);
|
||||||
|
|
||||||
|
// printseed(keyseed);
|
||||||
|
// printseed(lockseed);
|
||||||
|
restart=lockseed[7];
|
||||||
|
// lockseed[3]=lockseed[7];
|
||||||
|
if(!restart)restart=1;
|
||||||
|
// printf("send %d-15\n", restart);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
70
cic/scramble.txt
Normal file
70
cic/scramble.txt
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
start:
|
||||||
|
b14f4b57fd61e98
|
||||||
|
4953771997e11b4
|
||||||
|
BL=f
|
||||||
|
A=[f]=8
|
||||||
|
X=A
|
||||||
|
C=1
|
||||||
|
BL=1
|
||||||
|
A+=[1]+1 = 8+b+1 = 4 C=1
|
||||||
|
store [1]=4
|
||||||
|
A=[1]=4 BL=2
|
||||||
|
A+=[2]+1 = 4+1+1 = 6 C=0
|
||||||
|
A=~A = 9
|
||||||
|
A=[2] = 1
|
||||||
|
store [2]=9 BL=3
|
||||||
|
A+=[3]+0 = 4+1+0 = 5 C=0; no skip
|
||||||
|
A=[3] = 4
|
||||||
|
store [3]=5 BL=4
|
||||||
|
A+=[4] = 4+f = 3 C=1
|
||||||
|
store [4]=3
|
||||||
|
A=[4] = 3 BL=5
|
||||||
|
C=0
|
||||||
|
A+=[5]+1 = 3+4+0 = 7 C=0
|
||||||
|
A=[5] = 4
|
||||||
|
store [5]=7 BL=6
|
||||||
|
A+=8 = 4+8 = c C=0
|
||||||
|
A+=[6]+0 = b+c+0 = 7 C=1
|
||||||
|
A=[6] = b
|
||||||
|
store [6]=7 BL=7
|
||||||
|
|
||||||
|
A+=1 = b+1 = c C=0
|
||||||
|
A+=[7]+0 = c+5+0 = 1 C=1
|
||||||
|
store [7] = 1
|
||||||
|
A=[7] = 1 BL=8
|
||||||
|
A+=1 = 1+1 = 2 C=0
|
||||||
|
A+=[8]+0 = 2+7+0 = 9 C=0
|
||||||
|
store [8] = 9
|
||||||
|
A=[8] = 9 BL=9
|
||||||
|
A+=1 = 9+1 = a C=0
|
||||||
|
A+=[9]+0 = a+f+0 = 9 C=1
|
||||||
|
store [9] = 9
|
||||||
|
A=[9] = 9 BL=a
|
||||||
|
A+=1 = 9+1 = a C=0
|
||||||
|
A+=[a]+0 = a+d+0 = 7 C=1
|
||||||
|
store [a] = 7
|
||||||
|
A=[a] = 7 BL=b
|
||||||
|
A+=1 = 7+1 = 8 C=0
|
||||||
|
A+=[b]+0 = 8+6+0 = e C=0
|
||||||
|
store [b] = e
|
||||||
|
A=[b] = e BL=c
|
||||||
|
A+=1 = e+1 = f C=0
|
||||||
|
A+=[c]+0 = f+1+0 = 0 C=1
|
||||||
|
store [c] = 0
|
||||||
|
A=[c] = 0 BL=d
|
||||||
|
A+=1 = 0+1 = 1 C=0
|
||||||
|
A+=[d]+0 = 1+e+0 = f C=0
|
||||||
|
store [d] = f
|
||||||
|
A=[d] = f BL=e
|
||||||
|
A+=1 = f+1 = 0 C=1
|
||||||
|
A+=[e]+1 = 0+9+1 = a C=0
|
||||||
|
store [e] = a
|
||||||
|
A=[e] = a BL=f
|
||||||
|
A+=1 = a+1 = b C=0
|
||||||
|
A+=[f]+0 = b+8+0 = 3 C=1
|
||||||
|
store [f] = 3
|
||||||
|
A=[f] = 3 BL=0; skip
|
||||||
|
A=X=8
|
||||||
|
A+=f = 8+f = 7 C=1; skip
|
||||||
|
noooo, all the shit again
|
||||||
|
|
||||||
697
cic/snescic-key.asm
Normal file
697
cic/snescic-key.asm
Normal file
@@ -0,0 +1,697 @@
|
|||||||
|
#include <p12f629.inc>
|
||||||
|
processor p12f629
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------
|
||||||
|
; SNES CIC clone for PIC Microcontroller (key mode only)
|
||||||
|
;
|
||||||
|
; Copyright (C) 2010 by Maximilian Rehkopf (ikari_01) <otakon@gmx.net>
|
||||||
|
; This software is part of the sd2snes project.
|
||||||
|
;
|
||||||
|
; 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; version 2 of the License only.
|
||||||
|
;
|
||||||
|
; 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
;
|
||||||
|
; ---------------------------------------------------------------------
|
||||||
|
;
|
||||||
|
; pin configuration: (cartridge pin) [key CIC pin]
|
||||||
|
;
|
||||||
|
; ,---_---.
|
||||||
|
; +5V (27,58) [16] |1 8| GND (5,36) [8]
|
||||||
|
; CIC clk (56) [6] |2 7| CIC data i/o 0 (55) [2]
|
||||||
|
; status out |3 6| CIC data i/o 1 (24) [1]
|
||||||
|
; nc |4 5| CIC slave reset (25) [7]
|
||||||
|
; `-------'
|
||||||
|
;
|
||||||
|
;
|
||||||
|
; Status out can be connected to a LED. It indicates:
|
||||||
|
;
|
||||||
|
; state | output
|
||||||
|
; -------------------------+--------------------
|
||||||
|
; OK (normal operation) | high
|
||||||
|
; error (unlock failed) | alternating @~2.5Hz
|
||||||
|
; no CIC (modded SNES) | low
|
||||||
|
;
|
||||||
|
; In case lockout fails, the region is switched automatically and
|
||||||
|
; will be used after the next reset.
|
||||||
|
;
|
||||||
|
; memory usage:
|
||||||
|
;
|
||||||
|
; 0x20 buffer for seed calc and transfer
|
||||||
|
; 0x21 - 0x2f seed area (lock seed)
|
||||||
|
; 0x30 buffer for seed calc
|
||||||
|
; 0x31 - 0x3f seed area (key seed; 0x31 filled in by lock)
|
||||||
|
; 0x40 - 0x41 buffer for seed calc
|
||||||
|
; 0x4d buffer for eeprom access
|
||||||
|
; 0x4e loop variable for longwait
|
||||||
|
; 0x4f loop variable for wait
|
||||||
|
;
|
||||||
|
; ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
; -----------------------------------------------------------------------
|
||||||
|
__CONFIG _EC_OSC & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _CPD_OFF
|
||||||
|
|
||||||
|
; -----------------------------------------------------------------------
|
||||||
|
; code memory
|
||||||
|
org 0x0000
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
goto init
|
||||||
|
isr
|
||||||
|
org 0x0004
|
||||||
|
bcf INTCON, 1 ; clear interrupt cause
|
||||||
|
bcf GPIO, 0
|
||||||
|
bcf GPIO, 1
|
||||||
|
bsf GPIO, 4 ; LED on
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
bsf INTCON, 7 ; re-enable interrupts (ISR will continue as main)
|
||||||
|
goto main
|
||||||
|
init
|
||||||
|
org 0x0010
|
||||||
|
banksel GPIO
|
||||||
|
clrf GPIO
|
||||||
|
movlw 0x07 ; GPIO2..0 are digital I/O (not connected to comparator)
|
||||||
|
movwf CMCON
|
||||||
|
movlw 0x90 ; global enable interrupts + enable external interrupt
|
||||||
|
movwf INTCON
|
||||||
|
banksel TRISIO
|
||||||
|
movlw 0x2d ; in out in in out in
|
||||||
|
movwf TRISIO
|
||||||
|
movlw 0x24 ; pullups for reset+clk to avoid errors when no CIC in host
|
||||||
|
movwf WPU
|
||||||
|
movlw 0x00 ; 0x80 for global pullup disable
|
||||||
|
movwf OPTION_REG
|
||||||
|
|
||||||
|
banksel GPIO
|
||||||
|
bcf GPIO, 4 ; LED off
|
||||||
|
idle
|
||||||
|
goto idle ; wait for interrupt from lock
|
||||||
|
|
||||||
|
main
|
||||||
|
banksel TRISIO
|
||||||
|
bsf TRISIO, 0
|
||||||
|
bcf TRISIO, 1
|
||||||
|
banksel GPIO
|
||||||
|
; --------INIT LOCK SEED (what the lock sends)--------
|
||||||
|
movlw 0xb
|
||||||
|
movwf 0x21
|
||||||
|
movlw 0x1
|
||||||
|
movwf 0x22
|
||||||
|
movlw 0x4
|
||||||
|
movwf 0x23
|
||||||
|
movlw 0xf
|
||||||
|
movwf 0x24
|
||||||
|
movlw 0x4
|
||||||
|
movwf 0x25
|
||||||
|
movlw 0xb
|
||||||
|
movwf 0x26
|
||||||
|
movlw 0x5
|
||||||
|
movwf 0x27
|
||||||
|
movlw 0x7
|
||||||
|
movwf 0x28
|
||||||
|
movlw 0xf
|
||||||
|
movwf 0x29
|
||||||
|
movlw 0xd
|
||||||
|
movwf 0x2a
|
||||||
|
movlw 0x6
|
||||||
|
movwf 0x2b
|
||||||
|
movlw 0x1
|
||||||
|
movwf 0x2c
|
||||||
|
movlw 0xe
|
||||||
|
movwf 0x2d
|
||||||
|
movlw 0x9
|
||||||
|
movwf 0x2e
|
||||||
|
movlw 0x8
|
||||||
|
movwf 0x2f
|
||||||
|
|
||||||
|
; --------INIT KEY SEED (what we must send)--------
|
||||||
|
banksel EEADR ; D/F411 and D/F413
|
||||||
|
clrf EEADR ; differ in 2nd seed nibble
|
||||||
|
bsf EECON1, RD ; of key stream,
|
||||||
|
movf EEDAT, w ; restore saved nibble from EEPROM
|
||||||
|
banksel GPIO
|
||||||
|
movwf 0x32
|
||||||
|
movlw 0xa
|
||||||
|
movwf 0x33
|
||||||
|
movlw 0x1
|
||||||
|
movwf 0x34
|
||||||
|
movlw 0x8
|
||||||
|
movwf 0x35
|
||||||
|
movlw 0x5
|
||||||
|
movwf 0x36
|
||||||
|
movlw 0xf
|
||||||
|
movwf 0x37
|
||||||
|
movlw 0x1
|
||||||
|
movwf 0x38
|
||||||
|
movwf 0x39
|
||||||
|
movlw 0xe
|
||||||
|
movwf 0x3a
|
||||||
|
movlw 0x1
|
||||||
|
movwf 0x3b
|
||||||
|
movlw 0x0
|
||||||
|
movwf 0x3c
|
||||||
|
movlw 0xd
|
||||||
|
movwf 0x3d
|
||||||
|
movlw 0xe
|
||||||
|
movwf 0x3e
|
||||||
|
movlw 0xc
|
||||||
|
movwf 0x3f
|
||||||
|
|
||||||
|
; --------wait for stream ID--------
|
||||||
|
movlw 0xb5
|
||||||
|
call wait
|
||||||
|
clrf 0x31 ; clear lock stream ID
|
||||||
|
|
||||||
|
; --------lock sends stream ID. 15 cycles per bit--------
|
||||||
|
; bsf GPIO, 0 ; (debug marker)
|
||||||
|
; bcf GPIO, 0 ;
|
||||||
|
btfsc GPIO, 0 ; check stream ID bit
|
||||||
|
bsf 0x31, 3 ; copy to lock seed
|
||||||
|
movlw 0x2 ; wait=3*W+5
|
||||||
|
call wait ; burn 11 cycles
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
|
||||||
|
; bsf GPIO, 0
|
||||||
|
; bcf GPIO, 0
|
||||||
|
btfsc GPIO, 0 ; check stream ID bit
|
||||||
|
bsf 0x31, 0 ; copy to lock seed
|
||||||
|
movlw 0x2 ;
|
||||||
|
call wait ; burn 11 cycles
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
|
||||||
|
; bsf GPIO, 0
|
||||||
|
; bcf GPIO, 0
|
||||||
|
btfsc GPIO, 0 ; check stream ID bit
|
||||||
|
bsf 0x31, 1 ; copy to lock seed
|
||||||
|
movlw 0x2 ;
|
||||||
|
call wait ; burn 11 cycles
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
|
||||||
|
; bsf GPIO, 0
|
||||||
|
; bcf GPIO, 0
|
||||||
|
btfsc GPIO, 0 ; check stream ID bit
|
||||||
|
bsf 0x31, 2 ; copy to lock seed
|
||||||
|
banksel TRISIO
|
||||||
|
bcf TRISIO, 0
|
||||||
|
bsf TRISIO, 1
|
||||||
|
banksel GPIO
|
||||||
|
nop
|
||||||
|
movlw 0x27 ; "wait" 1
|
||||||
|
call wait ; wait 121
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
; --------main loop--------
|
||||||
|
loop
|
||||||
|
movlw 0x1
|
||||||
|
loop0
|
||||||
|
addlw 0x30 ; key stream
|
||||||
|
movwf FSR ; store in index reg
|
||||||
|
loop1
|
||||||
|
movf INDF, w ; load seed value
|
||||||
|
movwf 0x20
|
||||||
|
bcf 0x20, 1 ; clear bit 1
|
||||||
|
btfsc 0x20, 0 ; copy from bit 0
|
||||||
|
bsf 0x20, 1 ; (if set)
|
||||||
|
bsf 0x20, 4 ; LED on
|
||||||
|
movf 0x20, w
|
||||||
|
movwf GPIO
|
||||||
|
nop
|
||||||
|
movlw 0x10
|
||||||
|
movwf GPIO ; reset GPIO
|
||||||
|
movlw 0x16
|
||||||
|
call wait
|
||||||
|
nop
|
||||||
|
btfsc GPIO, 0 ; both pins must be low...
|
||||||
|
goto die
|
||||||
|
btfsc GPIO, 1 ; ...when no bit transfer takes place
|
||||||
|
goto die ; if not -> lock cic error state -> die
|
||||||
|
incf FSR, f ; next one
|
||||||
|
movlw 0xf
|
||||||
|
andwf FSR, w
|
||||||
|
btfss STATUS, Z
|
||||||
|
goto loop1
|
||||||
|
movlw 0x2 ; wait 10
|
||||||
|
call wait ;
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
call mangle
|
||||||
|
call mangle
|
||||||
|
call mangle
|
||||||
|
btfsc 0x37, 0
|
||||||
|
goto swap
|
||||||
|
banksel TRISIO
|
||||||
|
bcf TRISIO, 0
|
||||||
|
bsf TRISIO, 1
|
||||||
|
goto swapskip
|
||||||
|
swap
|
||||||
|
banksel TRISIO
|
||||||
|
bsf TRISIO, 0
|
||||||
|
bcf TRISIO, 1
|
||||||
|
nop
|
||||||
|
swapskip
|
||||||
|
banksel GPIO
|
||||||
|
movf 0x37, w
|
||||||
|
andlw 0xf
|
||||||
|
btfss STATUS, Z
|
||||||
|
goto loop0
|
||||||
|
goto loop
|
||||||
|
|
||||||
|
; --------calculate new seeds--------
|
||||||
|
; had to be unrolled because PIC has an inefficient way of handling
|
||||||
|
; indirect access, no post increment, etc.
|
||||||
|
mangle
|
||||||
|
call mangle_lock
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
mangle_key
|
||||||
|
movf 0x2f, w
|
||||||
|
movwf 0x20
|
||||||
|
mangle_key_loop
|
||||||
|
addlw 0x1
|
||||||
|
addwf 0x21, f
|
||||||
|
movf 0x22, w
|
||||||
|
movwf 0x40
|
||||||
|
movf 0x21, w
|
||||||
|
addwf 0x22, f
|
||||||
|
incf 0x22, f
|
||||||
|
comf 0x22, f
|
||||||
|
movf 0x23, w
|
||||||
|
movwf 0x41 ; store 23 to 41
|
||||||
|
movlw 0xf
|
||||||
|
andwf 0x23, f
|
||||||
|
movf 0x40, w ; add 40(22 old)+23+#1 and skip if carry
|
||||||
|
andlw 0xf
|
||||||
|
addwf 0x23, f
|
||||||
|
incf 0x23, f
|
||||||
|
btfsc 0x23, 4
|
||||||
|
goto mangle_key_withskip
|
||||||
|
mangle_key_withoutskip
|
||||||
|
movf 0x41, w ; restore 23
|
||||||
|
addwf 0x24, f ; add to 24
|
||||||
|
movf 0x25, w
|
||||||
|
movwf 0x40 ; save 25 to 40
|
||||||
|
movf 0x24, w
|
||||||
|
addwf 0x25, f
|
||||||
|
movf 0x26, w
|
||||||
|
movwf 0x41 ; save 26 to 41
|
||||||
|
movf 0x40, w ; restore 25
|
||||||
|
andlw 0xf ; mask nibble
|
||||||
|
addlw 0x8 ; add #8 to HIGH nibble
|
||||||
|
movwf 0x40
|
||||||
|
btfss 0x40, 4 ; skip if carry to 5th bit
|
||||||
|
addwf 0x26, w
|
||||||
|
movwf 0x26
|
||||||
|
|
||||||
|
movf 0x41, w ; restore 26
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x27, f ; add to 27
|
||||||
|
|
||||||
|
movf 0x27, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x28, f ; add to 28
|
||||||
|
|
||||||
|
movf 0x28, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x29, f ; add to 29
|
||||||
|
|
||||||
|
movf 0x29, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2a, f ; add to 2a
|
||||||
|
|
||||||
|
movf 0x2a, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2b, f ; add to 2b
|
||||||
|
|
||||||
|
movf 0x2b, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2c, f ; add to 2c
|
||||||
|
|
||||||
|
movf 0x2c, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2d, f ; add to 2d
|
||||||
|
|
||||||
|
movf 0x2d, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2e, f ; add to 2e
|
||||||
|
|
||||||
|
movf 0x2e, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2f, f ; add to 2f
|
||||||
|
|
||||||
|
movf 0x20, w ; restore original 0xf
|
||||||
|
andlw 0xf
|
||||||
|
addlw 0xf
|
||||||
|
movwf 0x20
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
btfss 0x20, 4 ; skip if half-byte carry
|
||||||
|
goto mangle_return ; +2 cycles in return
|
||||||
|
nop
|
||||||
|
goto mangle_key_loop
|
||||||
|
; 69 when goto, 69 when return
|
||||||
|
; CIC has 78 -> 9 nops
|
||||||
|
|
||||||
|
mangle_key_withskip
|
||||||
|
movf 0x41, w ; restore 23
|
||||||
|
addwf 0x23, f ; add to 23
|
||||||
|
movf 0x24, w
|
||||||
|
movwf 0x40 ; save 24 to 40
|
||||||
|
movf 0x23, w
|
||||||
|
addwf 0x24, f
|
||||||
|
movf 0x25, w
|
||||||
|
movwf 0x41 ; save 25 to 41
|
||||||
|
movf 0x40, w ; restore 24
|
||||||
|
andlw 0xf ; mask nibble
|
||||||
|
addlw 0x8 ; add #8 to HIGH nibble
|
||||||
|
movwf 0x40
|
||||||
|
btfss 0x40, 4 ; skip if carry to 5th bit
|
||||||
|
addwf 0x25, w
|
||||||
|
movwf 0x25
|
||||||
|
|
||||||
|
movf 0x41, w ; restore 25
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x26, f ; add to 26
|
||||||
|
|
||||||
|
movf 0x26, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x27, f ; add to 27
|
||||||
|
|
||||||
|
movf 0x27, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x28, f ; add to 28
|
||||||
|
|
||||||
|
movf 0x28, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x29, f ; add to 29
|
||||||
|
|
||||||
|
movf 0x29, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2a, f ; add to 2a
|
||||||
|
|
||||||
|
movf 0x2a, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2b, f ; add to 2b
|
||||||
|
|
||||||
|
movf 0x2b, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2c, f ; add to 2c
|
||||||
|
|
||||||
|
movf 0x2c, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2d, f ; add to 2d
|
||||||
|
|
||||||
|
movf 0x2d, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2e, f ; add to 2e
|
||||||
|
|
||||||
|
movf 0x2e, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2f, f ; add to 2f
|
||||||
|
|
||||||
|
movf 0x20, w ; restore original 0xf
|
||||||
|
andlw 0xf
|
||||||
|
addlw 0xf
|
||||||
|
movwf 0x20
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
btfss 0x20, 4 ; skip if half-byte carry
|
||||||
|
goto mangle_return ; +2 cycles in return
|
||||||
|
nop
|
||||||
|
goto mangle_key_loop
|
||||||
|
mangle_return
|
||||||
|
return
|
||||||
|
; 73 when goto, 73 when return
|
||||||
|
; CIC has 84 -> 11 nops
|
||||||
|
|
||||||
|
mangle_lock
|
||||||
|
movf 0x3f, w
|
||||||
|
movwf 0x30
|
||||||
|
mangle_lock_loop
|
||||||
|
addlw 0x1
|
||||||
|
addwf 0x31, f
|
||||||
|
movf 0x32, w
|
||||||
|
movwf 0x40
|
||||||
|
movf 0x31, w
|
||||||
|
addwf 0x32, f
|
||||||
|
incf 0x32, f
|
||||||
|
comf 0x32, f
|
||||||
|
movf 0x33, w
|
||||||
|
movwf 0x41 ; store 33 to 41
|
||||||
|
movlw 0xf
|
||||||
|
andwf 0x33, f
|
||||||
|
movf 0x40, w ; add 40(32 old)+33+#1 and skip if carry
|
||||||
|
andlw 0xf
|
||||||
|
addwf 0x33, f
|
||||||
|
incf 0x33, f
|
||||||
|
btfsc 0x33, 4
|
||||||
|
goto mangle_lock_withskip
|
||||||
|
mangle_lock_withoutskip
|
||||||
|
movf 0x41, w ; restore 33
|
||||||
|
addwf 0x34, f ; add to 34
|
||||||
|
movf 0x35, w
|
||||||
|
movwf 0x40 ; save 35 to 40
|
||||||
|
movf 0x34, w
|
||||||
|
addwf 0x35, f
|
||||||
|
movf 0x36, w
|
||||||
|
movwf 0x41 ; save 36 to 41
|
||||||
|
movf 0x40, w ; restore 35
|
||||||
|
andlw 0xf ; mask nibble
|
||||||
|
addlw 0x8 ; add #8 to HIGH nibble
|
||||||
|
movwf 0x40
|
||||||
|
btfss 0x40, 4 ; skip if carry to 5th bit
|
||||||
|
addwf 0x36, w
|
||||||
|
movwf 0x36
|
||||||
|
|
||||||
|
movf 0x41, w ; restore 36
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x37, f ; add to 37
|
||||||
|
|
||||||
|
movf 0x37, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x38, f ; add to 38
|
||||||
|
|
||||||
|
movf 0x38, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x39, f ; add to 39
|
||||||
|
|
||||||
|
movf 0x39, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3a, f ; add to 3a
|
||||||
|
|
||||||
|
movf 0x3a, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3b, f ; add to 3b
|
||||||
|
|
||||||
|
movf 0x3b, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3c, f ; add to 3c
|
||||||
|
|
||||||
|
movf 0x3c, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3d, f ; add to 3d
|
||||||
|
|
||||||
|
movf 0x3d, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3e, f ; add to 3e
|
||||||
|
|
||||||
|
movf 0x3e, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3f, f ; add to 3f
|
||||||
|
|
||||||
|
movf 0x30, w ; restore original 0xf
|
||||||
|
andlw 0xf
|
||||||
|
addlw 0xf
|
||||||
|
movwf 0x30
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
btfss 0x30, 4 ; skip if half-byte carry
|
||||||
|
goto mangle_return
|
||||||
|
nop
|
||||||
|
goto mangle_lock_loop
|
||||||
|
; 69 when goto, 69 when return
|
||||||
|
; CIC has 78 -> 9 nops
|
||||||
|
|
||||||
|
mangle_lock_withskip
|
||||||
|
movf 0x41, w ; restore 33
|
||||||
|
addwf 0x33, f ; add to 33
|
||||||
|
movf 0x34, w
|
||||||
|
movwf 0x40 ; save 34 to 40
|
||||||
|
movf 0x33, w
|
||||||
|
addwf 0x34, f
|
||||||
|
movf 0x35, w
|
||||||
|
movwf 0x41 ; save 35 to 41
|
||||||
|
movf 0x40, w ; restore 34
|
||||||
|
andlw 0xf ; mask nibble
|
||||||
|
addlw 0x8 ; add #8 to HIGH nibble
|
||||||
|
movwf 0x40
|
||||||
|
btfss 0x40, 4 ; skip if carry to 5th bit
|
||||||
|
addwf 0x35, w
|
||||||
|
movwf 0x35
|
||||||
|
|
||||||
|
movf 0x41, w ; restore 35
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x36, f ; add to 36
|
||||||
|
|
||||||
|
movf 0x36, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x37, f ; add to 37
|
||||||
|
|
||||||
|
movf 0x37, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x38, f ; add to 38
|
||||||
|
|
||||||
|
movf 0x38, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x39, f ; add to 39
|
||||||
|
|
||||||
|
movf 0x39, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3a, f ; add to 3a
|
||||||
|
|
||||||
|
movf 0x3a, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3b, f ; add to 3b
|
||||||
|
|
||||||
|
movf 0x3b, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3c, f ; add to 3c
|
||||||
|
|
||||||
|
movf 0x3c, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3d, f ; add to 3d
|
||||||
|
|
||||||
|
movf 0x3d, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3e, f ; add to 3e
|
||||||
|
|
||||||
|
movf 0x3e, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3f, f ; add to 3f
|
||||||
|
|
||||||
|
movf 0x30, w ; restore original 0xf
|
||||||
|
andlw 0xf
|
||||||
|
addlw 0xf
|
||||||
|
movwf 0x30
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
btfss 0x30, 4 ; skip if half-byte carry
|
||||||
|
goto mangle_return
|
||||||
|
nop
|
||||||
|
goto mangle_lock_loop
|
||||||
|
; 73 when goto, 73 when return
|
||||||
|
; CIC has 84 -> 11 nops
|
||||||
|
|
||||||
|
; --------wait: 3*(W-1)+7 cycles (including call+return). W=0 -> 256!--------
|
||||||
|
wait
|
||||||
|
movwf 0x4f
|
||||||
|
wait0 decfsz 0x4f, f
|
||||||
|
goto wait0
|
||||||
|
return
|
||||||
|
|
||||||
|
; --------wait long: 8+(3*(w-1))+(772*w). W=0 -> 256!--------
|
||||||
|
longwait
|
||||||
|
movwf 0x4e
|
||||||
|
clrw
|
||||||
|
longwait0
|
||||||
|
call wait
|
||||||
|
decfsz 0x4e, f
|
||||||
|
goto longwait0
|
||||||
|
return
|
||||||
|
|
||||||
|
; --------change region in eeprom and die--------
|
||||||
|
die
|
||||||
|
banksel EEADR
|
||||||
|
clrw
|
||||||
|
movwf EEADR
|
||||||
|
bsf EECON1, RD
|
||||||
|
movf EEDAT, w
|
||||||
|
banksel GPIO
|
||||||
|
movwf 0x4d
|
||||||
|
btfsc 0x4d, 0
|
||||||
|
goto die_reg_6
|
||||||
|
die_reg_9
|
||||||
|
movlw 0x9 ; died with PAL, fall back to NTSC
|
||||||
|
goto die_reg_cont
|
||||||
|
die_reg_6
|
||||||
|
movlw 0x6 ; died with NTSC, fall back to PAL
|
||||||
|
die_reg_cont
|
||||||
|
banksel EEADR
|
||||||
|
movwf EEDAT
|
||||||
|
bsf EECON1, WREN
|
||||||
|
|
||||||
|
die_intloop
|
||||||
|
bcf INTCON, GIE
|
||||||
|
btfsc INTCON, GIE
|
||||||
|
goto die_intloop
|
||||||
|
|
||||||
|
movlw 0x55
|
||||||
|
movwf EECON2
|
||||||
|
movlw 0xaa
|
||||||
|
movwf EECON2
|
||||||
|
bsf EECON1, WR
|
||||||
|
bsf INTCON, GIE
|
||||||
|
|
||||||
|
banksel GPIO
|
||||||
|
; --------forever: blink status pin--------
|
||||||
|
die_blink
|
||||||
|
clrw
|
||||||
|
call longwait
|
||||||
|
bcf GPIO, 4
|
||||||
|
call longwait
|
||||||
|
bsf GPIO, 4
|
||||||
|
goto die_blink
|
||||||
|
; -----------------------------------------------------------------------
|
||||||
|
; eeprom memory
|
||||||
|
DEEPROM CODE
|
||||||
|
de 0x09 ; D411 (NTSC)
|
||||||
|
end
|
||||||
741
cic/snescic-lock-resync.asm
Normal file
741
cic/snescic-lock-resync.asm
Normal file
@@ -0,0 +1,741 @@
|
|||||||
|
#include <p12f629.inc>
|
||||||
|
processor p12f629
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------
|
||||||
|
; SNES CIC clone for PIC Microcontroller (lock mode, auto key region detect,
|
||||||
|
; error tolerant)
|
||||||
|
;
|
||||||
|
; Copyright (C) 2010 by Maximilian Rehkopf (ikari_01) <otakon@gmx.net>
|
||||||
|
; This software is part of the sd2snes project.
|
||||||
|
;
|
||||||
|
; 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; version 2 of the License only.
|
||||||
|
;
|
||||||
|
; 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
;
|
||||||
|
; ---------------------------------------------------------------------
|
||||||
|
;
|
||||||
|
; pin configuration: (cartridge slot pin) [original 18-pin SMD lock CIC pin]
|
||||||
|
;
|
||||||
|
; ,---_---.
|
||||||
|
; +5V (27,58) [18] |1 8| GND (5,36) [9]
|
||||||
|
; CIC clk (56) [7] |2 7| CIC data i/o 0 (55) [1]
|
||||||
|
; host reset out [10] |3 6| CIC data i/o 1 (24) [2]
|
||||||
|
; CIC lock reset in [8] |4 5| CIC slave reset out (25) [11]
|
||||||
|
; `-------'
|
||||||
|
;
|
||||||
|
; pin 3 connected to PPU2 reset in
|
||||||
|
; pin 4 connected to reset button
|
||||||
|
; pin 5 connected to key CIC pin 7 (or clone CIC pin 5)
|
||||||
|
; pin 6 connected to key CIC pin 1 (or clone CIC pin 6)
|
||||||
|
; pin 7 connected to key CIC pin 2 (or clone CIC pin 7)
|
||||||
|
;
|
||||||
|
; Host reset out behaves as follows:
|
||||||
|
; After powerup it is held low for a couple of us to properly allow the
|
||||||
|
; components to power-up.
|
||||||
|
; It is then asserted a high level even if the CIC "auth" should fail at
|
||||||
|
; any point, thus enabling homebrew or other cartridges without a CIC or
|
||||||
|
; CIC clone to be run properly while maintaining compatibility with CIC
|
||||||
|
; demanding cartridges like S-DD1 or SA-1 powered ones.
|
||||||
|
; The type of key CIC (411/413) is detected automatically.
|
||||||
|
;
|
||||||
|
; memory usage:
|
||||||
|
;
|
||||||
|
; 0x20 buffer for seed calc and transfer
|
||||||
|
; 0x21 - 0x2f seed area (lock seed)
|
||||||
|
; 0x30 buffer for seed calc
|
||||||
|
; 0x31 - 0x3f seed area (key seed; 0x31 filled in by lock)
|
||||||
|
; 0x40 - 0x41 buffer for seed calc
|
||||||
|
; 0x42 input buffer
|
||||||
|
; 0x43 variable for key detect
|
||||||
|
; 0x4d buffer for eeprom access
|
||||||
|
; 0x4e loop variable for longwait
|
||||||
|
; 0x4f loop variable for wait
|
||||||
|
;
|
||||||
|
; ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
; -----------------------------------------------------------------------
|
||||||
|
__CONFIG _EC_OSC & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _CPD_OFF
|
||||||
|
|
||||||
|
; -----------------------------------------------------------------------
|
||||||
|
; code memory
|
||||||
|
org 0x0000
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
goto init
|
||||||
|
rst ; we jump here after powerup or GPIO3=1
|
||||||
|
org 0x0004
|
||||||
|
bcf GPIO, 0 ; clear stream i/o
|
||||||
|
bcf GPIO, 1 ; clear stream i/o
|
||||||
|
bcf GPIO, 2 ; disable slave reset
|
||||||
|
bcf GPIO, 4 ; hold the SNES in reset
|
||||||
|
rst_loop
|
||||||
|
btfsc GPIO, 3 ; stay in "reset" as long as GPIO3=1
|
||||||
|
goto rst_loop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
goto main
|
||||||
|
init
|
||||||
|
org 0x0010
|
||||||
|
banksel GPIO
|
||||||
|
clrf GPIO
|
||||||
|
movlw 0x07 ; GPIO2..0 are digital I/O (not connected to comparator)
|
||||||
|
movwf CMCON
|
||||||
|
movlw 0x00 ; disable all interrupts
|
||||||
|
movwf INTCON
|
||||||
|
banksel TRISIO
|
||||||
|
movlw 0x29 ; in out in OUT out in. slave reset is an output on lock
|
||||||
|
movwf TRISIO
|
||||||
|
movlw 0x00 ; no pullups
|
||||||
|
movwf WPU
|
||||||
|
movlw 0x80 ; global pullup disable
|
||||||
|
movwf OPTION_REG
|
||||||
|
|
||||||
|
banksel GPIO
|
||||||
|
bcf GPIO, 4 ; LED off
|
||||||
|
goto rst
|
||||||
|
main
|
||||||
|
movlw 0x40 ; wait a bit before initializing the slave + console
|
||||||
|
call longwait
|
||||||
|
|
||||||
|
bsf GPIO, 4 ; enable console
|
||||||
|
|
||||||
|
bsf GPIO, 2 ; trigger the slave
|
||||||
|
clrf 0x44 ; clear direction
|
||||||
|
nop
|
||||||
|
bcf GPIO, 2
|
||||||
|
|
||||||
|
banksel TRISIO
|
||||||
|
bcf TRISIO, 0
|
||||||
|
bsf TRISIO, 1
|
||||||
|
banksel GPIO
|
||||||
|
; --------INIT LOCK SEED (what we must send)--------
|
||||||
|
movlw 0xb
|
||||||
|
movwf 0x21
|
||||||
|
movlw 0x1
|
||||||
|
movwf 0x22
|
||||||
|
movlw 0x4
|
||||||
|
movwf 0x23
|
||||||
|
movlw 0xf
|
||||||
|
movwf 0x24
|
||||||
|
movlw 0x4
|
||||||
|
movwf 0x25
|
||||||
|
movlw 0xb
|
||||||
|
movwf 0x26
|
||||||
|
movlw 0x5
|
||||||
|
movwf 0x27
|
||||||
|
movlw 0x7
|
||||||
|
movwf 0x28
|
||||||
|
movlw 0xf
|
||||||
|
movwf 0x29
|
||||||
|
movlw 0xd
|
||||||
|
movwf 0x2a
|
||||||
|
movlw 0x6
|
||||||
|
movwf 0x2b
|
||||||
|
movlw 0x1
|
||||||
|
movwf 0x2c
|
||||||
|
movlw 0xe
|
||||||
|
movwf 0x2d
|
||||||
|
movlw 0x9
|
||||||
|
movwf 0x2e
|
||||||
|
movlw 0x8
|
||||||
|
movwf 0x2f
|
||||||
|
|
||||||
|
; --------INIT KEY SEED (what the key sends)--------
|
||||||
|
movlw 0xf ; we always request the same stream for simplicity
|
||||||
|
movwf 0x31
|
||||||
|
movlw 0x0 ; this is filled in by key autodetect
|
||||||
|
movwf 0x32
|
||||||
|
movlw 0xa
|
||||||
|
movwf 0x33
|
||||||
|
movlw 0x1
|
||||||
|
movwf 0x34
|
||||||
|
movlw 0x8
|
||||||
|
movwf 0x35
|
||||||
|
movlw 0x5
|
||||||
|
movwf 0x36
|
||||||
|
movlw 0xf
|
||||||
|
movwf 0x37
|
||||||
|
movlw 0x1
|
||||||
|
movwf 0x38
|
||||||
|
movwf 0x39
|
||||||
|
movlw 0xe
|
||||||
|
movwf 0x3a
|
||||||
|
movlw 0x1
|
||||||
|
movwf 0x3b
|
||||||
|
movlw 0x0
|
||||||
|
movwf 0x3c
|
||||||
|
movlw 0xd
|
||||||
|
movwf 0x3d
|
||||||
|
movlw 0xe
|
||||||
|
movwf 0x3e
|
||||||
|
movlw 0xc
|
||||||
|
movwf 0x3f
|
||||||
|
|
||||||
|
; --------wait before sending stream ID--------
|
||||||
|
movlw 0xba
|
||||||
|
call wait
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
|
||||||
|
; --------lock sends stream ID. 15 cycles per bit--------
|
||||||
|
; bsf GPIO, 0 ; (debug marker)
|
||||||
|
; bcf GPIO, 0 ;
|
||||||
|
btfsc 0x31, 3 ; read stream select bit
|
||||||
|
bsf GPIO, 0 ; send bit
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
bcf GPIO, 0
|
||||||
|
movlw 0x1 ; wait=7
|
||||||
|
call wait ; burn 10 cycles
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
|
||||||
|
; bsf GPIO, 0
|
||||||
|
; bcf GPIO, 0
|
||||||
|
btfsc 0x31, 0 ; read stream select bit
|
||||||
|
bsf GPIO, 0 ; send bit
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
bcf GPIO, 0
|
||||||
|
movlw 0x1 ; wait=3*W+5
|
||||||
|
call wait ; burn 11 cycles
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
|
||||||
|
; bsf GPIO, 0
|
||||||
|
; bcf GPIO, 0
|
||||||
|
btfsc 0x31, 1 ; read stream select bit
|
||||||
|
bsf GPIO, 0 ; send bit
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
bcf GPIO, 0
|
||||||
|
movlw 0x1 ; wait=3*W+5
|
||||||
|
call wait ; burn 11 cycles
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
|
||||||
|
; bsf GPIO, 0
|
||||||
|
; bcf GPIO, 0
|
||||||
|
btfsc 0x31, 2 ; read stream select bit
|
||||||
|
bsf GPIO, 0 ; send bit
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
bcf GPIO, 0
|
||||||
|
movlw 0x1 ; wait=3*0+7
|
||||||
|
call wait ; burn 10 cycles
|
||||||
|
banksel TRISIO
|
||||||
|
bsf TRISIO, 0
|
||||||
|
bcf TRISIO, 1
|
||||||
|
banksel GPIO
|
||||||
|
movlw 0x24 ; "wait" 1
|
||||||
|
call wait ; wait 112
|
||||||
|
; nop
|
||||||
|
movlw 0x1 ; 'first time' bit
|
||||||
|
movwf 0x43 ; for key detection
|
||||||
|
; --------main loop--------
|
||||||
|
loop
|
||||||
|
movlw 0x1
|
||||||
|
loop0
|
||||||
|
addlw 0x20 ; lock stream
|
||||||
|
movwf FSR ; store in index reg
|
||||||
|
loop1
|
||||||
|
movf INDF, w ; load seed value
|
||||||
|
movwf 0x20
|
||||||
|
bcf 0x20, 1 ; clear bit 1
|
||||||
|
btfsc 0x20, 0 ; copy from bit 0
|
||||||
|
bsf 0x20, 1 ; (if set)
|
||||||
|
bsf 0x20, 4 ; run console
|
||||||
|
bcf 0x20, 2 ; run slave
|
||||||
|
movf 0x20, w
|
||||||
|
movwf GPIO
|
||||||
|
movf GPIO, w ; read input
|
||||||
|
movwf 0x42 ; store input
|
||||||
|
movlw 0x10
|
||||||
|
movwf GPIO ; reset GPIO
|
||||||
|
call checkkey
|
||||||
|
|
||||||
|
btfsc GPIO, 3 ; poll master reset
|
||||||
|
goto rst ; (to allow resetting w/o key CIC...)
|
||||||
|
|
||||||
|
btfsc 0x44, 0 ; check "direction"
|
||||||
|
rrf 0x42, f ; shift received bit into place
|
||||||
|
bsf FSR, 4 ; goto other stream
|
||||||
|
movf INDF, w ; read
|
||||||
|
xorwf 0x42, f ; xor received + calculated
|
||||||
|
bcf FSR, 4 ; back to our own stream
|
||||||
|
btfsc 0x42, 0 ; equal? then continue
|
||||||
|
goto main ; else resync key and start over
|
||||||
|
|
||||||
|
nop ; wait 1 cycle
|
||||||
|
nop ; wait 1 cycle
|
||||||
|
movlw 0xc ; wait 40 cycles
|
||||||
|
call wait
|
||||||
|
btfsc GPIO, 0 ; both pins must be low...
|
||||||
|
goto die
|
||||||
|
btfsc GPIO, 1 ; ...when no bit transfer takes place
|
||||||
|
goto die ; if not -> lock cic error state -> die
|
||||||
|
incf FSR, f ; next one
|
||||||
|
movlw 0xf
|
||||||
|
andwf FSR, w
|
||||||
|
btfss STATUS, Z
|
||||||
|
goto loop1
|
||||||
|
movlw 0x1 ; wait 7
|
||||||
|
call wait ;
|
||||||
|
call mangle
|
||||||
|
call mangle
|
||||||
|
call mangle
|
||||||
|
movf 0x37, w
|
||||||
|
movwf 0x44
|
||||||
|
btfsc 0x37, 0
|
||||||
|
goto swap
|
||||||
|
banksel TRISIO
|
||||||
|
bsf TRISIO, 0
|
||||||
|
bcf TRISIO, 1
|
||||||
|
goto swapskip
|
||||||
|
swap
|
||||||
|
banksel TRISIO
|
||||||
|
bcf TRISIO, 0
|
||||||
|
bsf TRISIO, 1
|
||||||
|
nop
|
||||||
|
swapskip
|
||||||
|
banksel GPIO
|
||||||
|
btfsc GPIO, 3 ; poll master reset
|
||||||
|
goto rst
|
||||||
|
clrf 0x43 ; don't check key region anymore
|
||||||
|
movf 0x37, w
|
||||||
|
andlw 0xf
|
||||||
|
btfss STATUS, Z
|
||||||
|
goto loop0
|
||||||
|
goto loop
|
||||||
|
|
||||||
|
; --------calculate new seeds--------
|
||||||
|
; had to be unrolled because PIC has an inefficient way of handling
|
||||||
|
; indirect access, no post increment, no swap, etc.
|
||||||
|
mangle
|
||||||
|
call mangle_lock
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
mangle_key
|
||||||
|
movf 0x2f, w
|
||||||
|
movwf 0x20
|
||||||
|
mangle_key_loop
|
||||||
|
addlw 0x1
|
||||||
|
addwf 0x21, f
|
||||||
|
movf 0x22, w
|
||||||
|
movwf 0x40
|
||||||
|
movf 0x21, w
|
||||||
|
addwf 0x22, f
|
||||||
|
incf 0x22, f
|
||||||
|
comf 0x22, f
|
||||||
|
movf 0x23, w
|
||||||
|
movwf 0x41 ; store 23 to 41
|
||||||
|
movlw 0xf
|
||||||
|
andwf 0x23, f
|
||||||
|
movf 0x40, w ; add 40(22 old)+23+#1 and skip if carry
|
||||||
|
andlw 0xf
|
||||||
|
addwf 0x23, f
|
||||||
|
incf 0x23, f
|
||||||
|
btfsc 0x23, 4
|
||||||
|
goto mangle_key_withskip
|
||||||
|
mangle_key_withoutskip
|
||||||
|
movf 0x41, w ; restore 23
|
||||||
|
addwf 0x24, f ; add to 24
|
||||||
|
movf 0x25, w
|
||||||
|
movwf 0x40 ; save 25 to 40
|
||||||
|
movf 0x24, w
|
||||||
|
addwf 0x25, f
|
||||||
|
movf 0x26, w
|
||||||
|
movwf 0x41 ; save 26 to 41
|
||||||
|
movf 0x40, w ; restore 25
|
||||||
|
andlw 0xf ; mask nibble
|
||||||
|
addlw 0x8 ; add #8 to HIGH nibble
|
||||||
|
movwf 0x40
|
||||||
|
btfss 0x40, 4 ; skip if carry to 5th bit
|
||||||
|
addwf 0x26, w
|
||||||
|
movwf 0x26
|
||||||
|
|
||||||
|
movf 0x41, w ; restore 26
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x27, f ; add to 27
|
||||||
|
|
||||||
|
movf 0x27, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x28, f ; add to 28
|
||||||
|
|
||||||
|
movf 0x28, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x29, f ; add to 29
|
||||||
|
|
||||||
|
movf 0x29, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2a, f ; add to 2a
|
||||||
|
|
||||||
|
movf 0x2a, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2b, f ; add to 2b
|
||||||
|
|
||||||
|
movf 0x2b, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2c, f ; add to 2c
|
||||||
|
|
||||||
|
movf 0x2c, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2d, f ; add to 2d
|
||||||
|
|
||||||
|
movf 0x2d, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2e, f ; add to 2e
|
||||||
|
|
||||||
|
movf 0x2e, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2f, f ; add to 2f
|
||||||
|
|
||||||
|
movf 0x20, w ; restore original 0xf
|
||||||
|
andlw 0xf
|
||||||
|
addlw 0xf
|
||||||
|
movwf 0x20
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
btfss 0x20, 4 ; skip if half-byte carry
|
||||||
|
goto mangle_return ; +2 cycles in return
|
||||||
|
nop
|
||||||
|
goto mangle_key_loop
|
||||||
|
; 69 when goto, 69 when return
|
||||||
|
; CIC has 78 -> 9 nops
|
||||||
|
|
||||||
|
mangle_key_withskip
|
||||||
|
movf 0x41, w ; restore 23
|
||||||
|
addwf 0x23, f ; add to 23
|
||||||
|
movf 0x24, w
|
||||||
|
movwf 0x40 ; save 24 to 40
|
||||||
|
movf 0x23, w
|
||||||
|
addwf 0x24, f
|
||||||
|
movf 0x25, w
|
||||||
|
movwf 0x41 ; save 25 to 41
|
||||||
|
movf 0x40, w ; restore 24
|
||||||
|
andlw 0xf ; mask nibble
|
||||||
|
addlw 0x8 ; add #8 to HIGH nibble
|
||||||
|
movwf 0x40
|
||||||
|
btfss 0x40, 4 ; skip if carry to 5th bit
|
||||||
|
addwf 0x25, w
|
||||||
|
movwf 0x25
|
||||||
|
|
||||||
|
movf 0x41, w ; restore 25
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x26, f ; add to 26
|
||||||
|
|
||||||
|
movf 0x26, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x27, f ; add to 27
|
||||||
|
|
||||||
|
movf 0x27, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x28, f ; add to 28
|
||||||
|
|
||||||
|
movf 0x28, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x29, f ; add to 29
|
||||||
|
|
||||||
|
movf 0x29, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2a, f ; add to 2a
|
||||||
|
|
||||||
|
movf 0x2a, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2b, f ; add to 2b
|
||||||
|
|
||||||
|
movf 0x2b, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2c, f ; add to 2c
|
||||||
|
|
||||||
|
movf 0x2c, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2d, f ; add to 2d
|
||||||
|
|
||||||
|
movf 0x2d, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2e, f ; add to 2e
|
||||||
|
|
||||||
|
movf 0x2e, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2f, f ; add to 2f
|
||||||
|
|
||||||
|
movf 0x20, w ; restore original 0xf
|
||||||
|
andlw 0xf
|
||||||
|
addlw 0xf
|
||||||
|
movwf 0x20
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
btfss 0x20, 4 ; skip if half-byte carry
|
||||||
|
goto mangle_return ; +2 cycles in return
|
||||||
|
nop
|
||||||
|
goto mangle_key_loop
|
||||||
|
mangle_return
|
||||||
|
return
|
||||||
|
; 73 when goto, 73 when return
|
||||||
|
; CIC has 84 -> 11 nops
|
||||||
|
|
||||||
|
mangle_lock
|
||||||
|
movf 0x3f, w
|
||||||
|
movwf 0x30
|
||||||
|
mangle_lock_loop
|
||||||
|
addlw 0x1
|
||||||
|
addwf 0x31, f
|
||||||
|
movf 0x32, w
|
||||||
|
movwf 0x40
|
||||||
|
movf 0x31, w
|
||||||
|
addwf 0x32, f
|
||||||
|
incf 0x32, f
|
||||||
|
comf 0x32, f
|
||||||
|
movf 0x33, w
|
||||||
|
movwf 0x41 ; store 33 to 41
|
||||||
|
movlw 0xf
|
||||||
|
andwf 0x33, f
|
||||||
|
movf 0x40, w ; add 40(32 old)+33+#1 and skip if carry
|
||||||
|
andlw 0xf
|
||||||
|
addwf 0x33, f
|
||||||
|
incf 0x33, f
|
||||||
|
btfsc 0x33, 4
|
||||||
|
goto mangle_lock_withskip
|
||||||
|
mangle_lock_withoutskip
|
||||||
|
movf 0x41, w ; restore 33
|
||||||
|
addwf 0x34, f ; add to 34
|
||||||
|
movf 0x35, w
|
||||||
|
movwf 0x40 ; save 35 to 40
|
||||||
|
movf 0x34, w
|
||||||
|
addwf 0x35, f
|
||||||
|
movf 0x36, w
|
||||||
|
movwf 0x41 ; save 36 to 41
|
||||||
|
movf 0x40, w ; restore 35
|
||||||
|
andlw 0xf ; mask nibble
|
||||||
|
addlw 0x8 ; add #8 to HIGH nibble
|
||||||
|
movwf 0x40
|
||||||
|
btfss 0x40, 4 ; skip if carry to 5th bit
|
||||||
|
addwf 0x36, w
|
||||||
|
movwf 0x36
|
||||||
|
|
||||||
|
movf 0x41, w ; restore 36
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x37, f ; add to 37
|
||||||
|
|
||||||
|
movf 0x37, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x38, f ; add to 38
|
||||||
|
|
||||||
|
movf 0x38, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x39, f ; add to 39
|
||||||
|
|
||||||
|
movf 0x39, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3a, f ; add to 3a
|
||||||
|
|
||||||
|
movf 0x3a, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3b, f ; add to 3b
|
||||||
|
|
||||||
|
movf 0x3b, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3c, f ; add to 3c
|
||||||
|
|
||||||
|
movf 0x3c, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3d, f ; add to 3d
|
||||||
|
|
||||||
|
movf 0x3d, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3e, f ; add to 3e
|
||||||
|
|
||||||
|
movf 0x3e, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3f, f ; add to 3f
|
||||||
|
|
||||||
|
movf 0x30, w ; restore original 0xf
|
||||||
|
andlw 0xf
|
||||||
|
addlw 0xf
|
||||||
|
movwf 0x30
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
btfss 0x30, 4 ; skip if half-byte carry
|
||||||
|
goto mangle_return
|
||||||
|
nop
|
||||||
|
goto mangle_lock_loop
|
||||||
|
; 69 when goto, 69 when return
|
||||||
|
; CIC has 78 -> 9 nops
|
||||||
|
|
||||||
|
mangle_lock_withskip
|
||||||
|
movf 0x41, w ; restore 33
|
||||||
|
addwf 0x33, f ; add to 33
|
||||||
|
movf 0x34, w
|
||||||
|
movwf 0x40 ; save 34 to 40
|
||||||
|
movf 0x33, w
|
||||||
|
addwf 0x34, f
|
||||||
|
movf 0x35, w
|
||||||
|
movwf 0x41 ; save 35 to 41
|
||||||
|
movf 0x40, w ; restore 34
|
||||||
|
andlw 0xf ; mask nibble
|
||||||
|
addlw 0x8 ; add #8 to HIGH nibble
|
||||||
|
movwf 0x40
|
||||||
|
btfss 0x40, 4 ; skip if carry to 5th bit
|
||||||
|
addwf 0x35, w
|
||||||
|
movwf 0x35
|
||||||
|
|
||||||
|
movf 0x41, w ; restore 35
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x36, f ; add to 36
|
||||||
|
|
||||||
|
movf 0x36, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x37, f ; add to 37
|
||||||
|
|
||||||
|
movf 0x37, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x38, f ; add to 38
|
||||||
|
|
||||||
|
movf 0x38, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x39, f ; add to 39
|
||||||
|
|
||||||
|
movf 0x39, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3a, f ; add to 3a
|
||||||
|
|
||||||
|
movf 0x3a, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3b, f ; add to 3b
|
||||||
|
|
||||||
|
movf 0x3b, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3c, f ; add to 3c
|
||||||
|
|
||||||
|
movf 0x3c, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3d, f ; add to 3d
|
||||||
|
|
||||||
|
movf 0x3d, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3e, f ; add to 3e
|
||||||
|
|
||||||
|
movf 0x3e, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3f, f ; add to 3f
|
||||||
|
|
||||||
|
movf 0x30, w ; restore original 0xf
|
||||||
|
andlw 0xf
|
||||||
|
addlw 0xf
|
||||||
|
movwf 0x30
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
btfss 0x30, 4 ; skip if half-byte carry
|
||||||
|
goto mangle_return
|
||||||
|
nop
|
||||||
|
goto mangle_lock_loop
|
||||||
|
; 73 when goto, 73 when return
|
||||||
|
; CIC has 84 -> 11 nops
|
||||||
|
|
||||||
|
; --------wait: 3*(W-1)+7 cycles (including call+return). W=0 -> 256!--------
|
||||||
|
wait
|
||||||
|
movwf 0x4f
|
||||||
|
wait0 decfsz 0x4f, f
|
||||||
|
goto wait0
|
||||||
|
return
|
||||||
|
|
||||||
|
; --------wait long: 8+(3*(w-1))+(772*w). W=0 -> 256!--------
|
||||||
|
longwait
|
||||||
|
movwf 0x4e
|
||||||
|
clrw
|
||||||
|
longwait0
|
||||||
|
call wait
|
||||||
|
decfsz 0x4e, f
|
||||||
|
goto longwait0
|
||||||
|
return
|
||||||
|
|
||||||
|
; --------die (do nothing, wait for reset)--------
|
||||||
|
die
|
||||||
|
btfsc GPIO, 3
|
||||||
|
goto rst
|
||||||
|
goto die
|
||||||
|
|
||||||
|
; --------check the key input and change "region" when appropriate--------
|
||||||
|
; --------requires 17 cycles (incl. call+return)
|
||||||
|
checkkey
|
||||||
|
btfss 0x43, 0 ; first time?
|
||||||
|
goto checkkey_nocheck ; if not, just burn some cycles
|
||||||
|
movlw 0x22 ; are we at the correct stream offset?
|
||||||
|
xorwf FSR, w
|
||||||
|
btfss STATUS, Z ; if not equal:
|
||||||
|
goto checkkey_nocheck2 ; burn some cycles less.
|
||||||
|
; if equal do the check
|
||||||
|
btfss 0x42, 0 ; if value from slave is set it's a 411
|
||||||
|
goto check_413
|
||||||
|
check_411
|
||||||
|
nop ; to compensate for untaken branch
|
||||||
|
movlw 0x9
|
||||||
|
goto check_save
|
||||||
|
check_413
|
||||||
|
movlw 0x6
|
||||||
|
goto check_save
|
||||||
|
|
||||||
|
checkkey_nocheck
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
checkkey_nocheck2
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
goto check_done
|
||||||
|
check_save
|
||||||
|
movwf 0x32
|
||||||
|
check_done
|
||||||
|
return
|
||||||
|
end
|
||||||
|
; ------------------------------------------------------------------------
|
||||||
71
cic/snescic-lock-resync.hex
Normal file
71
cic/snescic-lock-resync.hex
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
:020000040000FA
|
||||||
|
:1000000000000000000010280510851005110512E1
|
||||||
|
:1000100085190828000000000000000000002028CA
|
||||||
|
:10002000831285010730990000308B008316293038
|
||||||
|
:10003000850000309500803081008312051204286D
|
||||||
|
:100040004030FC2105160515C4010000051183167A
|
||||||
|
:100050000510851483120B30A1000130A20004307A
|
||||||
|
:10006000A3000F30A4000430A5000B30A60005301B
|
||||||
|
:10007000A7000730A8000F30A9000D30AA000630F5
|
||||||
|
:10008000AB000130AC000E30AD000930AE000830DE
|
||||||
|
:10009000AF000F30B1000030B2000A30B3000130C1
|
||||||
|
:1000A000B4000830B5000530B6000F30B70001309D
|
||||||
|
:1000B000B800B9000E30BA000130BB000030BC00FF
|
||||||
|
:1000C0000D30BD000E30BE000C30BF00BA30F8213C
|
||||||
|
:1000D00000000000B11905140000000005100130F7
|
||||||
|
:1000E000F821000000003118051400000000051080
|
||||||
|
:1000F0000130F82100000000B118051400000000D4
|
||||||
|
:1001000005100130F821000000003119051400002D
|
||||||
|
:10011000000005100130F8218316051485108312A4
|
||||||
|
:100120002430F8210130C3000130203E8400000853
|
||||||
|
:10013000A000A0102018A01420162011200885006F
|
||||||
|
:100140000508C200103085000522851904284418CE
|
||||||
|
:10015000C20C04160008C20604124218202800002F
|
||||||
|
:1001600000000C30F8210518022A8518022A840A9A
|
||||||
|
:100170000F300405031D97280130F821D620D62022
|
||||||
|
:10018000D6203708C4003718C928831605148510EF
|
||||||
|
:10019000CD288316051085140000831285190428C4
|
||||||
|
:1001A000C30137080F39031D9528942869210000E1
|
||||||
|
:1001B00000002F08A000013EA1072208C00021086E
|
||||||
|
:1001C000A207A20AA2092308C1000F30A305400814
|
||||||
|
:1001D0000F39A307A30A231A28294108A4072508D1
|
||||||
|
:1001E000C0002408A5072608C10040080F39083EB2
|
||||||
|
:1001F000C000401E2607A6004108013EA7072708A9
|
||||||
|
:10020000013EA8072808013EA9072908013EAA07C0
|
||||||
|
:100210002A08013EAB072B08013EAC072C08013E23
|
||||||
|
:10022000AD072D08013EAE072E08013EAF0720089E
|
||||||
|
:100230000F390F3EA0000000000000000000000089
|
||||||
|
:100240000000000000000000201E68290000DB28DC
|
||||||
|
:100250004108A3072408C0002308A4072508C100FB
|
||||||
|
:1002600040080F39083EC000401E2507A500410880
|
||||||
|
:10027000013EA6072608013EA7072708013EA8075A
|
||||||
|
:100280002808013EA9072908013EAA072A08013EBD
|
||||||
|
:10029000AB072B08013EAC072C08013EAD072D082B
|
||||||
|
:1002A000013EAE072E08013EAF0720080F390F3E72
|
||||||
|
:1002B000A00000000000000000000000000000009E
|
||||||
|
:1002C0000000000000000000201E68290000DB285C
|
||||||
|
:1002D00008003F08B000013EB1073208C0003108F5
|
||||||
|
:1002E000B207B20AB2093308C1000F30B3054008A3
|
||||||
|
:1002F0000F39B307B30A331AB8294108B4073508D0
|
||||||
|
:10030000C0003408B5073608C10040080F39083E60
|
||||||
|
:10031000C000401E3607B6004108013EB707370847
|
||||||
|
:10032000013EB8073808013EB9073908013EBA074F
|
||||||
|
:100330003A08013EBB073B08013EBC073C08013EB2
|
||||||
|
:10034000BD073D08013EBE073E08013EBF0730081D
|
||||||
|
:100350000F390F3EB0000000000000000000000058
|
||||||
|
:100360000000000000000000301E682900006B291A
|
||||||
|
:100370004108B3073408C0003308B4073508C1008A
|
||||||
|
:1003800040080F39083EC000401E3507B50041083F
|
||||||
|
:10039000013EB6073608013EB7073708013EB807E9
|
||||||
|
:1003A0003808013EB9073908013EBA073A08013E4C
|
||||||
|
:1003B000BB073B08013EBC073C08013EBD073D08AA
|
||||||
|
:1003C000013EBE073E08013EBF0730080F390F3E11
|
||||||
|
:1003D000B00000000000000000000000000000006D
|
||||||
|
:1003E0000000000000000000301E682900006B299A
|
||||||
|
:1003F000CF00CF0BF9290800CE000301F821CE0B66
|
||||||
|
:10040000FE29080085190428022A431C122A2230DA
|
||||||
|
:100410000406031D162A421C102A000009301B2A5C
|
||||||
|
:1004200006301B2A00000000000000000000000051
|
||||||
|
:0A043000000000001C2AB2000800C2
|
||||||
|
:02400E00D33F9E
|
||||||
|
:00000001FF
|
||||||
726
cic/snescic-lock.asm
Normal file
726
cic/snescic-lock.asm
Normal file
@@ -0,0 +1,726 @@
|
|||||||
|
#include <p12f629.inc>
|
||||||
|
processor p12f629
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------
|
||||||
|
; SNES CIC clone for PIC Microcontroller (lock mode, auto key region detect,
|
||||||
|
; error tolerant)
|
||||||
|
;
|
||||||
|
; Copyright (C) 2010 by Maximilian Rehkopf (ikari_01) <otakon@gmx.net>
|
||||||
|
; This software is part of the sd2snes project.
|
||||||
|
;
|
||||||
|
; 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; version 2 of the License only.
|
||||||
|
;
|
||||||
|
; 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
;
|
||||||
|
; ---------------------------------------------------------------------
|
||||||
|
;
|
||||||
|
; pin configuration: (cartridge slot pin) [original 18-pin SMD lock CIC pin]
|
||||||
|
;
|
||||||
|
; ,---_---.
|
||||||
|
; +5V (27,58) [18] |1 8| GND (5,36) [9]
|
||||||
|
; CIC clk (56) [7] |2 7| CIC data i/o 0 (55) [1]
|
||||||
|
; host reset out [10] |3 6| CIC data i/o 1 (24) [2]
|
||||||
|
; CIC lock reset in [8] |4 5| CIC slave reset out (25) [11]
|
||||||
|
; `-------'
|
||||||
|
;
|
||||||
|
; pin 3 connected to PPU2 reset in
|
||||||
|
; pin 4 connected to reset button
|
||||||
|
; pin 5 connected to key CIC pin 7 (or clone CIC pin 5)
|
||||||
|
; pin 6 connected to key CIC pin 1 (or clone CIC pin 6)
|
||||||
|
; pin 7 connected to key CIC pin 2 (or clone CIC pin 7)
|
||||||
|
;
|
||||||
|
; Host reset out behaves as follows:
|
||||||
|
; After powerup it is held low for a couple of us to properly allow the
|
||||||
|
; components to power-up.
|
||||||
|
; It is then asserted a high level even if the CIC "auth" should fail at
|
||||||
|
; any point, thus enabling homebrew or other cartridges without a CIC or
|
||||||
|
; CIC clone to be run properly while maintaining compatibility with CIC
|
||||||
|
; demanding cartridges like S-DD1 or SA-1 powered ones.
|
||||||
|
; The type of key CIC (411/413) is detected automatically.
|
||||||
|
;
|
||||||
|
; memory usage:
|
||||||
|
;
|
||||||
|
; 0x20 buffer for seed calc and transfer
|
||||||
|
; 0x21 - 0x2f seed area (lock seed)
|
||||||
|
; 0x30 buffer for seed calc
|
||||||
|
; 0x31 - 0x3f seed area (key seed; 0x31 filled in by lock)
|
||||||
|
; 0x40 - 0x41 buffer for seed calc
|
||||||
|
; 0x42 input buffer
|
||||||
|
; 0x43 variable for key detect
|
||||||
|
; 0x4d buffer for eeprom access
|
||||||
|
; 0x4e loop variable for longwait
|
||||||
|
; 0x4f loop variable for wait
|
||||||
|
;
|
||||||
|
; ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
; -----------------------------------------------------------------------
|
||||||
|
__CONFIG _EC_OSC & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _CPD_OFF
|
||||||
|
|
||||||
|
; -----------------------------------------------------------------------
|
||||||
|
; code memory
|
||||||
|
org 0x0000
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
goto init
|
||||||
|
rst ; we jump here after powerup or GPIO3=1
|
||||||
|
org 0x0004
|
||||||
|
bcf GPIO, 0 ; clear stream i/o
|
||||||
|
bcf GPIO, 1 ; clear stream i/o
|
||||||
|
bcf GPIO, 2 ; disable slave reset
|
||||||
|
bcf GPIO, 4 ; hold the SNES in reset
|
||||||
|
rst_loop
|
||||||
|
btfsc GPIO, 3 ; stay in "reset" as long as GPIO3=1
|
||||||
|
goto rst_loop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
goto main
|
||||||
|
init
|
||||||
|
org 0x0010
|
||||||
|
banksel GPIO
|
||||||
|
clrf GPIO
|
||||||
|
movlw 0x07 ; GPIO2..0 are digital I/O (not connected to comparator)
|
||||||
|
movwf CMCON
|
||||||
|
movlw 0x00 ; disable all interrupts
|
||||||
|
movwf INTCON
|
||||||
|
banksel TRISIO
|
||||||
|
movlw 0x29 ; in out in OUT out in. slave reset is an output on lock
|
||||||
|
movwf TRISIO
|
||||||
|
movlw 0x00 ; no pullups
|
||||||
|
movwf WPU
|
||||||
|
movlw 0x80 ; global pullup disable
|
||||||
|
movwf OPTION_REG
|
||||||
|
|
||||||
|
banksel GPIO
|
||||||
|
bcf GPIO, 4 ; LED off
|
||||||
|
goto rst
|
||||||
|
main
|
||||||
|
movlw 0x40 ; wait a bit before initializing the slave + console
|
||||||
|
call longwait
|
||||||
|
|
||||||
|
bsf GPIO, 4 ; enable console
|
||||||
|
|
||||||
|
bsf GPIO, 2 ; trigger the slave
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
bcf GPIO, 2
|
||||||
|
|
||||||
|
banksel TRISIO
|
||||||
|
bcf TRISIO, 0
|
||||||
|
bsf TRISIO, 1
|
||||||
|
banksel GPIO
|
||||||
|
; --------INIT LOCK SEED (what we must send)--------
|
||||||
|
movlw 0xb
|
||||||
|
movwf 0x21
|
||||||
|
movlw 0x1
|
||||||
|
movwf 0x22
|
||||||
|
movlw 0x4
|
||||||
|
movwf 0x23
|
||||||
|
movlw 0xf
|
||||||
|
movwf 0x24
|
||||||
|
movlw 0x4
|
||||||
|
movwf 0x25
|
||||||
|
movlw 0xb
|
||||||
|
movwf 0x26
|
||||||
|
movlw 0x5
|
||||||
|
movwf 0x27
|
||||||
|
movlw 0x7
|
||||||
|
movwf 0x28
|
||||||
|
movlw 0xf
|
||||||
|
movwf 0x29
|
||||||
|
movlw 0xd
|
||||||
|
movwf 0x2a
|
||||||
|
movlw 0x6
|
||||||
|
movwf 0x2b
|
||||||
|
movlw 0x1
|
||||||
|
movwf 0x2c
|
||||||
|
movlw 0xe
|
||||||
|
movwf 0x2d
|
||||||
|
movlw 0x9
|
||||||
|
movwf 0x2e
|
||||||
|
movlw 0x8
|
||||||
|
movwf 0x2f
|
||||||
|
|
||||||
|
; --------INIT KEY SEED (what the key sends)--------
|
||||||
|
movlw 0xf ; we always request the same stream for simplicity
|
||||||
|
movwf 0x31
|
||||||
|
movlw 0x0 ; this is filled in by key autodetect
|
||||||
|
movwf 0x32
|
||||||
|
movlw 0xa
|
||||||
|
movwf 0x33
|
||||||
|
movlw 0x1
|
||||||
|
movwf 0x34
|
||||||
|
movlw 0x8
|
||||||
|
movwf 0x35
|
||||||
|
movlw 0x5
|
||||||
|
movwf 0x36
|
||||||
|
movlw 0xf
|
||||||
|
movwf 0x37
|
||||||
|
movlw 0x1
|
||||||
|
movwf 0x38
|
||||||
|
movwf 0x39
|
||||||
|
movlw 0xe
|
||||||
|
movwf 0x3a
|
||||||
|
movlw 0x1
|
||||||
|
movwf 0x3b
|
||||||
|
movlw 0x0
|
||||||
|
movwf 0x3c
|
||||||
|
movlw 0xd
|
||||||
|
movwf 0x3d
|
||||||
|
movlw 0xe
|
||||||
|
movwf 0x3e
|
||||||
|
movlw 0xc
|
||||||
|
movwf 0x3f
|
||||||
|
|
||||||
|
; --------wait before sending stream ID--------
|
||||||
|
movlw 0xba
|
||||||
|
call wait
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
|
||||||
|
; --------lock sends stream ID. 15 cycles per bit--------
|
||||||
|
; bsf GPIO, 0 ; (debug marker)
|
||||||
|
; bcf GPIO, 0 ;
|
||||||
|
btfsc 0x31, 3 ; read stream select bit
|
||||||
|
bsf GPIO, 0 ; send bit
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
bcf GPIO, 0
|
||||||
|
movlw 0x1 ; wait=7
|
||||||
|
call wait ; burn 10 cycles
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
|
||||||
|
; bsf GPIO, 0
|
||||||
|
; bcf GPIO, 0
|
||||||
|
btfsc 0x31, 0 ; read stream select bit
|
||||||
|
bsf GPIO, 0 ; send bit
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
bcf GPIO, 0
|
||||||
|
movlw 0x1 ; wait=3*W+5
|
||||||
|
call wait ; burn 11 cycles
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
|
||||||
|
; bsf GPIO, 0
|
||||||
|
; bcf GPIO, 0
|
||||||
|
btfsc 0x31, 1 ; read stream select bit
|
||||||
|
bsf GPIO, 0 ; send bit
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
bcf GPIO, 0
|
||||||
|
movlw 0x1 ; wait=3*W+5
|
||||||
|
call wait ; burn 11 cycles
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
|
||||||
|
; bsf GPIO, 0
|
||||||
|
; bcf GPIO, 0
|
||||||
|
btfsc 0x31, 2 ; read stream select bit
|
||||||
|
bsf GPIO, 0 ; send bit
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
bcf GPIO, 0
|
||||||
|
movlw 0x1 ; wait=3*0+7
|
||||||
|
call wait ; burn 10 cycles
|
||||||
|
banksel TRISIO
|
||||||
|
bsf TRISIO, 0
|
||||||
|
bcf TRISIO, 1
|
||||||
|
banksel GPIO
|
||||||
|
movlw 0x24 ; "wait" 1
|
||||||
|
call wait ; wait 112
|
||||||
|
; nop
|
||||||
|
movlw 0x1 ; 'first time' bit
|
||||||
|
movwf 0x43 ; for key detection
|
||||||
|
; --------main loop--------
|
||||||
|
loop
|
||||||
|
movlw 0x1
|
||||||
|
loop0
|
||||||
|
addlw 0x20 ; lock stream
|
||||||
|
movwf FSR ; store in index reg
|
||||||
|
loop1
|
||||||
|
movf INDF, w ; load seed value
|
||||||
|
movwf 0x20
|
||||||
|
bcf 0x20, 1 ; clear bit 1
|
||||||
|
btfsc 0x20, 0 ; copy from bit 0
|
||||||
|
bsf 0x20, 1 ; (if set)
|
||||||
|
bsf 0x20, 4 ; run console
|
||||||
|
bcf 0x20, 2 ; run slave
|
||||||
|
movf 0x20, w
|
||||||
|
movwf GPIO
|
||||||
|
movf GPIO, w ; read input
|
||||||
|
movwf 0x42 ; store input
|
||||||
|
movlw 0x10
|
||||||
|
movwf GPIO ; reset GPIO
|
||||||
|
call checkkey
|
||||||
|
movlw 0x10 ; wait 52 cycles
|
||||||
|
call wait
|
||||||
|
btfsc GPIO, 0 ; both pins must be low...
|
||||||
|
goto die
|
||||||
|
btfsc GPIO, 1 ; ...when no bit transfer takes place
|
||||||
|
goto die ; if not -> lock cic error state -> die
|
||||||
|
incf FSR, f ; next one
|
||||||
|
movlw 0xf
|
||||||
|
andwf FSR, w
|
||||||
|
btfss STATUS, Z
|
||||||
|
goto loop1
|
||||||
|
movlw 0x1 ; wait 7
|
||||||
|
call wait ;
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
call mangle
|
||||||
|
call mangle
|
||||||
|
call mangle
|
||||||
|
btfsc 0x37, 0
|
||||||
|
goto swap
|
||||||
|
banksel TRISIO
|
||||||
|
bsf TRISIO, 0
|
||||||
|
bcf TRISIO, 1
|
||||||
|
goto swapskip
|
||||||
|
swap
|
||||||
|
banksel TRISIO
|
||||||
|
bcf TRISIO, 0
|
||||||
|
bsf TRISIO, 1
|
||||||
|
nop
|
||||||
|
swapskip
|
||||||
|
banksel GPIO
|
||||||
|
btfsc GPIO, 3 ; poll master reset
|
||||||
|
goto rst
|
||||||
|
clrf 0x43 ; don't check key region anymore
|
||||||
|
movf 0x37, w
|
||||||
|
andlw 0xf
|
||||||
|
btfss STATUS, Z
|
||||||
|
goto loop0
|
||||||
|
goto loop
|
||||||
|
|
||||||
|
; --------calculate new seeds--------
|
||||||
|
; had to be unrolled because PIC has an inefficient way of handling
|
||||||
|
; indirect access, no post increment, no swap, etc.
|
||||||
|
mangle
|
||||||
|
call mangle_lock
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
mangle_key
|
||||||
|
movf 0x2f, w
|
||||||
|
movwf 0x20
|
||||||
|
mangle_key_loop
|
||||||
|
addlw 0x1
|
||||||
|
addwf 0x21, f
|
||||||
|
movf 0x22, w
|
||||||
|
movwf 0x40
|
||||||
|
movf 0x21, w
|
||||||
|
addwf 0x22, f
|
||||||
|
incf 0x22, f
|
||||||
|
comf 0x22, f
|
||||||
|
movf 0x23, w
|
||||||
|
movwf 0x41 ; store 23 to 41
|
||||||
|
movlw 0xf
|
||||||
|
andwf 0x23, f
|
||||||
|
movf 0x40, w ; add 40(22 old)+23+#1 and skip if carry
|
||||||
|
andlw 0xf
|
||||||
|
addwf 0x23, f
|
||||||
|
incf 0x23, f
|
||||||
|
btfsc 0x23, 4
|
||||||
|
goto mangle_key_withskip
|
||||||
|
mangle_key_withoutskip
|
||||||
|
movf 0x41, w ; restore 23
|
||||||
|
addwf 0x24, f ; add to 24
|
||||||
|
movf 0x25, w
|
||||||
|
movwf 0x40 ; save 25 to 40
|
||||||
|
movf 0x24, w
|
||||||
|
addwf 0x25, f
|
||||||
|
movf 0x26, w
|
||||||
|
movwf 0x41 ; save 26 to 41
|
||||||
|
movf 0x40, w ; restore 25
|
||||||
|
andlw 0xf ; mask nibble
|
||||||
|
addlw 0x8 ; add #8 to HIGH nibble
|
||||||
|
movwf 0x40
|
||||||
|
btfss 0x40, 4 ; skip if carry to 5th bit
|
||||||
|
addwf 0x26, w
|
||||||
|
movwf 0x26
|
||||||
|
|
||||||
|
movf 0x41, w ; restore 26
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x27, f ; add to 27
|
||||||
|
|
||||||
|
movf 0x27, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x28, f ; add to 28
|
||||||
|
|
||||||
|
movf 0x28, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x29, f ; add to 29
|
||||||
|
|
||||||
|
movf 0x29, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2a, f ; add to 2a
|
||||||
|
|
||||||
|
movf 0x2a, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2b, f ; add to 2b
|
||||||
|
|
||||||
|
movf 0x2b, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2c, f ; add to 2c
|
||||||
|
|
||||||
|
movf 0x2c, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2d, f ; add to 2d
|
||||||
|
|
||||||
|
movf 0x2d, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2e, f ; add to 2e
|
||||||
|
|
||||||
|
movf 0x2e, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2f, f ; add to 2f
|
||||||
|
|
||||||
|
movf 0x20, w ; restore original 0xf
|
||||||
|
andlw 0xf
|
||||||
|
addlw 0xf
|
||||||
|
movwf 0x20
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
btfss 0x20, 4 ; skip if half-byte carry
|
||||||
|
goto mangle_return ; +2 cycles in return
|
||||||
|
nop
|
||||||
|
goto mangle_key_loop
|
||||||
|
; 69 when goto, 69 when return
|
||||||
|
; CIC has 78 -> 9 nops
|
||||||
|
|
||||||
|
mangle_key_withskip
|
||||||
|
movf 0x41, w ; restore 23
|
||||||
|
addwf 0x23, f ; add to 23
|
||||||
|
movf 0x24, w
|
||||||
|
movwf 0x40 ; save 24 to 40
|
||||||
|
movf 0x23, w
|
||||||
|
addwf 0x24, f
|
||||||
|
movf 0x25, w
|
||||||
|
movwf 0x41 ; save 25 to 41
|
||||||
|
movf 0x40, w ; restore 24
|
||||||
|
andlw 0xf ; mask nibble
|
||||||
|
addlw 0x8 ; add #8 to HIGH nibble
|
||||||
|
movwf 0x40
|
||||||
|
btfss 0x40, 4 ; skip if carry to 5th bit
|
||||||
|
addwf 0x25, w
|
||||||
|
movwf 0x25
|
||||||
|
|
||||||
|
movf 0x41, w ; restore 25
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x26, f ; add to 26
|
||||||
|
|
||||||
|
movf 0x26, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x27, f ; add to 27
|
||||||
|
|
||||||
|
movf 0x27, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x28, f ; add to 28
|
||||||
|
|
||||||
|
movf 0x28, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x29, f ; add to 29
|
||||||
|
|
||||||
|
movf 0x29, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2a, f ; add to 2a
|
||||||
|
|
||||||
|
movf 0x2a, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2b, f ; add to 2b
|
||||||
|
|
||||||
|
movf 0x2b, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2c, f ; add to 2c
|
||||||
|
|
||||||
|
movf 0x2c, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2d, f ; add to 2d
|
||||||
|
|
||||||
|
movf 0x2d, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2e, f ; add to 2e
|
||||||
|
|
||||||
|
movf 0x2e, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x2f, f ; add to 2f
|
||||||
|
|
||||||
|
movf 0x20, w ; restore original 0xf
|
||||||
|
andlw 0xf
|
||||||
|
addlw 0xf
|
||||||
|
movwf 0x20
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
btfss 0x20, 4 ; skip if half-byte carry
|
||||||
|
goto mangle_return ; +2 cycles in return
|
||||||
|
nop
|
||||||
|
goto mangle_key_loop
|
||||||
|
mangle_return
|
||||||
|
return
|
||||||
|
; 73 when goto, 73 when return
|
||||||
|
; CIC has 84 -> 11 nops
|
||||||
|
|
||||||
|
mangle_lock
|
||||||
|
movf 0x3f, w
|
||||||
|
movwf 0x30
|
||||||
|
mangle_lock_loop
|
||||||
|
addlw 0x1
|
||||||
|
addwf 0x31, f
|
||||||
|
movf 0x32, w
|
||||||
|
movwf 0x40
|
||||||
|
movf 0x31, w
|
||||||
|
addwf 0x32, f
|
||||||
|
incf 0x32, f
|
||||||
|
comf 0x32, f
|
||||||
|
movf 0x33, w
|
||||||
|
movwf 0x41 ; store 33 to 41
|
||||||
|
movlw 0xf
|
||||||
|
andwf 0x33, f
|
||||||
|
movf 0x40, w ; add 40(32 old)+33+#1 and skip if carry
|
||||||
|
andlw 0xf
|
||||||
|
addwf 0x33, f
|
||||||
|
incf 0x33, f
|
||||||
|
btfsc 0x33, 4
|
||||||
|
goto mangle_lock_withskip
|
||||||
|
mangle_lock_withoutskip
|
||||||
|
movf 0x41, w ; restore 33
|
||||||
|
addwf 0x34, f ; add to 34
|
||||||
|
movf 0x35, w
|
||||||
|
movwf 0x40 ; save 35 to 40
|
||||||
|
movf 0x34, w
|
||||||
|
addwf 0x35, f
|
||||||
|
movf 0x36, w
|
||||||
|
movwf 0x41 ; save 36 to 41
|
||||||
|
movf 0x40, w ; restore 35
|
||||||
|
andlw 0xf ; mask nibble
|
||||||
|
addlw 0x8 ; add #8 to HIGH nibble
|
||||||
|
movwf 0x40
|
||||||
|
btfss 0x40, 4 ; skip if carry to 5th bit
|
||||||
|
addwf 0x36, w
|
||||||
|
movwf 0x36
|
||||||
|
|
||||||
|
movf 0x41, w ; restore 36
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x37, f ; add to 37
|
||||||
|
|
||||||
|
movf 0x37, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x38, f ; add to 38
|
||||||
|
|
||||||
|
movf 0x38, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x39, f ; add to 39
|
||||||
|
|
||||||
|
movf 0x39, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3a, f ; add to 3a
|
||||||
|
|
||||||
|
movf 0x3a, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3b, f ; add to 3b
|
||||||
|
|
||||||
|
movf 0x3b, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3c, f ; add to 3c
|
||||||
|
|
||||||
|
movf 0x3c, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3d, f ; add to 3d
|
||||||
|
|
||||||
|
movf 0x3d, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3e, f ; add to 3e
|
||||||
|
|
||||||
|
movf 0x3e, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3f, f ; add to 3f
|
||||||
|
|
||||||
|
movf 0x30, w ; restore original 0xf
|
||||||
|
andlw 0xf
|
||||||
|
addlw 0xf
|
||||||
|
movwf 0x30
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
btfss 0x30, 4 ; skip if half-byte carry
|
||||||
|
goto mangle_return
|
||||||
|
nop
|
||||||
|
goto mangle_lock_loop
|
||||||
|
; 69 when goto, 69 when return
|
||||||
|
; CIC has 78 -> 9 nops
|
||||||
|
|
||||||
|
mangle_lock_withskip
|
||||||
|
movf 0x41, w ; restore 33
|
||||||
|
addwf 0x33, f ; add to 33
|
||||||
|
movf 0x34, w
|
||||||
|
movwf 0x40 ; save 34 to 40
|
||||||
|
movf 0x33, w
|
||||||
|
addwf 0x34, f
|
||||||
|
movf 0x35, w
|
||||||
|
movwf 0x41 ; save 35 to 41
|
||||||
|
movf 0x40, w ; restore 34
|
||||||
|
andlw 0xf ; mask nibble
|
||||||
|
addlw 0x8 ; add #8 to HIGH nibble
|
||||||
|
movwf 0x40
|
||||||
|
btfss 0x40, 4 ; skip if carry to 5th bit
|
||||||
|
addwf 0x35, w
|
||||||
|
movwf 0x35
|
||||||
|
|
||||||
|
movf 0x41, w ; restore 35
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x36, f ; add to 36
|
||||||
|
|
||||||
|
movf 0x36, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x37, f ; add to 37
|
||||||
|
|
||||||
|
movf 0x37, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x38, f ; add to 38
|
||||||
|
|
||||||
|
movf 0x38, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x39, f ; add to 39
|
||||||
|
|
||||||
|
movf 0x39, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3a, f ; add to 3a
|
||||||
|
|
||||||
|
movf 0x3a, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3b, f ; add to 3b
|
||||||
|
|
||||||
|
movf 0x3b, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3c, f ; add to 3c
|
||||||
|
|
||||||
|
movf 0x3c, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3d, f ; add to 3d
|
||||||
|
|
||||||
|
movf 0x3d, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3e, f ; add to 3e
|
||||||
|
|
||||||
|
movf 0x3e, w ;
|
||||||
|
addlw 0x1 ; inc
|
||||||
|
addwf 0x3f, f ; add to 3f
|
||||||
|
|
||||||
|
movf 0x30, w ; restore original 0xf
|
||||||
|
andlw 0xf
|
||||||
|
addlw 0xf
|
||||||
|
movwf 0x30
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
btfss 0x30, 4 ; skip if half-byte carry
|
||||||
|
goto mangle_return
|
||||||
|
nop
|
||||||
|
goto mangle_lock_loop
|
||||||
|
; 73 when goto, 73 when return
|
||||||
|
; CIC has 84 -> 11 nops
|
||||||
|
|
||||||
|
; --------wait: 3*(W-1)+7 cycles (including call+return). W=0 -> 256!--------
|
||||||
|
wait
|
||||||
|
movwf 0x4f
|
||||||
|
wait0 decfsz 0x4f, f
|
||||||
|
goto wait0
|
||||||
|
return
|
||||||
|
|
||||||
|
; --------wait long: 8+(3*(w-1))+(772*w). W=0 -> 256!--------
|
||||||
|
longwait
|
||||||
|
movwf 0x4e
|
||||||
|
clrw
|
||||||
|
longwait0
|
||||||
|
call wait
|
||||||
|
decfsz 0x4e, f
|
||||||
|
goto longwait0
|
||||||
|
return
|
||||||
|
|
||||||
|
; --------die (do nothing, wait for reset)--------
|
||||||
|
die
|
||||||
|
btfsc GPIO, 3
|
||||||
|
goto rst
|
||||||
|
goto die
|
||||||
|
|
||||||
|
; --------check the key input and change "region" when appropriate--------
|
||||||
|
; --------requires 17 cycles (incl. call+return)
|
||||||
|
checkkey
|
||||||
|
btfss 0x43, 0 ; first time?
|
||||||
|
goto checkkey_nocheck ; if not, just burn some cycles
|
||||||
|
movlw 0x22 ; are we at the correct stream offset?
|
||||||
|
xorwf FSR, w
|
||||||
|
btfss STATUS, Z ; if not equal:
|
||||||
|
goto checkkey_nocheck2 ; burn some cycles less.
|
||||||
|
; if equal do the check
|
||||||
|
btfss 0x42, 0 ; if value from slave is set it's a 411
|
||||||
|
goto check_413
|
||||||
|
check_411
|
||||||
|
nop ; to compensate for untaken branch
|
||||||
|
movlw 0x9
|
||||||
|
goto check_save
|
||||||
|
check_413
|
||||||
|
movlw 0x6
|
||||||
|
goto check_save
|
||||||
|
|
||||||
|
checkkey_nocheck
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
checkkey_nocheck2
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
goto check_done
|
||||||
|
check_save
|
||||||
|
movwf 0x32
|
||||||
|
check_done
|
||||||
|
return
|
||||||
|
end
|
||||||
|
; ------------------------------------------------------------------------
|
||||||
BIN
cic/supercic/1chip-5060-back.jpg
Normal file
BIN
cic/supercic/1chip-5060-back.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 192 KiB |
BIN
cic/supercic/1chip-5060-front.jpg
Normal file
BIN
cic/supercic/1chip-5060-front.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 188 KiB |
BIN
cic/supercic/1chip-5060.pdf
Normal file
BIN
cic/supercic/1chip-5060.pdf
Normal file
Binary file not shown.
401
cic/supercic/1chip-5060.sch
Normal file
401
cic/supercic/1chip-5060.sch
Normal file
@@ -0,0 +1,401 @@
|
|||||||
|
EESchema Schematic File Version 2 date Mon 07 Jun 2010 05:23:48 AM CEST
|
||||||
|
LIBS:power
|
||||||
|
LIBS:device
|
||||||
|
LIBS:transistors
|
||||||
|
LIBS:conn
|
||||||
|
LIBS:linear
|
||||||
|
LIBS:regul
|
||||||
|
LIBS:74xx
|
||||||
|
LIBS:cmos4000
|
||||||
|
LIBS:adc-dac
|
||||||
|
LIBS:memory
|
||||||
|
LIBS:xilinx
|
||||||
|
LIBS:special
|
||||||
|
LIBS:microcontrollers
|
||||||
|
LIBS:dsp
|
||||||
|
LIBS:microchip
|
||||||
|
LIBS:analog_switches
|
||||||
|
LIBS:motorola
|
||||||
|
LIBS:texas
|
||||||
|
LIBS:intel
|
||||||
|
LIBS:audio
|
||||||
|
LIBS:interface
|
||||||
|
LIBS:digital-audio
|
||||||
|
LIBS:philips
|
||||||
|
LIBS:display
|
||||||
|
LIBS:cypress
|
||||||
|
LIBS:siliconi
|
||||||
|
LIBS:opto
|
||||||
|
LIBS:atmel
|
||||||
|
LIBS:contrib
|
||||||
|
LIBS:valves
|
||||||
|
EELAYER 24 0
|
||||||
|
EELAYER END
|
||||||
|
$Descr A4 11700 8267
|
||||||
|
Sheet 1 1
|
||||||
|
Title "1chip-5060.sch"
|
||||||
|
Date "7 jun 2010"
|
||||||
|
Rev "A"
|
||||||
|
Comp "ikari_01"
|
||||||
|
Comment1 ""
|
||||||
|
Comment2 ""
|
||||||
|
Comment3 ""
|
||||||
|
Comment4 ""
|
||||||
|
$EndDescr
|
||||||
|
Text Notes 9750 2250 0 60 ~ 0
|
||||||
|
S-CPUN pin 111\n(lifted / angehoben)
|
||||||
|
Connection ~ 6400 2250
|
||||||
|
Wire Wire Line
|
||||||
|
9700 2250 4650 2250
|
||||||
|
Wire Wire Line
|
||||||
|
6700 2800 6400 2800
|
||||||
|
Wire Wire Line
|
||||||
|
6400 2800 6400 2250
|
||||||
|
Wire Wire Line
|
||||||
|
4650 2250 4650 2000
|
||||||
|
Wire Wire Line
|
||||||
|
8000 3700 8000 2900
|
||||||
|
Wire Wire Line
|
||||||
|
8000 3700 8100 3700
|
||||||
|
Wire Wire Line
|
||||||
|
6700 4800 5700 4800
|
||||||
|
Connection ~ 4650 2000
|
||||||
|
Wire Wire Line
|
||||||
|
4850 1700 4850 1800
|
||||||
|
Wire Wire Line
|
||||||
|
4850 1800 4950 1800
|
||||||
|
Wire Wire Line
|
||||||
|
8000 2900 7900 2900
|
||||||
|
Wire Wire Line
|
||||||
|
2800 6100 2800 6200
|
||||||
|
Connection ~ 2800 5600
|
||||||
|
Wire Wire Line
|
||||||
|
2800 5700 2800 5300
|
||||||
|
Wire Wire Line
|
||||||
|
4650 4800 4800 4800
|
||||||
|
Wire Wire Line
|
||||||
|
2750 5600 2800 5600
|
||||||
|
Wire Wire Line
|
||||||
|
2950 4800 3100 4800
|
||||||
|
Wire Wire Line
|
||||||
|
3100 4800 3100 5300
|
||||||
|
Wire Wire Line
|
||||||
|
3100 5300 2800 5300
|
||||||
|
Wire Wire Line
|
||||||
|
2200 4300 2200 4400
|
||||||
|
Connection ~ 2200 3800
|
||||||
|
Wire Wire Line
|
||||||
|
2200 3900 2200 3500
|
||||||
|
Wire Wire Line
|
||||||
|
3600 3000 3750 3000
|
||||||
|
Wire Wire Line
|
||||||
|
2250 3800 2200 3800
|
||||||
|
Wire Wire Line
|
||||||
|
2200 3500 1900 3500
|
||||||
|
Wire Wire Line
|
||||||
|
1900 3500 1900 3000
|
||||||
|
Wire Wire Line
|
||||||
|
1900 3000 2050 3000
|
||||||
|
Wire Wire Line
|
||||||
|
3100 3500 2800 3500
|
||||||
|
Wire Wire Line
|
||||||
|
3100 3500 3100 3000
|
||||||
|
Wire Wire Line
|
||||||
|
3100 3000 2950 3000
|
||||||
|
Wire Wire Line
|
||||||
|
2750 3800 2800 3800
|
||||||
|
Wire Wire Line
|
||||||
|
4650 3000 4800 3000
|
||||||
|
Wire Wire Line
|
||||||
|
2800 3500 2800 3900
|
||||||
|
Connection ~ 2800 3800
|
||||||
|
Wire Wire Line
|
||||||
|
2800 4300 2800 4400
|
||||||
|
Wire Wire Line
|
||||||
|
2050 4800 1900 4800
|
||||||
|
Wire Wire Line
|
||||||
|
1900 4800 1900 5300
|
||||||
|
Wire Wire Line
|
||||||
|
1900 5300 2200 5300
|
||||||
|
Wire Wire Line
|
||||||
|
2250 5600 2200 5600
|
||||||
|
Wire Wire Line
|
||||||
|
3600 4800 3750 4800
|
||||||
|
Wire Wire Line
|
||||||
|
2200 5300 2200 5700
|
||||||
|
Connection ~ 2200 5600
|
||||||
|
Wire Wire Line
|
||||||
|
2200 6100 2200 6200
|
||||||
|
Wire Wire Line
|
||||||
|
6700 3000 5700 3000
|
||||||
|
Wire Wire Line
|
||||||
|
4950 2000 4300 2000
|
||||||
|
Wire Wire Line
|
||||||
|
6150 1900 6550 1900
|
||||||
|
Wire Wire Line
|
||||||
|
6550 1900 6550 4600
|
||||||
|
Wire Wire Line
|
||||||
|
6550 4600 6700 4600
|
||||||
|
Wire Wire Line
|
||||||
|
7900 4700 8000 4700
|
||||||
|
Wire Wire Line
|
||||||
|
8000 4700 8000 3900
|
||||||
|
Wire Wire Line
|
||||||
|
8000 3900 8100 3900
|
||||||
|
Wire Wire Line
|
||||||
|
9300 3800 9700 3800
|
||||||
|
Text Notes 9750 3800 0 60 ~ 0
|
||||||
|
X1 right pin / rechter Pin\n(S-CPUN pin 9)
|
||||||
|
$Comp
|
||||||
|
L +5V #PWR?
|
||||||
|
U 1 1 4C0C42E1
|
||||||
|
P 4850 1700
|
||||||
|
F 0 "#PWR?" H 4850 1790 20 0001 C CNN
|
||||||
|
F 1 "+5V" H 4850 1790 30 0000 C CNN
|
||||||
|
1 4850 1700
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
Text Notes 5700 4750 0 60 ~ 0
|
||||||
|
NTSC clock
|
||||||
|
Text Notes 5700 2950 0 60 ~ 0
|
||||||
|
PAL clock
|
||||||
|
Text Notes 3800 2550 0 60 ~ 0
|
||||||
|
SuperCIC
|
||||||
|
$Comp
|
||||||
|
L DIL14 U3
|
||||||
|
U 1 1 4C0C3DF6
|
||||||
|
P 3950 2100
|
||||||
|
F 0 "U3" H 3950 2500 60 0000 C CNN
|
||||||
|
F 1 "PIC16F630" V 3950 2100 50 0000 C CNN
|
||||||
|
1 3950 2100
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
Text Notes 2850 1200 0 60 ~ 0
|
||||||
|
©2010 ikari_01
|
||||||
|
Text Notes 650 1100 0 300 ~ 60
|
||||||
|
1chip / junior switchless 50/60Hz mod
|
||||||
|
Text Notes 2850 5400 0 60 ~ 0
|
||||||
|
NTSC Quartz
|
||||||
|
Text Notes 2850 3600 0 60 ~ 0
|
||||||
|
PAL Quartz
|
||||||
|
Text Notes 6900 1550 0 60 ~ 0
|
||||||
|
Switch / Schalter
|
||||||
|
Text Notes 1900 2550 0 60 ~ 0
|
||||||
|
Oscillators / Oszillatoren
|
||||||
|
$Comp
|
||||||
|
L GND #PWR?
|
||||||
|
U 1 1 4C0C3CD2
|
||||||
|
P 2800 6200
|
||||||
|
F 0 "#PWR?" H 2800 6200 30 0001 C CNN
|
||||||
|
F 1 "GND" H 2800 6130 30 0001 C CNN
|
||||||
|
1 2800 6200
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L GND #PWR?
|
||||||
|
U 1 1 4C0C3CCF
|
||||||
|
P 2200 6200
|
||||||
|
F 0 "#PWR?" H 2200 6200 30 0001 C CNN
|
||||||
|
F 1 "GND" H 2200 6130 30 0001 C CNN
|
||||||
|
1 2200 6200
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L GND #PWR?
|
||||||
|
U 1 1 4C0C3C02
|
||||||
|
P 2800 4400
|
||||||
|
F 0 "#PWR?" H 2800 4400 30 0001 C CNN
|
||||||
|
F 1 "GND" H 2800 4330 30 0001 C CNN
|
||||||
|
1 2800 4400
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L GND #PWR?
|
||||||
|
U 1 1 4C0C3BFF
|
||||||
|
P 2200 4400
|
||||||
|
F 0 "#PWR?" H 2200 4400 30 0001 C CNN
|
||||||
|
F 1 "GND" H 2200 4330 30 0001 C CNN
|
||||||
|
1 2200 4400
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L C C4
|
||||||
|
U 1 1 4C0C3BC3
|
||||||
|
P 2800 5900
|
||||||
|
F 0 "C4" H 2850 6000 50 0000 L CNN
|
||||||
|
F 1 "22p" H 2850 5800 50 0000 L CNN
|
||||||
|
1 2800 5900
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L C C3
|
||||||
|
U 1 1 4C0C3BC2
|
||||||
|
P 2200 5900
|
||||||
|
F 0 "C3" H 2250 6000 50 0000 L CNN
|
||||||
|
F 1 "22p" H 2250 5800 50 0000 L CNN
|
||||||
|
1 2200 5900
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L C C2
|
||||||
|
U 1 1 4C0C3BC1
|
||||||
|
P 2800 4100
|
||||||
|
F 0 "C2" H 2850 4200 50 0000 L CNN
|
||||||
|
F 1 "22p" H 2850 4000 50 0000 L CNN
|
||||||
|
1 2800 4100
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L C C1
|
||||||
|
U 1 1 4C0C3BBF
|
||||||
|
P 2200 4100
|
||||||
|
F 0 "C1" H 2250 4200 50 0000 L CNN
|
||||||
|
F 1 "22p" H 2250 4000 50 0000 L CNN
|
||||||
|
1 2200 4100
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L R R4
|
||||||
|
U 1 1 4C0C3B9A
|
||||||
|
P 3350 4800
|
||||||
|
F 0 "R4" V 3430 4800 50 0000 C CNN
|
||||||
|
F 1 "330" V 3350 4800 50 0000 C CNN
|
||||||
|
1 3350 4800
|
||||||
|
0 1 1 0
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L R R3
|
||||||
|
U 1 1 4C0C3B98
|
||||||
|
P 2500 5600
|
||||||
|
F 0 "R3" V 2580 5600 50 0000 C CNN
|
||||||
|
F 1 "1M" V 2500 5600 50 0000 C CNN
|
||||||
|
1 2500 5600
|
||||||
|
0 1 1 0
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L R R2
|
||||||
|
U 1 1 4C0C3B96
|
||||||
|
P 3350 3000
|
||||||
|
F 0 "R2" V 3430 3000 50 0000 C CNN
|
||||||
|
F 1 "330" V 3350 3000 50 0000 C CNN
|
||||||
|
1 3350 3000
|
||||||
|
0 1 1 0
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L R R1
|
||||||
|
U 1 1 4C0C3B93
|
||||||
|
P 2500 3800
|
||||||
|
F 0 "R1" V 2580 3800 50 0000 C CNN
|
||||||
|
F 1 "1M" V 2500 3800 50 0000 C CNN
|
||||||
|
1 2500 3800
|
||||||
|
0 1 1 0
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L CRYSTAL X1
|
||||||
|
U 1 1 4C0C3B5D
|
||||||
|
P 2500 3500
|
||||||
|
F 0 "X1" H 2500 3650 60 0000 C CNN
|
||||||
|
F 1 "17.734MHz" H 2500 3350 60 0000 C CNN
|
||||||
|
1 2500 3500
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L CRYSTAL X2
|
||||||
|
U 1 1 4C0C3B46
|
||||||
|
P 2500 5300
|
||||||
|
F 0 "X2" H 2500 5450 60 0000 C CNN
|
||||||
|
F 1 "21.477MHz" H 2500 5150 60 0000 C CNN
|
||||||
|
1 2500 5300
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L 74HC04 U2
|
||||||
|
U 6 1 4C0C2CC2
|
||||||
|
P 2500 4800
|
||||||
|
F 0 "U2" H 2650 4900 40 0000 C CNN
|
||||||
|
F 1 "74HCU04" H 2700 4700 40 0000 C CNN
|
||||||
|
6 2500 4800
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L 74HC04 U2
|
||||||
|
U 5 1 4C0C2CC0
|
||||||
|
P 4200 4800
|
||||||
|
F 0 "U2" H 4350 4900 40 0000 C CNN
|
||||||
|
F 1 "74HCU04" H 4400 4700 40 0000 C CNN
|
||||||
|
5 4200 4800
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L 74HC04 U2
|
||||||
|
U 4 1 4C0C2CBD
|
||||||
|
P 5250 4800
|
||||||
|
F 0 "U2" H 5400 4900 40 0000 C CNN
|
||||||
|
F 1 "74HCU04" H 5450 4700 40 0000 C CNN
|
||||||
|
4 5250 4800
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L 74HC04 U2
|
||||||
|
U 3 1 4C0C2CBA
|
||||||
|
P 5250 3000
|
||||||
|
F 0 "U2" H 5400 3100 40 0000 C CNN
|
||||||
|
F 1 "74HCU04" H 5450 2900 40 0000 C CNN
|
||||||
|
3 5250 3000
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L 74HC04 U2
|
||||||
|
U 2 1 4C0BF549
|
||||||
|
P 4200 3000
|
||||||
|
F 0 "U2" H 4350 3100 40 0000 C CNN
|
||||||
|
F 1 "74HCU04" H 4400 2900 40 0000 C CNN
|
||||||
|
2 4200 3000
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L 74HC04 U2
|
||||||
|
U 1 1 4C0BF539
|
||||||
|
P 2500 3000
|
||||||
|
F 0 "U2" H 2650 3100 40 0000 C CNN
|
||||||
|
F 1 "74HCU04" H 2700 2900 40 0000 C CNN
|
||||||
|
1 2500 3000
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L 7400 U1
|
||||||
|
U 4 1 4C0BF3E9
|
||||||
|
P 5550 1900
|
||||||
|
F 0 "U1" H 5550 1950 60 0000 C CNN
|
||||||
|
F 1 "7400" H 5550 1800 60 0000 C CNN
|
||||||
|
4 5550 1900
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L 7400 U1
|
||||||
|
U 3 1 4C0BF3D0
|
||||||
|
P 7300 4700
|
||||||
|
F 0 "U1" H 7300 4750 60 0000 C CNN
|
||||||
|
F 1 "7400" H 7300 4600 60 0000 C CNN
|
||||||
|
3 7300 4700
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L 7400 U1
|
||||||
|
U 2 1 4C0BF3C9
|
||||||
|
P 8700 3800
|
||||||
|
F 0 "U1" H 8700 3850 60 0000 C CNN
|
||||||
|
F 1 "7400" H 8700 3700 60 0000 C CNN
|
||||||
|
2 8700 3800
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L 7400 U1
|
||||||
|
U 1 1 4C0BEF68
|
||||||
|
P 7300 2900
|
||||||
|
F 0 "U1" H 7300 2950 60 0000 C CNN
|
||||||
|
F 1 "7400" H 7300 2800 60 0000 C CNN
|
||||||
|
1 7300 2900
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$EndSCHEMATC
|
||||||
1102
cic/supercic/supercic-lock.asm
Normal file
1102
cic/supercic/supercic-lock.asm
Normal file
File diff suppressed because it is too large
Load Diff
BIN
cic/supercic/supercic-snes.jpg
Normal file
BIN
cic/supercic/supercic-snes.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 237 KiB |
BIN
cic/supercic/supercic.png
Normal file
BIN
cic/supercic/supercic.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
357
cic/supercic/supercic.sch
Normal file
357
cic/supercic/supercic.sch
Normal file
@@ -0,0 +1,357 @@
|
|||||||
|
EESchema Schematic File Version 2 date Sun 06 Jun 2010 03:26:33 AM CEST
|
||||||
|
LIBS:power
|
||||||
|
LIBS:device
|
||||||
|
LIBS:transistors
|
||||||
|
LIBS:conn
|
||||||
|
LIBS:linear
|
||||||
|
LIBS:regul
|
||||||
|
LIBS:74xx
|
||||||
|
LIBS:cmos4000
|
||||||
|
LIBS:adc-dac
|
||||||
|
LIBS:memory
|
||||||
|
LIBS:xilinx
|
||||||
|
LIBS:special
|
||||||
|
LIBS:microcontrollers
|
||||||
|
LIBS:dsp
|
||||||
|
LIBS:microchip
|
||||||
|
LIBS:analog_switches
|
||||||
|
LIBS:motorola
|
||||||
|
LIBS:texas
|
||||||
|
LIBS:intel
|
||||||
|
LIBS:audio
|
||||||
|
LIBS:interface
|
||||||
|
LIBS:digital-audio
|
||||||
|
LIBS:philips
|
||||||
|
LIBS:display
|
||||||
|
LIBS:cypress
|
||||||
|
LIBS:siliconi
|
||||||
|
LIBS:opto
|
||||||
|
LIBS:atmel
|
||||||
|
LIBS:contrib
|
||||||
|
LIBS:valves
|
||||||
|
LIBS:sd2snes-cache
|
||||||
|
EELAYER 24 0
|
||||||
|
EELAYER END
|
||||||
|
$Descr A4 11700 8267
|
||||||
|
Sheet 1 1
|
||||||
|
Title "SuperCIC lock - other connections"
|
||||||
|
Date "6 jun 2010"
|
||||||
|
Rev "A"
|
||||||
|
Comp "ikari_01"
|
||||||
|
Comment1 ""
|
||||||
|
Comment2 ""
|
||||||
|
Comment3 ""
|
||||||
|
Comment4 ""
|
||||||
|
$EndDescr
|
||||||
|
Text Notes 1800 1700 0 60 ~ 0
|
||||||
|
©2010 ikari_01
|
||||||
|
Text Notes 1100 1900 0 100 ~ 0
|
||||||
|
"SNES" connections: see SNES connection diagram
|
||||||
|
Wire Wire Line
|
||||||
|
3200 6150 3200 6550
|
||||||
|
Wire Wire Line
|
||||||
|
2900 5750 2900 5550
|
||||||
|
Wire Wire Line
|
||||||
|
3200 5750 3200 5650
|
||||||
|
Wire Wire Line
|
||||||
|
3200 5650 2600 5650
|
||||||
|
Wire Wire Line
|
||||||
|
2600 5650 2600 5750
|
||||||
|
Wire Wire Line
|
||||||
|
3550 6450 2900 6450
|
||||||
|
Wire Wire Line
|
||||||
|
4050 6450 4550 6450
|
||||||
|
Wire Wire Line
|
||||||
|
5250 6550 5450 6550
|
||||||
|
Wire Wire Line
|
||||||
|
5250 6350 5450 6350
|
||||||
|
Wire Wire Line
|
||||||
|
5250 6150 5450 6150
|
||||||
|
Wire Wire Line
|
||||||
|
4550 6150 4350 6150
|
||||||
|
Wire Wire Line
|
||||||
|
4450 6050 4550 6050
|
||||||
|
Wire Wire Line
|
||||||
|
5250 6050 5350 6050
|
||||||
|
Wire Wire Line
|
||||||
|
4550 6250 4350 6250
|
||||||
|
Wire Wire Line
|
||||||
|
4550 6650 4450 6650
|
||||||
|
Wire Wire Line
|
||||||
|
5250 6250 5450 6250
|
||||||
|
Wire Wire Line
|
||||||
|
5250 6450 5450 6450
|
||||||
|
Wire Wire Line
|
||||||
|
5250 6650 5450 6650
|
||||||
|
Wire Wire Line
|
||||||
|
4550 6350 4450 6350
|
||||||
|
Connection ~ 4450 6050
|
||||||
|
Wire Wire Line
|
||||||
|
4050 6550 4550 6550
|
||||||
|
Wire Wire Line
|
||||||
|
3200 6550 3550 6550
|
||||||
|
Wire Wire Line
|
||||||
|
5350 6050 5350 7250
|
||||||
|
Wire Wire Line
|
||||||
|
5350 3800 5350 2600
|
||||||
|
Connection ~ 3050 3700
|
||||||
|
Wire Wire Line
|
||||||
|
3050 3800 3050 3700
|
||||||
|
Wire Wire Line
|
||||||
|
3550 3100 3200 3100
|
||||||
|
Wire Wire Line
|
||||||
|
3200 3100 3200 3200
|
||||||
|
Wire Wire Line
|
||||||
|
4050 3100 4550 3100
|
||||||
|
Connection ~ 4450 2600
|
||||||
|
Wire Wire Line
|
||||||
|
4450 2450 4450 2900
|
||||||
|
Wire Wire Line
|
||||||
|
4450 2900 4550 2900
|
||||||
|
Wire Wire Line
|
||||||
|
5250 3200 5450 3200
|
||||||
|
Wire Wire Line
|
||||||
|
5250 3000 5450 3000
|
||||||
|
Wire Wire Line
|
||||||
|
5250 2800 5450 2800
|
||||||
|
Wire Wire Line
|
||||||
|
4550 3200 4450 3200
|
||||||
|
Wire Wire Line
|
||||||
|
4550 2800 4350 2800
|
||||||
|
Wire Wire Line
|
||||||
|
5350 2600 5250 2600
|
||||||
|
Wire Wire Line
|
||||||
|
4550 2600 4450 2600
|
||||||
|
Wire Wire Line
|
||||||
|
4550 2700 4350 2700
|
||||||
|
Wire Wire Line
|
||||||
|
5250 2700 5450 2700
|
||||||
|
Wire Wire Line
|
||||||
|
5250 2900 5450 2900
|
||||||
|
Wire Wire Line
|
||||||
|
5250 3100 5450 3100
|
||||||
|
Wire Wire Line
|
||||||
|
4050 3000 4550 3000
|
||||||
|
Wire Wire Line
|
||||||
|
3550 3000 2900 3000
|
||||||
|
Wire Wire Line
|
||||||
|
2900 3000 2900 3200
|
||||||
|
Wire Wire Line
|
||||||
|
2900 3600 2900 3700
|
||||||
|
Wire Wire Line
|
||||||
|
2900 3700 3200 3700
|
||||||
|
Wire Wire Line
|
||||||
|
3200 3700 3200 3600
|
||||||
|
Wire Wire Line
|
||||||
|
4450 3200 4450 3800
|
||||||
|
Wire Wire Line
|
||||||
|
4450 6650 4450 5550
|
||||||
|
Connection ~ 4450 6350
|
||||||
|
Connection ~ 2900 5650
|
||||||
|
Wire Wire Line
|
||||||
|
2900 6450 2900 6150
|
||||||
|
Text Notes 1100 1600 0 300 ~ 60
|
||||||
|
SuperCIC other connections
|
||||||
|
Text Notes 5450 3850 0 60 ~ 0
|
||||||
|
GND
|
||||||
|
$Comp
|
||||||
|
L +5V #PWR?
|
||||||
|
U 1 1 4C0AF540
|
||||||
|
P 2900 5550
|
||||||
|
F 0 "#PWR?" H 2900 5640 20 0001 C CNN
|
||||||
|
F 1 "+5V" H 2900 5640 30 0000 C CNN
|
||||||
|
1 2900 5550
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
Text Notes 3350 5400 0 100 ~ 0
|
||||||
|
"RGB LED" (common anode)
|
||||||
|
Text Notes 3150 2300 0 100 ~ 0
|
||||||
|
"Duo-LED" (common cathode)
|
||||||
|
$Comp
|
||||||
|
L DIL14 ~
|
||||||
|
U 1 1 4C0AF4AF
|
||||||
|
P 4900 6350
|
||||||
|
F 0 "~" H 4900 6750 60 0000 C CNN
|
||||||
|
F 1 "PIC16F630" H 4900 5900 50 0000 C CNN
|
||||||
|
1 4900 6350
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L R ~
|
||||||
|
U 1 1 4C0AF4AE
|
||||||
|
P 3800 6550
|
||||||
|
F 0 "~" V 3850 6350 50 0000 C CNN
|
||||||
|
F 1 "180" V 3800 6550 50 0000 C CNN
|
||||||
|
1 3800 6550
|
||||||
|
0 1 1 0
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L R ~
|
||||||
|
U 1 1 4C0AF4AD
|
||||||
|
P 3800 6450
|
||||||
|
F 0 "~" V 3850 6250 50 0000 C CNN
|
||||||
|
F 1 "180" V 3800 6450 50 0000 C CNN
|
||||||
|
1 3800 6450
|
||||||
|
0 1 1 0
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L +5V #PWR?
|
||||||
|
U 1 1 4C0AF4AA
|
||||||
|
P 4450 5550
|
||||||
|
F 0 "#PWR?" H 4450 5640 20 0001 C CNN
|
||||||
|
F 1 "+5V" H 4450 5640 30 0000 C CNN
|
||||||
|
1 4450 5550
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
NoConn ~ 4350 6250
|
||||||
|
Text Notes 4100 6200 0 60 ~ 0
|
||||||
|
SNES
|
||||||
|
Text Notes 5450 7300 0 60 ~ 0
|
||||||
|
GND
|
||||||
|
$Comp
|
||||||
|
L GND #PWR?
|
||||||
|
U 1 1 4C0AF4A7
|
||||||
|
P 5350 7250
|
||||||
|
F 0 "#PWR?" H 5350 7250 30 0001 C CNN
|
||||||
|
F 1 "GND" H 5350 7180 30 0001 C CNN
|
||||||
|
1 5350 7250
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
Text Notes 5500 6200 0 60 ~ 0
|
||||||
|
SNES
|
||||||
|
Text Notes 5500 6300 0 60 ~ 0
|
||||||
|
SNES
|
||||||
|
Text Notes 5500 6400 0 60 ~ 0
|
||||||
|
SNES
|
||||||
|
Text Notes 5500 6500 0 60 ~ 0
|
||||||
|
SNES
|
||||||
|
Text Notes 5500 6600 0 60 ~ 0
|
||||||
|
SNES
|
||||||
|
Text Notes 5500 6700 0 60 ~ 0
|
||||||
|
SNES
|
||||||
|
Text Notes 5500 3250 0 60 ~ 0
|
||||||
|
SNES
|
||||||
|
Text Notes 5500 3150 0 60 ~ 0
|
||||||
|
SNES
|
||||||
|
Text Notes 5500 3050 0 60 ~ 0
|
||||||
|
SNES
|
||||||
|
Text Notes 5500 2950 0 60 ~ 0
|
||||||
|
SNES
|
||||||
|
Text Notes 5500 2850 0 60 ~ 0
|
||||||
|
SNES
|
||||||
|
Text Notes 5500 2750 0 60 ~ 0
|
||||||
|
SNES
|
||||||
|
$Comp
|
||||||
|
L GND #PWR?
|
||||||
|
U 1 1 4C0AF458
|
||||||
|
P 5350 3800
|
||||||
|
F 0 "#PWR?" H 5350 3800 30 0001 C CNN
|
||||||
|
F 1 "GND" H 5350 3730 30 0001 C CNN
|
||||||
|
1 5350 3800
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
Text Notes 3600 3850 0 60 ~ 0
|
||||||
|
GND
|
||||||
|
$Comp
|
||||||
|
L GND #PWR?
|
||||||
|
U 1 1 4C0AF41F
|
||||||
|
P 4450 3800
|
||||||
|
F 0 "#PWR?" H 4450 3800 30 0001 C CNN
|
||||||
|
F 1 "GND" H 4450 3730 30 0001 C CNN
|
||||||
|
1 4450 3800
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L GND #PWR?
|
||||||
|
U 1 1 4C0AF407
|
||||||
|
P 3050 3800
|
||||||
|
F 0 "#PWR?" H 3050 3800 30 0001 C CNN
|
||||||
|
F 1 "GND" H 3050 3730 30 0001 C CNN
|
||||||
|
1 3050 3800
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
Text Notes 4100 2750 0 60 ~ 0
|
||||||
|
SNES
|
||||||
|
NoConn ~ 4350 2800
|
||||||
|
$Comp
|
||||||
|
L +5V #PWR?
|
||||||
|
U 1 1 4C0AF329
|
||||||
|
P 4450 2450
|
||||||
|
F 0 "#PWR?" H 4450 2540 20 0001 C CNN
|
||||||
|
F 1 "+5V" H 4450 2540 30 0000 C CNN
|
||||||
|
1 4450 2450
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L LED ~
|
||||||
|
U 1 1 4C0AF2F1
|
||||||
|
P 3200 5950
|
||||||
|
F 0 "~" H 3200 6050 50 0000 C CNN
|
||||||
|
F 1 "LED red" H 3200 5850 50 0000 C CNN
|
||||||
|
1 3200 5950
|
||||||
|
0 1 1 0
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L LED ~
|
||||||
|
U 1 1 4C0AF2F0
|
||||||
|
P 2900 5950
|
||||||
|
F 0 "~" H 2900 6050 50 0000 C CNN
|
||||||
|
F 1 "LED grn" H 2900 5850 50 0000 C CNN
|
||||||
|
1 2900 5950
|
||||||
|
0 1 1 0
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L LED ~
|
||||||
|
U 1 1 4C0AF2EE
|
||||||
|
P 2600 5950
|
||||||
|
F 0 "~" H 2600 6050 50 0000 C CNN
|
||||||
|
F 1 "LED blu" H 2600 5850 50 0000 C CNN
|
||||||
|
1 2600 5950
|
||||||
|
0 1 1 0
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L LED ~
|
||||||
|
U 1 1 4C0AF2EC
|
||||||
|
P 3200 3400
|
||||||
|
F 0 "~" H 3200 3500 50 0000 C CNN
|
||||||
|
F 1 "LED red" H 3200 3300 50 0000 C CNN
|
||||||
|
1 3200 3400
|
||||||
|
0 1 1 0
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L LED ~
|
||||||
|
U 1 1 4C0AF2DF
|
||||||
|
P 2900 3400
|
||||||
|
F 0 "~" H 2900 3500 50 0000 C CNN
|
||||||
|
F 1 "LED grn" H 2900 3300 50 0000 C CNN
|
||||||
|
1 2900 3400
|
||||||
|
0 1 1 0
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L R ~
|
||||||
|
U 1 1 4C0AF2A2
|
||||||
|
P 3800 3000
|
||||||
|
F 0 "~" V 3850 2800 50 0000 C CNN
|
||||||
|
F 1 "180" V 3800 3000 50 0000 C CNN
|
||||||
|
1 3800 3000
|
||||||
|
0 1 1 0
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L R ~
|
||||||
|
U 1 1 4C0AF29F
|
||||||
|
P 3800 3100
|
||||||
|
F 0 "~" V 3850 2900 50 0000 C CNN
|
||||||
|
F 1 "180" V 3800 3100 50 0000 C CNN
|
||||||
|
1 3800 3100
|
||||||
|
0 1 1 0
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L DIL14 ~
|
||||||
|
U 1 1 4C0AF0D9
|
||||||
|
P 4900 2900
|
||||||
|
F 0 "~" H 4900 3300 60 0000 C CNN
|
||||||
|
F 1 "PIC16F630" H 4900 2450 50 0000 C CNN
|
||||||
|
1 4900 2900
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$EndSCHEMATC
|
||||||
BIN
gfx/logo.chi
Normal file
BIN
gfx/logo.chi
Normal file
Binary file not shown.
BIN
gfx/logo_v2.chi
Normal file
BIN
gfx/logo_v2.chi
Normal file
Binary file not shown.
BIN
gfx/logo_v2_sprites.chi
Normal file
BIN
gfx/logo_v2_sprites.chi
Normal file
Binary file not shown.
BIN
gfx/sd2snes.pal
Normal file
BIN
gfx/sd2snes.pal
Normal file
Binary file not shown.
BIN
gfx/sd2snes.psd
Normal file
BIN
gfx/sd2snes.psd
Normal file
Binary file not shown.
BIN
gfx/sd2snes_logo_remap.bin
Normal file
BIN
gfx/sd2snes_logo_remap.bin
Normal file
Binary file not shown.
BIN
gfx/sd2snes_v2-sprites-b15-15-gradient_orig.xcf
Normal file
BIN
gfx/sd2snes_v2-sprites-b15-15-gradient_orig.xcf
Normal file
Binary file not shown.
BIN
gfx/sd2snes_v2.psd
Normal file
BIN
gfx/sd2snes_v2.psd
Normal file
Binary file not shown.
BIN
lbr/atmega644.lbr
Normal file
BIN
lbr/atmega644.lbr
Normal file
Binary file not shown.
BIN
lbr/cy62167.lbr
Normal file
BIN
lbr/cy62167.lbr
Normal file
Binary file not shown.
BIN
lbr/lm1117.lbr
Normal file
BIN
lbr/lm1117.lbr
Normal file
Binary file not shown.
BIN
lbr/misc-74.lbr
Normal file
BIN
lbr/misc-74.lbr
Normal file
Binary file not shown.
BIN
lbr/sdcard.lbr
Normal file
BIN
lbr/sdcard.lbr
Normal file
Binary file not shown.
BIN
lbr/snescart.lbr
Normal file
BIN
lbr/snescart.lbr
Normal file
Binary file not shown.
339
misc/igr/COPYING
Normal file
339
misc/igr/COPYING
Normal file
@@ -0,0 +1,339 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Lesser General Public License instead.) You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
this service if you wish), that you receive source code or can get it
|
||||||
|
if you want it, that you can change the software or use pieces of it
|
||||||
|
in new free programs; and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if you
|
||||||
|
distribute copies of the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. You must make sure that they, too, receive or can get the
|
||||||
|
source code. And you must show them these terms so they know their
|
||||||
|
rights.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, so
|
||||||
|
that any problems introduced by others will not reflect on the original
|
||||||
|
authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Program's
|
||||||
|
source code as you receive it, in any medium, provided that you
|
||||||
|
conspicuously and appropriately publish on each copy an appropriate
|
||||||
|
copyright notice and disclaimer of warranty; keep intact all the
|
||||||
|
notices that refer to this License and to the absence of any warranty;
|
||||||
|
and give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy, and
|
||||||
|
you may at your option offer warranty protection in exchange for a fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Program, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) Accompany it with the complete corresponding machine-readable
|
||||||
|
source code, which must be distributed under the terms of Sections
|
||||||
|
1 and 2 above on a medium customarily used for software interchange; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, complete source
|
||||||
|
code means all the source code for all modules it contains, plus any
|
||||||
|
associated interface definition files, plus the scripts used to
|
||||||
|
control compilation and installation of the executable. However, as a
|
||||||
|
special exception, the source code distributed need not include
|
||||||
|
anything that is normally distributed (in either source or binary
|
||||||
|
form) with the major components (compiler, kernel, and so on) of the
|
||||||
|
operating system on which the executable runs, unless that component
|
||||||
|
itself accompanies the executable.
|
||||||
|
|
||||||
|
If distribution of executable or object code is made by offering
|
||||||
|
access to copy from a designated place, then offering equivalent
|
||||||
|
access to copy the source code from the same place counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
void, and will automatically terminate your rights under this License.
|
||||||
|
However, parties who have received copies, or rights, from you under
|
||||||
|
this License will not have their licenses terminated so long as such
|
||||||
|
parties remain in full compliance.
|
||||||
|
|
||||||
|
5. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program subject to
|
||||||
|
these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
7. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Program.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under
|
||||||
|
any particular circumstance, the balance of the section is intended to
|
||||||
|
apply and the section as a whole is intended to apply in other
|
||||||
|
circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system, which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program under this License
|
||||||
|
may add an explicit geographical distribution limitation excluding
|
||||||
|
those countries, so that distribution is permitted only in or among
|
||||||
|
countries not thus excluded. In such case, this License incorporates
|
||||||
|
the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Program
|
||||||
|
specifies a version number of this License which applies to it and "any
|
||||||
|
later version", you have the option of following the terms and conditions
|
||||||
|
either of that version or of any later version published by the Free
|
||||||
|
Software Foundation. If the Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, write to the author
|
||||||
|
to ask for permission. For software which is copyrighted by the Free
|
||||||
|
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||||
|
make exceptions for this. Our decision will be guided by the two goals
|
||||||
|
of preserving the free status of all derivatives of our free software and
|
||||||
|
of promoting the sharing and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||||
|
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||||
|
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||||
|
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||||
|
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||||
|
REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||||
|
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||||
|
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||||
|
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
|
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
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.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) year name of author
|
||||||
|
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This General Public License does not permit incorporating your program into
|
||||||
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License.
|
||||||
328
misc/igr/snes-igr.asm
Normal file
328
misc/igr/snes-igr.asm
Normal file
@@ -0,0 +1,328 @@
|
|||||||
|
#include <p16f630.inc>
|
||||||
|
|
||||||
|
; -----------------------------------------------------------------------
|
||||||
|
; SNES "In-game reset" (IGR) controller
|
||||||
|
;
|
||||||
|
; Copyright (C) 2010 by Maximilian Rehkopf <otakon@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; version 2 of the License only.
|
||||||
|
;
|
||||||
|
; 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
;
|
||||||
|
; -----------------------------------------------------------------------
|
||||||
|
;
|
||||||
|
; This program is designed to run on a PIC 16F630 microcontroller connected
|
||||||
|
; to the controller port and SNES main board. It allows an SNES to be reset
|
||||||
|
; and region switched via a standard controller.
|
||||||
|
;
|
||||||
|
; pin configuration: (controller port pin) [other connection]
|
||||||
|
; ,-----_-----.
|
||||||
|
; +5V (1) |1 14| GND (7)
|
||||||
|
; Reset out [to CIC pin 8 / SuperCIC pin 13] |2 A5 A0 13| serial data in(4)
|
||||||
|
; 50/60Hz out [to PPUs] |3 A4 A1 12| latch in(3)
|
||||||
|
; 50/60Hz in [from SuperCIC pin 12] |4 A3 A2 11| clk in(2)
|
||||||
|
; LED out - grn |5 C5 C0 10| LED in - grn [from SuperCIC pin 5]
|
||||||
|
; LED out - red |6 C4 C1 9| LED in - red [from SuperCIC pin 6]
|
||||||
|
; LED_TYPE in |7 C3 C2 8| SuperCIC present
|
||||||
|
; `-----------'
|
||||||
|
;
|
||||||
|
; Pin 4 should be connected to SuperCIC pin 12 if a SuperCIC is used.
|
||||||
|
;
|
||||||
|
; Pin 7 (LED_TYPE) sets the output mode for the LED pins
|
||||||
|
; (must be tied to either level):
|
||||||
|
; low = common cathode
|
||||||
|
; high = common anode (output inverted)
|
||||||
|
;
|
||||||
|
; Pin 8 should be connected as follows:
|
||||||
|
; low = no SuperCIC present
|
||||||
|
; high = SuperCIC present
|
||||||
|
;
|
||||||
|
; controller pin numbering
|
||||||
|
; ========================
|
||||||
|
; _______________________________
|
||||||
|
; | | \
|
||||||
|
; | (1) (2) (3) (4) | (5) (6) (7) )
|
||||||
|
; |_________________|_____________/
|
||||||
|
;
|
||||||
|
;
|
||||||
|
; key mapping: L + R + Select + (stream data)
|
||||||
|
; =============================
|
||||||
|
; Start Reset (normal) 0xcf 0xcf
|
||||||
|
; X Reset (6s) 0xdf 0x8f
|
||||||
|
;
|
||||||
|
; Y Region 50Hz/PAL 0x9f 0xcf
|
||||||
|
; A Region 60Hz/NTSC 0xdf 0x4f
|
||||||
|
; B Region from SuperCIC (SuperCIC only) 0x5f 0xcf
|
||||||
|
;
|
||||||
|
; functional description:
|
||||||
|
; =======================
|
||||||
|
; Reset (normal): simply resets the console.
|
||||||
|
; Reset (6s): resets the console for >5s to enter main menu on
|
||||||
|
; PowerPak and sd2snes.
|
||||||
|
; In SuperCIC mode this actually issues a reset
|
||||||
|
; "doubleclick" to trigger the SuperCIC's long reset
|
||||||
|
; function.
|
||||||
|
;
|
||||||
|
; Region 50Hz/PAL overrides the region to 50Hz/PAL.
|
||||||
|
; Region 60Hz/NTSC overrides the region to 60Hz/NTSC.
|
||||||
|
; Region from SuperCIC sets the region according to the input level of
|
||||||
|
; pin 4 (+5V = 50Hz, 0V = 60Hz). In this mode the
|
||||||
|
; region is updated constantly.
|
||||||
|
; This function is only available in SuperCIC mode
|
||||||
|
; (pin 8 = 5V).
|
||||||
|
;
|
||||||
|
; -----------------------------------------------------------------------
|
||||||
|
; Configuration bits: adapt to your setup and needs
|
||||||
|
__CONFIG _INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _BODEN & _CP_OFF & _CPD_OFF
|
||||||
|
|
||||||
|
; -----------------------------------------------------------------------
|
||||||
|
; relocatable code
|
||||||
|
PROG CODE
|
||||||
|
start
|
||||||
|
banksel PORTA
|
||||||
|
clrf PORTA
|
||||||
|
movlw 0x07 ; PORTA2..0 are digital I/O (not connected to comparator)
|
||||||
|
movwf CMCON
|
||||||
|
movlw 0x00 ; disable all interrupts
|
||||||
|
movwf INTCON
|
||||||
|
banksel TRISA
|
||||||
|
movlw 0x2f ; in out in in in in
|
||||||
|
movwf TRISA
|
||||||
|
movlw 0x0f ; out out in in in in
|
||||||
|
movwf TRISC
|
||||||
|
movlw 0x00 ; no pullups
|
||||||
|
movwf WPUA
|
||||||
|
movlw 0x80 ; global pullup disable
|
||||||
|
movwf OPTION_REG
|
||||||
|
banksel PORTA
|
||||||
|
bsf PORTA, 5
|
||||||
|
|
||||||
|
; tits GTFO
|
||||||
|
|
||||||
|
clrf 0x24
|
||||||
|
btfsc PORTC, 2
|
||||||
|
bsf 0x24, 1
|
||||||
|
|
||||||
|
clrf 0x23
|
||||||
|
btfss 0x24, 1 ; SuperCIC absent?
|
||||||
|
goto doregion_60 ; then set defaults
|
||||||
|
|
||||||
|
bsf 0x23, 1 ; else enable passthru
|
||||||
|
|
||||||
|
idle
|
||||||
|
; check region passthru
|
||||||
|
btfss 0x23, 1 ; passthru enabled?
|
||||||
|
goto waitforlatch_h ;
|
||||||
|
btfsc PORTA, 3
|
||||||
|
bsf PORTA, 4
|
||||||
|
btfss PORTA, 3
|
||||||
|
bcf PORTA, 4
|
||||||
|
call setleds_passthru
|
||||||
|
waitforlatch_h ; wait for "latch" to become high
|
||||||
|
btfss PORTA, 1
|
||||||
|
goto idle
|
||||||
|
|
||||||
|
|
||||||
|
waitforlatch_l ; wait for "latch" to become low
|
||||||
|
btfsc PORTA, 1
|
||||||
|
goto waitforlatch_l
|
||||||
|
|
||||||
|
|
||||||
|
clrf 0x20
|
||||||
|
clrf 0x21
|
||||||
|
clrf 0x22
|
||||||
|
bcf STATUS, C ; clear carry
|
||||||
|
dl1
|
||||||
|
movf PORTA, w ;read data bit
|
||||||
|
rlf 0x20, f ;shift
|
||||||
|
andlw 0x1
|
||||||
|
iorwf 0x20, f ;put in data reg
|
||||||
|
incf 0x22, f ;inc bit count
|
||||||
|
dl1_wait
|
||||||
|
btfss PORTA, 2 ;wait for clk=h
|
||||||
|
goto dl1_wait
|
||||||
|
btfss 0x22, 3 ;first byte done?
|
||||||
|
goto dl1
|
||||||
|
clrf 0x22
|
||||||
|
dl2
|
||||||
|
movf PORTA, w ;read data bit
|
||||||
|
rlf 0x21, f ;shift
|
||||||
|
andlw 0x1
|
||||||
|
iorwf 0x21, f ;put in data reg
|
||||||
|
incf 0x22, f ;inc bit count
|
||||||
|
dl2_wait
|
||||||
|
btfss PORTA, 2 ;wait for clk=h
|
||||||
|
goto dl2_wait
|
||||||
|
btfss 0x22, 2 ; read only 4 bits
|
||||||
|
goto dl2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
checkkeys
|
||||||
|
; we now have the first 8 bits in 0x20 and the second 4 bits in 0x21
|
||||||
|
; 00011111 00011111 = ABXY, Select, L
|
||||||
|
movlw 0x04
|
||||||
|
xorwf 0x21, w
|
||||||
|
btfsc STATUS, Z
|
||||||
|
goto group04
|
||||||
|
movlw 0x08
|
||||||
|
xorwf 0x21, w
|
||||||
|
btfsc STATUS, Z
|
||||||
|
goto group08
|
||||||
|
movlw 0x0c
|
||||||
|
xorwf 0x21, w
|
||||||
|
btfsc STATUS, Z
|
||||||
|
goto group0c
|
||||||
|
goto idle
|
||||||
|
|
||||||
|
group04
|
||||||
|
movlw 0xdf
|
||||||
|
xorwf 0x20, w
|
||||||
|
btfss STATUS, Z
|
||||||
|
goto idle
|
||||||
|
goto doregion_60
|
||||||
|
|
||||||
|
group08
|
||||||
|
movlw 0xdf
|
||||||
|
xorwf 0x20, w
|
||||||
|
btfss STATUS, Z
|
||||||
|
goto idle
|
||||||
|
btfss 0x24, 1 ; SuperCIC absent?
|
||||||
|
goto doreset_long ; then do long reset
|
||||||
|
goto doreset_dbl ; else do dbl reset
|
||||||
|
|
||||||
|
group0c
|
||||||
|
movlw 0x5f
|
||||||
|
xorwf 0x20, w
|
||||||
|
btfsc STATUS, Z
|
||||||
|
goto doregion_passthru
|
||||||
|
movlw 0x9f
|
||||||
|
xorwf 0x20, w
|
||||||
|
btfsc STATUS, Z
|
||||||
|
goto doregion_50
|
||||||
|
movlw 0xcf
|
||||||
|
xorwf 0x20, w
|
||||||
|
btfsc STATUS, Z
|
||||||
|
goto doreset_normal
|
||||||
|
goto idle
|
||||||
|
|
||||||
|
doreset_normal
|
||||||
|
banksel TRISA
|
||||||
|
bcf TRISA, 5
|
||||||
|
banksel PORTA
|
||||||
|
bsf PORTA, 5
|
||||||
|
movlw 0x15
|
||||||
|
call longwait
|
||||||
|
banksel TRISA
|
||||||
|
bsf TRISA, 5
|
||||||
|
banksel PORTA
|
||||||
|
goto idle
|
||||||
|
|
||||||
|
doreset_dbl
|
||||||
|
banksel TRISA
|
||||||
|
bcf TRISA, 5
|
||||||
|
banksel PORTA
|
||||||
|
bsf PORTA, 5
|
||||||
|
movlw 0x15
|
||||||
|
call longwait
|
||||||
|
banksel TRISA
|
||||||
|
bsf TRISA, 5
|
||||||
|
clrw
|
||||||
|
call longwait
|
||||||
|
bcf TRISA, 5
|
||||||
|
movlw 0x15
|
||||||
|
call longwait
|
||||||
|
banksel TRISA
|
||||||
|
bsf TRISA, 5
|
||||||
|
banksel PORTA
|
||||||
|
goto idle
|
||||||
|
|
||||||
|
doreset_long
|
||||||
|
banksel TRISA
|
||||||
|
bcf TRISA, 5
|
||||||
|
banksel PORTA
|
||||||
|
bsf PORTA, 5
|
||||||
|
movlw 0x1e
|
||||||
|
call superlongwait
|
||||||
|
banksel TRISA
|
||||||
|
bsf TRISA, 5
|
||||||
|
banksel PORTA
|
||||||
|
goto idle
|
||||||
|
|
||||||
|
doregion_50
|
||||||
|
bsf PORTA, 4
|
||||||
|
clrf 0x23
|
||||||
|
call setleds_own
|
||||||
|
goto idle
|
||||||
|
|
||||||
|
doregion_60
|
||||||
|
bcf PORTA, 4
|
||||||
|
clrf 0x23
|
||||||
|
call setleds_own
|
||||||
|
goto idle
|
||||||
|
|
||||||
|
doregion_passthru
|
||||||
|
clrf 0x23
|
||||||
|
btfsc 0x24, 1 ; SuperCIC present?
|
||||||
|
bsf 0x23, 1 ; then enable passthru
|
||||||
|
goto idle
|
||||||
|
|
||||||
|
; --------wait: 3*(W-1)+7 cycles (including call+return). W=0 -> 256!--------
|
||||||
|
wait
|
||||||
|
movwf 0x2f
|
||||||
|
wait0 decfsz 0x2f, f
|
||||||
|
goto wait0
|
||||||
|
goto longwait1
|
||||||
|
|
||||||
|
; --------wait long: 8+(3*(w-1))+(772*w). W=0 -> 256!--------
|
||||||
|
longwait
|
||||||
|
movwf 0x2e
|
||||||
|
clrw
|
||||||
|
longwait0
|
||||||
|
goto wait
|
||||||
|
longwait1
|
||||||
|
decfsz 0x2e, f
|
||||||
|
goto longwait0
|
||||||
|
return
|
||||||
|
|
||||||
|
; --------wait extra long: 8+(3*(w-1))+(198405*w).
|
||||||
|
superlongwait
|
||||||
|
movwf 0x2d
|
||||||
|
clrw
|
||||||
|
superlongwait0
|
||||||
|
call longwait
|
||||||
|
decfsz 0x2d, f
|
||||||
|
goto superlongwait0
|
||||||
|
return
|
||||||
|
|
||||||
|
setleds
|
||||||
|
btfss 0x24, 1
|
||||||
|
goto setleds_own
|
||||||
|
setleds_passthru
|
||||||
|
clrw
|
||||||
|
btfsc PORTC, 0 ; green LED
|
||||||
|
iorlw 0x20
|
||||||
|
btfsc PORTC, 1 ; red LED
|
||||||
|
iorlw 0x10
|
||||||
|
movwf PORTC
|
||||||
|
return
|
||||||
|
|
||||||
|
setleds_own
|
||||||
|
movlw 0x20 ; assume green LED
|
||||||
|
btfss PORTA, 4
|
||||||
|
movlw 0x10 ; if PORTA.4 is low -> red LED
|
||||||
|
btfsc PORTC, 3 ; if common anode:
|
||||||
|
xorlw 0x30 ; invert output
|
||||||
|
movwf PORTC
|
||||||
|
return
|
||||||
|
END
|
||||||
28
misc/igr/snes-igr.hex
Normal file
28
misc/igr/snes-igr.hex
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
:020000040000FA
|
||||||
|
:100000008312031385010730990000308B0083169B
|
||||||
|
:1000100003132F3085000F308700003095008030AB
|
||||||
|
:100020008100831203138516A4010719A414A301E8
|
||||||
|
:10003000A41C9928A314A31C222885190516851D24
|
||||||
|
:100040000512B320851C1B2885182428A001A101B6
|
||||||
|
:10005000A20103100508A00D0139A004A20A051D84
|
||||||
|
:100060002F28A21D2A28A2010508A10D0139A104EB
|
||||||
|
:10007000A20A051D3928221D34280430210603193F
|
||||||
|
:100080004A280830210603194F280C30210603198D
|
||||||
|
:1000900056281B28DF302006031D1B289928DF3037
|
||||||
|
:1000A0002006031D1B28A41C872871285F3020060A
|
||||||
|
:1000B00003199D289F30200603199528CF3020066C
|
||||||
|
:1000C000031963281B288316031385128312031355
|
||||||
|
:1000D00085161530A5208316031385168312031386
|
||||||
|
:1000E0001B288316031385128312031385161530FC
|
||||||
|
:1000F000A5208316031385160301A520851215304C
|
||||||
|
:10010000A520831603138516831203131B28831659
|
||||||
|
:10011000031385128312031385161E30AB2083163A
|
||||||
|
:1001200003138516831203131B280516A301BA2097
|
||||||
|
:100130001B280512A301BA201B28A301A418A3148D
|
||||||
|
:100140001B28AF00AF0BA228A828AE000301A128EE
|
||||||
|
:10015000AE0BA7280800AD000301A520AD0BAD280C
|
||||||
|
:100160000800A41CBA280301071820388718103883
|
||||||
|
:10017000870008002030051E10308719303A8700AC
|
||||||
|
:02018000080075
|
||||||
|
:02400E00D43F9D
|
||||||
|
:00000001FF
|
||||||
619
mk1-src/Makefile
Normal file
619
mk1-src/Makefile
Normal file
@@ -0,0 +1,619 @@
|
|||||||
|
# Hey Emacs, this is a -*- makefile -*-
|
||||||
|
|
||||||
|
# Define version number
|
||||||
|
MAJOR = 0
|
||||||
|
MINOR = 0
|
||||||
|
PATCHLEVEL = 1
|
||||||
|
FIX =
|
||||||
|
|
||||||
|
# Forces bootloader version to 0, comment out for release
|
||||||
|
#PRERELEASE =
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------------
|
||||||
|
# WinAVR Makefile Template written by Eric B. Weddington, Joerg Wunsch, et al.
|
||||||
|
#
|
||||||
|
# Released to the Public Domain
|
||||||
|
#
|
||||||
|
# Additional material for this makefile was written by:
|
||||||
|
# Peter Fleury
|
||||||
|
# Tim Henigan
|
||||||
|
# Colin O'Flynn
|
||||||
|
# Reiner Patommel
|
||||||
|
# Markus Pfaff
|
||||||
|
# Sander Pool
|
||||||
|
# Frederik Rouleau
|
||||||
|
# Carlos Lamas
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Extensively modified for sd2iec by Ingo Korb
|
||||||
|
#
|
||||||
|
# To rebuild project do "make clean" then "make all".
|
||||||
|
#----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Read configuration file
|
||||||
|
ifdef CONFIG
|
||||||
|
CONFIGSUFFIX = $(CONFIG:config%=%)
|
||||||
|
else
|
||||||
|
CONFIG = config
|
||||||
|
CONFIGSUFFIX =
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Enable verbose compilation with "make V=1"
|
||||||
|
ifdef V
|
||||||
|
Q :=
|
||||||
|
E := @:
|
||||||
|
else
|
||||||
|
Q := @
|
||||||
|
E := @echo
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Include the configuration file
|
||||||
|
include $(CONFIG)
|
||||||
|
|
||||||
|
# Set MCU name and length of binary for bootloader
|
||||||
|
# WARNING: Fuse settings not tested!
|
||||||
|
MCU := $(CONFIG_MCU)
|
||||||
|
ifeq ($(MCU),atmega128)
|
||||||
|
BINARY_LENGTH = 0x1f000
|
||||||
|
# EFUSE = 0xff
|
||||||
|
# HFUSE = 0x91
|
||||||
|
# LFUSE = 0xaf
|
||||||
|
else ifeq ($(MCU),atmega1281)
|
||||||
|
BINARY_LENGTH = 0x1f000
|
||||||
|
BOOTLDRSIZE = 0x0800
|
||||||
|
EFUSE = 0xff
|
||||||
|
HFUSE = 0xd2
|
||||||
|
LFUSE = 0xfc
|
||||||
|
else ifeq ($(MCU),atmega2561)
|
||||||
|
BINARY_LENGTH = 0x3f000
|
||||||
|
EFUSE = 0xfd
|
||||||
|
HFUSE = 0x93
|
||||||
|
LFUSE = 0xef
|
||||||
|
else ifeq ($(MCU),atmega644)
|
||||||
|
BINARY_LENGTH = 0xf000
|
||||||
|
EFUSE = 0xfd
|
||||||
|
HFUSE = 0x91
|
||||||
|
# LFUSE = 0xef
|
||||||
|
LFUSE = 0xaf
|
||||||
|
else ifeq ($(MCU),atmega644p)
|
||||||
|
BINARY_LENGTH = 0xf000
|
||||||
|
EFUSE = 0xfd
|
||||||
|
HFUSE = 0x91
|
||||||
|
LFUSE = 0xef
|
||||||
|
else
|
||||||
|
.PHONY: nochip
|
||||||
|
nochip:
|
||||||
|
@echo '=============================================================='
|
||||||
|
@echo 'No known target chip specified.'
|
||||||
|
@echo
|
||||||
|
@echo 'Please edit the Makefile.'
|
||||||
|
@exit 1
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Directory for all generated files
|
||||||
|
OBJDIR := obj-$(CONFIG_MCU:atmega%=m%)$(CONFIGSUFFIX)
|
||||||
|
|
||||||
|
# Output format. (can be srec, ihex, binary)
|
||||||
|
FORMAT = ihex
|
||||||
|
|
||||||
|
|
||||||
|
# Target file name (without extension).
|
||||||
|
TARGET = $(OBJDIR)/sd2snes
|
||||||
|
|
||||||
|
# List C source files here. (C dependencies are automatically generated.)
|
||||||
|
SRC = main.c ff.c utils.c led.c diskio.c sdcard.c spi.c crc7.c snes.c fpga.c memory.c crc16.c fileops.c fpga_spi.c smc.c filetypes.c
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_UART_DEBUG),y)
|
||||||
|
SRC += uart.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
# 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.)
|
||||||
|
# Use s -mcall-prologues when you really need size...
|
||||||
|
OPT = s
|
||||||
|
#OPT = 3 -finline-functions
|
||||||
|
|
||||||
|
# Debugging format.
|
||||||
|
# Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs.
|
||||||
|
# AVR Studio 4.10 requires dwarf-2.
|
||||||
|
# AVR [Extended] COFF format requires stabs, plus an avr-objcopy run.
|
||||||
|
DEBUG = dwarf-2
|
||||||
|
|
||||||
|
|
||||||
|
# List any extra directories to look for include files here.
|
||||||
|
# Each directory must be seperated by a space.
|
||||||
|
# Use forward slashes for directory separators.
|
||||||
|
# For a directory that has spaces, enclose it in quotes.
|
||||||
|
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=gnu99
|
||||||
|
|
||||||
|
|
||||||
|
# Place -D or -U options here
|
||||||
|
CDEFS = -DF_CPU=$(CONFIG_MCU_FREQ)UL
|
||||||
|
|
||||||
|
# Calculate bootloader version
|
||||||
|
ifdef PRERELEASE
|
||||||
|
BOOT_VERSION := 0
|
||||||
|
else
|
||||||
|
BOOT_VERSION := 0x$(MAJOR)$(MINOR)$(PATCHLEVEL)$(FIX)
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Create a version number define
|
||||||
|
ifdef PATCHLEVEL
|
||||||
|
ifdef FIX
|
||||||
|
PROGRAMVERSION := $(MAJOR).$(MINOR).$(PATCHLEVEL).$(FIX)
|
||||||
|
else
|
||||||
|
PROGRAMVERSION := $(MAJOR).$(MINOR).$(PATCHLEVEL)
|
||||||
|
BOOT_VERSION := $(BOOT_VERSION)0
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
PROGRAMVERSION := $(MAJOR).$(MINOR)
|
||||||
|
BOOT_VERSION := $(BOOT_VERSION)00
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifdef PRERELEASE
|
||||||
|
PROGRAMVERSION := $(PROGRAMVERSION)$(PRERELEASE)
|
||||||
|
endif
|
||||||
|
|
||||||
|
LONGVERSION := -$(CONFIG_MCU:atmega%=m%)$(CONFIGSUFFIX)
|
||||||
|
|
||||||
|
CDEFS += -DVERSION=\"$(PROGRAMVERSION)\" -DLONGVERSION=\"$(LONGVERSION)\"
|
||||||
|
|
||||||
|
# Place -I options here
|
||||||
|
CINCS =
|
||||||
|
|
||||||
|
|
||||||
|
# Define programs and commands.
|
||||||
|
# CC must be defined here to generate the correct CFLAGS
|
||||||
|
SHELL = sh
|
||||||
|
CC = avr-gcc
|
||||||
|
OBJCOPY = avr-objcopy
|
||||||
|
OBJDUMP = avr-objdump
|
||||||
|
SIZE = avr-size
|
||||||
|
NM = avr-nm
|
||||||
|
AVRDUDE = avrdude
|
||||||
|
REMOVE = rm -f
|
||||||
|
COPY = cp
|
||||||
|
WINSHELL = cmd
|
||||||
|
|
||||||
|
|
||||||
|
#---------------- Compiler Options ----------------
|
||||||
|
# -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)
|
||||||
|
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
|
||||||
|
CFLAGS += -Wall -Wstrict-prototypes -Werror
|
||||||
|
CFLAGS += -Wa,-adhlns=$(OBJDIR)/$(<:.c=.lst)
|
||||||
|
CFLAGS += -I$(OBJDIR)
|
||||||
|
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
|
||||||
|
CFLAGS += $(CSTANDARD)
|
||||||
|
CFLAGS += -ffunction-sections -fdata-sections
|
||||||
|
#CFLAGS += -mcall-prologues
|
||||||
|
|
||||||
|
# these are needed for GCC 4.3.2, which is more aggressive at inlining
|
||||||
|
# gcc-4.2 knows one of those, but it tends to increase code size
|
||||||
|
ifeq ($(shell $(CC) --version|gawk -f gcctest.awk),YES)
|
||||||
|
CFLAGS += --param inline-call-cost=3
|
||||||
|
CFLAGS += -fno-inline-small-functions
|
||||||
|
CFLAGS += -fno-move-loop-invariants
|
||||||
|
CFLAGS += -fno-split-wide-types
|
||||||
|
|
||||||
|
# turn these on to keep the functions in the same order as in the source
|
||||||
|
# this is only useful if you're looking at disassembly
|
||||||
|
#CFLAGS += -fno-reorder-blocks
|
||||||
|
#CFLAGS += -fno-reorder-blocks-and-partition
|
||||||
|
#CFLAGS += -fno-reorder-functions
|
||||||
|
#CFLAGS += -fno-toplevel-reorder
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_STACK_TRACKING),y)
|
||||||
|
CFLAGS += -finstrument-functions
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
#---------------- Assembler Options ----------------
|
||||||
|
# -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=$(OBJDIR)/$(<:.S=.lst),-gstabs -I$(OBJDIR)
|
||||||
|
|
||||||
|
|
||||||
|
#---------------- Library Options ----------------
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# If this is left blank, then it will use the Standard printf version.
|
||||||
|
PRINTF_LIB =
|
||||||
|
#PRINTF_LIB = $(PRINTF_LIB_MIN)
|
||||||
|
#PRINTF_LIB = $(PRINTF_LIB_FLOAT)
|
||||||
|
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# If this is left blank, then it will use the Standard scanf version.
|
||||||
|
SCANF_LIB =
|
||||||
|
#SCANF_LIB = $(SCANF_LIB_MIN)
|
||||||
|
#SCANF_LIB = $(SCANF_LIB_FLOAT)
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
EXTMEMOPTS =
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#---------------- Linker Options ----------------
|
||||||
|
# -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
|
||||||
|
LDFLAGS += $(EXTMEMOPTS)
|
||||||
|
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
|
||||||
|
LDFLAGS += -Wl,--gc-sections
|
||||||
|
ifeq ($(CONFIG_LINKER_RELAX),y)
|
||||||
|
LDFLAGS += -Wl,-O9,--relax
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#---------------- Programming Options (avrdude) ----------------
|
||||||
|
|
||||||
|
# Programming hardware: alf avr910 avrisp bascom bsd
|
||||||
|
# dt006 pavr picoweb pony-stk200 sp12 stk200 stk500 stk500v2
|
||||||
|
#
|
||||||
|
# Type: avrdude -c ?
|
||||||
|
# to get a full listing.
|
||||||
|
#
|
||||||
|
AVRDUDE_PROGRAMMER = dragon_isp
|
||||||
|
|
||||||
|
# com1 = serial port. Use lpt1 to connect to parallel port.
|
||||||
|
AVRDUDE_PORT = usb # programmer connected to serial device
|
||||||
|
|
||||||
|
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
|
||||||
|
# AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
|
||||||
|
|
||||||
|
# Allow fuse overrides from the config file
|
||||||
|
ifdef CONFIG_EFUSE
|
||||||
|
EFUSE := CONFIG_EFUSE
|
||||||
|
endif
|
||||||
|
ifdef CONFIG_HFUSE
|
||||||
|
HFUSE := CONFIG_HFUSE
|
||||||
|
endif
|
||||||
|
ifdef CONFIG_LFUSE
|
||||||
|
LFUSE := CONFIG_LFUSE
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Calculate command line arguments for fuses
|
||||||
|
AVRDUDE_WRITE_FUSES :=
|
||||||
|
ifdef EFUSE
|
||||||
|
AVRDUDE_WRITE_FUSES += -U efuse:w:$(EFUSE):m
|
||||||
|
endif
|
||||||
|
ifdef HFUSE
|
||||||
|
AVRDUDE_WRITE_FUSES += -U hfuse:w:$(HFUSE):m
|
||||||
|
endif
|
||||||
|
ifdef LFUSE
|
||||||
|
AVRDUDE_WRITE_FUSES += -U lfuse:w:$(LFUSE):m
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
# 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_COUNTER = -y
|
||||||
|
|
||||||
|
# Uncomment the following if you do /not/ wish a verification to be
|
||||||
|
# performed after programming the device.
|
||||||
|
#AVRDUDE_NO_VERIFY = -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_VERBOSE = -v -v
|
||||||
|
|
||||||
|
AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
|
||||||
|
AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
|
||||||
|
AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
|
||||||
|
AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#---------------- Debugging Options ----------------
|
||||||
|
|
||||||
|
# For simulavr only - target MCU frequency.
|
||||||
|
DEBUG_MFREQ = $(CONFIG_MCU_FREQ)
|
||||||
|
|
||||||
|
# Set the DEBUG_UI to either gdb or insight.
|
||||||
|
# DEBUG_UI = gdb
|
||||||
|
DEBUG_UI = insight
|
||||||
|
|
||||||
|
# Set the debugging back-end to either avarice, simulavr.
|
||||||
|
DEBUG_BACKEND = avarice
|
||||||
|
#DEBUG_BACKEND = simulavr
|
||||||
|
|
||||||
|
# GDB Init Filename.
|
||||||
|
GDBINIT_FILE = __avr_gdbinit
|
||||||
|
|
||||||
|
# When using avarice settings for the JTAG
|
||||||
|
JTAG_DEV = /dev/com1
|
||||||
|
|
||||||
|
# Debugging port used to communicate between GDB / avarice / simulavr.
|
||||||
|
DEBUG_PORT = 4242
|
||||||
|
|
||||||
|
# Debugging host used to communicate between GDB / avarice / simulavr, normally
|
||||||
|
# just set to localhost unless doing some sort of crazy debugging when
|
||||||
|
# avarice is running on a different computer.
|
||||||
|
DEBUG_HOST = localhost
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#============================================================================
|
||||||
|
|
||||||
|
|
||||||
|
# De-dupe the list of C source files
|
||||||
|
CSRC := $(sort $(SRC))
|
||||||
|
|
||||||
|
# Define all object files.
|
||||||
|
OBJ := $(patsubst %,$(OBJDIR)/%,$(CSRC:.c=.o) $(ASRC:.S=.o))
|
||||||
|
|
||||||
|
# Define all listing files.
|
||||||
|
LST := $(patsubst %,$(OBJDIR)/%,$(CSRC:.c=.lst) $(ASRC:.S=.lst))
|
||||||
|
|
||||||
|
|
||||||
|
# Compiler flags to generate dependency files.
|
||||||
|
GENDEPFLAGS = -MMD -MP -MF .dep/$(@F).d
|
||||||
|
|
||||||
|
|
||||||
|
# Combine all necessary flags and optional flags.
|
||||||
|
# Add target processor to flags.
|
||||||
|
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
|
||||||
|
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS) $(CDEFS)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Default target.
|
||||||
|
all: build
|
||||||
|
|
||||||
|
build: elf bin hex
|
||||||
|
$(E) " SIZE $(TARGET).elf"
|
||||||
|
$(Q)$(ELFSIZE)|grep -v debug
|
||||||
|
|
||||||
|
elf: $(TARGET).elf
|
||||||
|
bin: $(TARGET).bin
|
||||||
|
hex: $(TARGET).hex
|
||||||
|
eep: $(TARGET).eep
|
||||||
|
lss: $(TARGET).lss
|
||||||
|
sym: $(TARGET).sym
|
||||||
|
|
||||||
|
# A little helper target for the maintainer =)
|
||||||
|
copy2card:
|
||||||
|
mount /mnt
|
||||||
|
cp $(TARGET).bin /mnt
|
||||||
|
umount /mnt
|
||||||
|
sync
|
||||||
|
|
||||||
|
|
||||||
|
# Doxygen output:
|
||||||
|
doxygen:
|
||||||
|
-rm -rf doxyinput
|
||||||
|
mkdir doxyinput
|
||||||
|
cp *.h *.c doxyinput
|
||||||
|
src2doxy.pl doxyinput/*.h doxyinput/*.c
|
||||||
|
doxygen doxygen.conf
|
||||||
|
|
||||||
|
# Display size of file.
|
||||||
|
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
|
||||||
|
ELFSIZE = $(SIZE) -A $(TARGET).elf
|
||||||
|
AVRMEM = avr-mem.sh $(TARGET).elf $(MCU)
|
||||||
|
|
||||||
|
# Program the device.
|
||||||
|
program: bin hex eep
|
||||||
|
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
|
||||||
|
|
||||||
|
# Set fuses of the device
|
||||||
|
fuses: $(CONFIG)
|
||||||
|
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FUSES)
|
||||||
|
|
||||||
|
# Generate avr-gdb config/init file which does the following:
|
||||||
|
# define the reset signal, load the target file, connect to target, and set
|
||||||
|
# a breakpoint at main().
|
||||||
|
gdb-config:
|
||||||
|
@$(REMOVE) $(GDBINIT_FILE)
|
||||||
|
@echo define reset >> $(GDBINIT_FILE)
|
||||||
|
@echo SIGNAL SIGHUP >> $(GDBINIT_FILE)
|
||||||
|
@echo end >> $(GDBINIT_FILE)
|
||||||
|
@echo file $(TARGET).elf >> $(GDBINIT_FILE)
|
||||||
|
@echo target remote $(DEBUG_HOST):$(DEBUG_PORT) >> $(GDBINIT_FILE)
|
||||||
|
ifeq ($(DEBUG_BACKEND),simulavr)
|
||||||
|
@echo load >> $(GDBINIT_FILE)
|
||||||
|
endif
|
||||||
|
@echo break main >> $(GDBINIT_FILE)
|
||||||
|
|
||||||
|
debug: gdb-config $(TARGET).elf
|
||||||
|
ifeq ($(DEBUG_BACKEND), avarice)
|
||||||
|
@echo Starting AVaRICE - Press enter when "waiting to connect" message displays.
|
||||||
|
@$(WINSHELL) /c start avarice --jtag $(JTAG_DEV) --erase --program --file \
|
||||||
|
$(TARGET).elf $(DEBUG_HOST):$(DEBUG_PORT)
|
||||||
|
@$(WINSHELL) /c pause
|
||||||
|
|
||||||
|
else
|
||||||
|
@$(WINSHELL) /c start simulavr --gdbserver --device $(MCU) --clock-freq \
|
||||||
|
$(DEBUG_MFREQ) --port $(DEBUG_PORT)
|
||||||
|
endif
|
||||||
|
@$(WINSHELL) /c start avr-$(DEBUG_UI) --command=$(GDBINIT_FILE)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# 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
|
||||||
|
$(COFFCONVERT) -O coff-avr $< $(TARGET).cof
|
||||||
|
|
||||||
|
|
||||||
|
extcoff: $(TARGET).elf
|
||||||
|
$(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof
|
||||||
|
|
||||||
|
|
||||||
|
# Generate autoconf.h from config
|
||||||
|
.PRECIOUS : $(OBJDIR)/autoconf.h
|
||||||
|
$(OBJDIR)/autoconf.h: $(CONFIG) | $(OBJDIR)
|
||||||
|
$(E) " CONF2H $(CONFIG)"
|
||||||
|
$(Q)gawk -f conf2h.awk $(CONFIG) > $(OBJDIR)/autoconf.h
|
||||||
|
|
||||||
|
# Create final output files (.hex, .eep) from ELF output file.
|
||||||
|
ifeq ($(CONFIG_BOOTLOADER),y)
|
||||||
|
$(OBJDIR)/%.bin: $(OBJDIR)/%.elf
|
||||||
|
$(E) " BIN $@"
|
||||||
|
$(Q)$(OBJCOPY) -O binary -R .eeprom $< $@
|
||||||
|
$(E) " CRCGEN $@"
|
||||||
|
-$(Q)crcgen-new $@ $(BINARY_LENGTH) $(CONFIG_BOOT_DEVID) $(BOOT_VERSION)
|
||||||
|
$(E) " COPY $(CONFIG_HARDWARE_NAME)-firmware-$(PROGRAMVERSION).bin"
|
||||||
|
$(Q)$(COPY) $@ $(OBJDIR)/$(CONFIG_HARDWARE_NAME)-firmware-$(PROGRAMVERSION).bin
|
||||||
|
else
|
||||||
|
$(OBJDIR)/%.bin: $(OBJDIR)/%.elf
|
||||||
|
$(E) " BIN $@"
|
||||||
|
$(Q)$(OBJCOPY) -O binary -R .eeprom $< $@
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
$(OBJDIR)/%.hex: $(OBJDIR)/%.elf
|
||||||
|
$(E) " HEX $@"
|
||||||
|
$(Q)$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
|
||||||
|
|
||||||
|
$(OBJDIR)/%.eep: $(OBJDIR)/%.elf
|
||||||
|
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
|
||||||
|
--change-section-lma .eeprom=0 -O $(FORMAT) $< $@
|
||||||
|
|
||||||
|
# Create extended listing file from ELF output file.
|
||||||
|
$(OBJDIR)/%.lss: $(OBJDIR)/%.elf
|
||||||
|
$(E) " LSS $<"
|
||||||
|
$(Q)$(OBJDUMP) -h -S $< > $@
|
||||||
|
|
||||||
|
# Create a symbol table from ELF output file.
|
||||||
|
$(OBJDIR)/%.sym: $(OBJDIR)/%.elf
|
||||||
|
$(E) " SYM $<"
|
||||||
|
$(E)$(NM) -n $< > $@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Link: create ELF output file from object files.
|
||||||
|
.SECONDARY : $(TARGET).elf
|
||||||
|
.PRECIOUS : $(OBJ)
|
||||||
|
$(OBJDIR)/%.elf: $(OBJ)
|
||||||
|
$(E) " LINK $@"
|
||||||
|
$(Q)$(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS)
|
||||||
|
|
||||||
|
|
||||||
|
# Compile: create object files from C source files.
|
||||||
|
$(OBJDIR)/%.o : %.c | $(OBJDIR) $(OBJDIR)/autoconf.h
|
||||||
|
$(E) " CC $<"
|
||||||
|
$(Q)$(CC) -c $(ALL_CFLAGS) $< -o $@
|
||||||
|
|
||||||
|
|
||||||
|
# Compile: create assembler files from C source files.
|
||||||
|
$(OBJDIR)/%.s : %.c | $(OBJDIR) $(OBJDIR)/autoconf.h
|
||||||
|
$(CC) -S $(ALL_CFLAGS) $< -o $@
|
||||||
|
|
||||||
|
|
||||||
|
# Assemble: create object files from assembler source files.
|
||||||
|
$(OBJDIR)/%.o : %.S | $(OBJDIR) $(OBJDIR)/autoconf.h
|
||||||
|
$(E) " AS $<"
|
||||||
|
$(Q)$(CC) -c $(ALL_ASFLAGS) $< -o $@
|
||||||
|
|
||||||
|
# Create preprocessed source for use in sending a bug report.
|
||||||
|
$(OBJDIR)/%.i : %.c | $(OBJDIR) $(OBJDIR)/autoconf.h
|
||||||
|
$(CC) -E -mmcu=$(MCU) -I. $(CFLAGS) $< -o $@
|
||||||
|
|
||||||
|
# Create the output directory
|
||||||
|
$(OBJDIR):
|
||||||
|
$(E) " MKDIR $(OBJDIR)"
|
||||||
|
$(Q)mkdir $(OBJDIR)
|
||||||
|
|
||||||
|
# Target: clean project.
|
||||||
|
clean: begin clean_list end
|
||||||
|
|
||||||
|
clean_list :
|
||||||
|
$(E) " CLEAN"
|
||||||
|
$(Q)$(REMOVE) $(TARGET).hex
|
||||||
|
$(Q)$(REMOVE) $(TARGET).bin
|
||||||
|
$(Q)$(REMOVE) $(TARGET).eep
|
||||||
|
$(Q)$(REMOVE) $(TARGET).cof
|
||||||
|
$(Q)$(REMOVE) $(TARGET).elf
|
||||||
|
$(Q)$(REMOVE) $(TARGET).map
|
||||||
|
$(Q)$(REMOVE) $(TARGET).sym
|
||||||
|
$(Q)$(REMOVE) $(TARGET).lss
|
||||||
|
$(Q)$(REMOVE) $(OBJ)
|
||||||
|
$(Q)$(REMOVE) $(OBJDIR)/autoconf.h
|
||||||
|
$(Q)$(REMOVE) $(OBJDIR)/*.bin
|
||||||
|
$(Q)$(REMOVE) $(LST)
|
||||||
|
$(Q)$(REMOVE) $(CSRC:.c=.s)
|
||||||
|
$(Q)$(REMOVE) $(CSRC:.c=.d)
|
||||||
|
$(Q)$(REMOVE) .dep/*
|
||||||
|
$(Q)$(REMOVE) -rf codedoc
|
||||||
|
$(Q)$(REMOVE) -rf doxyinput
|
||||||
|
-$(Q)rmdir $(OBJDIR)
|
||||||
|
|
||||||
|
# Include the dependency files.
|
||||||
|
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
|
||||||
|
|
||||||
|
# Manual dependency for the assembler module
|
||||||
|
# $(OBJDIR)/fastloader-ll.o: config.h $(OBJDIR)/autoconf.h
|
||||||
|
|
||||||
|
# Listing of phony targets.
|
||||||
|
.PHONY : all begin finish end sizebefore sizeafter gccversion \
|
||||||
|
build elf hex eep lss sym coff extcoff \
|
||||||
|
clean clean_list program debug gdb-config doxygen
|
||||||
|
|
||||||
168
mk1-src/avrcompat.h
Normal file
168
mk1-src/avrcompat.h
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
/* sd2snes - SD card based universal cartridge for the SNES
|
||||||
|
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
|
||||||
|
|
||||||
|
This file was adapted from sd2iec, written by Ingo Korb, original
|
||||||
|
disclaimer follows:
|
||||||
|
*/
|
||||||
|
/* sd2iec - SD/MMC to Commodore serial bus interface/controller
|
||||||
|
Copyright (C) 2007-2009 Ingo Korb <ingo@akana.de>
|
||||||
|
|
||||||
|
Inspiration and low-level SD/MMC access based on code from MMC2IEC
|
||||||
|
by Lars Pontoppidan et al., see sdcard.c|h and config.h.
|
||||||
|
|
||||||
|
FAT filesystem access based on code from ChaN and Jim Brain, see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
|
avrcompat.h: Compatibility defines for multiple target chips
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVRCOMPAT_H
|
||||||
|
#define AVRCOMPAT_H
|
||||||
|
|
||||||
|
/* USART */
|
||||||
|
|
||||||
|
#if defined __AVR_ATmega644__ || defined __AVR_ATmega644P__ || defined __AVR_ATmega1281__ || defined __AVR_ATmega2561__
|
||||||
|
|
||||||
|
# ifdef USE_UART1
|
||||||
|
# define RXC RXC1
|
||||||
|
# define RXEN RXEN1
|
||||||
|
# define TXC TXC1
|
||||||
|
# define TXEN TXEN1
|
||||||
|
# define UBRRH UBRR1H
|
||||||
|
# define UBRRL UBRR1L
|
||||||
|
# define UCSRA UCSR1A
|
||||||
|
# define UCSRB UCSR1B
|
||||||
|
# define UCSRC UCSR1C
|
||||||
|
# define UCSZ0 UCSZ10
|
||||||
|
# define UCSZ1 UCSZ11
|
||||||
|
# define UDR UDR1
|
||||||
|
# define UDRIE UDRIE1
|
||||||
|
# define RXCIE RXCIE1
|
||||||
|
# define USART_UDRE_vect USART1_UDRE_vect
|
||||||
|
# define USART_RX_vect USART1_RX_vect
|
||||||
|
# else
|
||||||
|
/* Default is USART0 */
|
||||||
|
# define RXC RXC0
|
||||||
|
# define RXEN RXEN0
|
||||||
|
# define TXC TXC0
|
||||||
|
# define TXEN TXEN0
|
||||||
|
# define UBRRH UBRR0H
|
||||||
|
# define UBRRL UBRR0L
|
||||||
|
# define UCSRA UCSR0A
|
||||||
|
# define UCSRB UCSR0B
|
||||||
|
# define UCSRC UCSR0C
|
||||||
|
# define UCSZ0 UCSZ00
|
||||||
|
# define UCSZ1 UCSZ01
|
||||||
|
# define UDR UDR0
|
||||||
|
# define UDRIE UDRIE0
|
||||||
|
# define RXCIE RXCIE0
|
||||||
|
# define USART_UDRE_vect USART0_UDRE_vect
|
||||||
|
# define USART_RX_vect USART0_RX_vect
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif defined __AVR_ATmega48__ || defined __AVR_ATmega88__ || defined __AVR_ATmega168__
|
||||||
|
/* These chips include the USART number in their register names, */
|
||||||
|
/* but not in the ISR name. */
|
||||||
|
# define RXC RXC0
|
||||||
|
# define RXEN RXEN0
|
||||||
|
# define TXC TXC0
|
||||||
|
# define TXEN TXEN0
|
||||||
|
# define UBRRH UBRR0H
|
||||||
|
# define UBRRL UBRR0L
|
||||||
|
# define UCSRA UCSR0A
|
||||||
|
# define UCSRB UCSR0B
|
||||||
|
# define UCSRC UCSR0C
|
||||||
|
# define UCSZ0 UCSZ00
|
||||||
|
# define UCSZ1 UCSZ01
|
||||||
|
# define UDR UDR0
|
||||||
|
# define UDRIE UDRIE0
|
||||||
|
|
||||||
|
#elif defined __AVR_ATmega32__
|
||||||
|
# define TIMER2_COMPA_vect TIMER2_COMP_vect
|
||||||
|
# define TCCR0B TCCR0
|
||||||
|
# define TCCR2A TCCR2
|
||||||
|
# define TCCR2B TCCR2
|
||||||
|
# define TIFR0 TIFR
|
||||||
|
# define TIMSK2 TIMSK
|
||||||
|
# define OCIE2A OCIE2
|
||||||
|
# define OCR2A OCR2
|
||||||
|
|
||||||
|
#elif defined __AVR_ATmega128__
|
||||||
|
# define UBRRH UBRR0H
|
||||||
|
# define UBRRL UBRR0L
|
||||||
|
# define UCSRA UCSR0A
|
||||||
|
# define UCSRB UCSR0B
|
||||||
|
# define UCSRC UCSR0C
|
||||||
|
# define UDR UDR0
|
||||||
|
# define USART_UDRE_vect USART0_UDRE_vect
|
||||||
|
# define TIMER2_COMPA_vect TIMER2_COMP_vect
|
||||||
|
# define TCCR0B TCCR0
|
||||||
|
# define TCCR2A TCCR2
|
||||||
|
# define TCCR2B TCCR2
|
||||||
|
# define TIFR0 TIFR
|
||||||
|
# define TIMSK1 TIMSK
|
||||||
|
# define TIMSK2 TIMSK
|
||||||
|
# define OCIE2A OCIE2
|
||||||
|
# define OCR2A OCR2
|
||||||
|
|
||||||
|
#else
|
||||||
|
# error Unknown chip! (USART)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* SPI and I2C */
|
||||||
|
#if defined __AVR_ATmega32__ || defined __AVR_ATmega644__ || defined __AVR_ATmega644P__
|
||||||
|
|
||||||
|
# define SPI_PORT PORTB
|
||||||
|
# define SPI_DDR DDRB
|
||||||
|
# define SPI_SS _BV(PB4)
|
||||||
|
# define SPI_MOSI _BV(PB5)
|
||||||
|
# define SPI_MISO _BV(PB6)
|
||||||
|
# define SPI_SCK _BV(PB7)
|
||||||
|
# define HWI2C_PORT PORTC
|
||||||
|
# define HWI2C_SDA _BV(PC1)
|
||||||
|
# define HWI2C_SCL _BV(PC0)
|
||||||
|
|
||||||
|
#elif defined __AVR_ATmega128__ || defined __AVR_ATmega1281__ || defined __AVR_ATmega2561__
|
||||||
|
|
||||||
|
# define SPI_PORT PORTB
|
||||||
|
# define SPI_DDR DDRB
|
||||||
|
# define SPI_SS _BV(PB0)
|
||||||
|
# define SPI_SCK _BV(PB1)
|
||||||
|
# define SPI_MOSI _BV(PB2)
|
||||||
|
# define SPI_MISO _BV(PB3)
|
||||||
|
# define HWI2C_PORT PORTD
|
||||||
|
# define HWI2C_SDA _BV(PD1)
|
||||||
|
# define HWI2C_SCL _BV(PD0)
|
||||||
|
|
||||||
|
#elif defined __AVR_ATmega48__ || defined __AVR_ATmega88__ || defined __AVR_ATmega168__
|
||||||
|
|
||||||
|
# define SPI_PORT PORTB
|
||||||
|
# define SPI_DDR DDRB
|
||||||
|
# define SPI_SS _BV(PB2)
|
||||||
|
# define SPI_SCK _BV(PB5)
|
||||||
|
# define SPI_MOSI _BV(PB3)
|
||||||
|
# define SPI_MISO _BV(PB4)
|
||||||
|
# define HWI2C_PORT PORTC
|
||||||
|
# define HWI2C_SDA _BV(PC4)
|
||||||
|
# define HWI2C_SCL _BV(PC5)
|
||||||
|
|
||||||
|
#else
|
||||||
|
# error Unknown chip! (SPI/TWI)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SPI_MASK (SPI_SS|SPI_MOSI|SPI_MISO|SPI_SCK)
|
||||||
|
|
||||||
|
#endif /* AVRCOMPAT_H */
|
||||||
29
mk1-src/conf2h.awk
Normal file
29
mk1-src/conf2h.awk
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#! /usr/bin/gawk -f
|
||||||
|
|
||||||
|
# Trivial little script to convert from a makefile-style configuration
|
||||||
|
# file to a C header. No copyright claimed.
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
|
print "// autoconf.h generated from " ARGV[1] " at " strftime() "\n" \
|
||||||
|
"#ifndef AUTOCONF_H\n" \
|
||||||
|
"#define AUTOCONF_H"
|
||||||
|
}
|
||||||
|
|
||||||
|
/^#/ { sub(/^#/,"//") }
|
||||||
|
|
||||||
|
/^CONFIG_.*=/ {
|
||||||
|
if (/=n$/) {
|
||||||
|
sub(/^/,"// ");
|
||||||
|
} else {
|
||||||
|
sub(/^/,"#define ")
|
||||||
|
if (/=y$/) {
|
||||||
|
sub(/=.*$/,"")
|
||||||
|
} else {
|
||||||
|
sub(/=/," ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{ print }
|
||||||
|
|
||||||
|
END { print "#endif" }
|
||||||
47
mk1-src/config
Normal file
47
mk1-src/config
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
# This may not look like it, but it's a -*- makefile -*-
|
||||||
|
# sd2snes - SD card based universal cartridge for the SNES
|
||||||
|
# Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
|
||||||
|
#
|
||||||
|
# This file was adapted from sd2iec, written by Ingo Korb.
|
||||||
|
# Original disclaimer follows:
|
||||||
|
#
|
||||||
|
# sd2iec - SD/MMC to Commodore serial bus interface/controller
|
||||||
|
# Copyright (C) 2007-2009 Ingo Korb <ingo@akana.de>
|
||||||
|
#
|
||||||
|
# Inspiration and low-level SD/MMC access based on code from MMC2IEC
|
||||||
|
# by Lars Pontoppidan et al., see sdcard.c|h and config.h.
|
||||||
|
#
|
||||||
|
# FAT filesystem access based on code from ChaN, see tff.c|h.
|
||||||
|
#
|
||||||
|
# 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; version 2 of the License only.
|
||||||
|
#
|
||||||
|
# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# This file is included in the main sd2iec Makefile and also parsed
|
||||||
|
# into autoconf.h.
|
||||||
|
|
||||||
|
CONFIG_MCU=atmega644
|
||||||
|
CONFIG_LINKER_RELAX=n
|
||||||
|
CONFIG_MCU_FREQ=12288000
|
||||||
|
CONFIG_BOOTLOADER=y
|
||||||
|
CONFIG_BOOT_DEVID=0x4e534453
|
||||||
|
CONFIG_UART_DEBUG=y
|
||||||
|
CONFIG_UART_BAUDRATE=384000
|
||||||
|
CONFIG_UART_BUF_SHIFT=7
|
||||||
|
CONFIG_HARDWARE_NAME=sd2snes
|
||||||
|
CONFIG_SD_AUTO_RETRIES=10
|
||||||
|
#CONFIG_SD_DATACRC=y
|
||||||
|
CONFIG_EEPROM_SIZE=512
|
||||||
|
CONFIG_EEPROM_OFFSET=512
|
||||||
|
CONFIG_MAX_PARTITIONS=1
|
||||||
|
#CONFIG_DEADLOCK_ME_HARDER=y
|
||||||
119
mk1-src/config.h
Normal file
119
mk1-src/config.h
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
/* sd2snes - SD card based universal cartridge for the SNES
|
||||||
|
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
|
||||||
|
This file was adapted from sd2iec, written by Ingo Korb.
|
||||||
|
Original copyright header follows:
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
sd2iec - SD/MMC to Commodore serial bus interface/controller
|
||||||
|
Copyright (C) 2007-2009 Ingo Korb <ingo@akana.de>
|
||||||
|
|
||||||
|
Inspiration and low-level SD/MMC access based on code from MMC2IEC
|
||||||
|
by Lars Pontoppidan et al., see sdcard.c|h and config.h.
|
||||||
|
|
||||||
|
FAT filesystem access based on code from ChaN and Jim Brain, see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
|
config.h: User-configurable options to simplify hardware changes and/or
|
||||||
|
reduce the code/ram requirements of the code.
|
||||||
|
|
||||||
|
|
||||||
|
Based on MMC2IEC, original copyright header follows:
|
||||||
|
|
||||||
|
//
|
||||||
|
// Title : MMC2IEC - Configuration
|
||||||
|
// Author : Lars Pontoppidan
|
||||||
|
// Date : Jan. 2007
|
||||||
|
// Version : 0.7
|
||||||
|
// Target MCU : AtMega32(L) at 8 MHz
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// DISCLAIMER:
|
||||||
|
// The author is in no way responsible for any problems or damage caused by
|
||||||
|
// using this code. Use at your own risk.
|
||||||
|
//
|
||||||
|
// LICENSE:
|
||||||
|
// This code is distributed under the GNU Public License
|
||||||
|
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
||||||
|
//
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CONFIG_H
|
||||||
|
#define CONFIG_H
|
||||||
|
|
||||||
|
#include "autoconf.h"
|
||||||
|
|
||||||
|
# define HW_NAME "SD2IEC"
|
||||||
|
# define HAVE_SD
|
||||||
|
# define SDCARD_DETECT (!(PIND & _BV(PD2)))
|
||||||
|
# define SDCARD_DETECT_SETUP() do { DDRD &= ~_BV(PD2); PORTD |= _BV(PD2); } while(0)
|
||||||
|
# if defined __AVR_ATmega32__
|
||||||
|
# define SD_CHANGE_SETUP() do { MCUCR |= _BV(ISC00); GICR |= _BV(INT0); } while(0)
|
||||||
|
# elif defined __AVR_ATmega644__ || defined __AVR_ATmega644P__
|
||||||
|
# define SD_CHANGE_SETUP() do { EICRA |= _BV(ISC00); EIMSK |= _BV(INT0); } while(0)
|
||||||
|
# else
|
||||||
|
# error Unknown chip!
|
||||||
|
# endif
|
||||||
|
# define SD_CHANGE_VECT INT0_vect
|
||||||
|
# define SDCARD_WP (PINA & _BV(PA0))
|
||||||
|
# define SDCARD_WP_SETUP() do { DDRA &= ~ _BV(PA0); PORTA |= _BV(PA0); } while(0)
|
||||||
|
# define SD_CHANGE_ICR MCUCR
|
||||||
|
# define SD_SUPPLY_VOLTAGE (1L<<21)
|
||||||
|
# define DEVICE_SELECT (8+!(PINA & _BV(PA2))+2*!(PINA & _BV(PA3)))
|
||||||
|
# define DEVICE_SELECT_SETUP() do { \
|
||||||
|
DDRA &= ~(_BV(PA2)|_BV(PA3)); \
|
||||||
|
PORTA |= _BV(PA2)|_BV(PA3); \
|
||||||
|
} while (0)
|
||||||
|
# define BUSY_LED_SETDDR() DDRA |= _BV(PA0)
|
||||||
|
# define BUSY_LED_ON() PORTA &= ~_BV(PA0)
|
||||||
|
# define BUSY_LED_OFF() PORTA |= _BV(PA0)
|
||||||
|
# define DIRTY_LED_SETDDR() DDRA |= _BV(PA1)
|
||||||
|
# define DIRTY_LED_ON() PORTA &= ~_BV(PA1)
|
||||||
|
# define DIRTY_LED_OFF() PORTA |= _BV(PA1)
|
||||||
|
# define DIRTY_LED_PORT PORTA
|
||||||
|
# define DIRTY_LED_BIT() _BV(PA1)
|
||||||
|
# define AUX_LED_SETDDR() do {} while (0)
|
||||||
|
# define AUX_LED_ON() do {} while (0)
|
||||||
|
# define AUX_LED_OFF() do {} while (0)
|
||||||
|
# define BUTTON_PIN PINA
|
||||||
|
# define BUTTON_PORT PORTA
|
||||||
|
# define BUTTON_DDR DDRA
|
||||||
|
# define BUTTON_MASK (_BV(PA4)|_BV(PA5))
|
||||||
|
# define BUTTON_NEXT _BV(PA4)
|
||||||
|
# define BUTTON_PREV _BV(PA5)
|
||||||
|
|
||||||
|
/* An interrupt for detecting card changes implies hotplugging capability */
|
||||||
|
#if defined(SD_CHANGE_VECT) || defined (CF_CHANGE_VECT)
|
||||||
|
# define HAVE_HOTPLUG
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Generate dummy functions for the BUSY LED if required */
|
||||||
|
#ifdef SINGLE_LED
|
||||||
|
# define BUSY_LED_SETDDR() do {} while(0)
|
||||||
|
# define BUSY_LED_ON() do {} while(0)
|
||||||
|
# define BUSY_LED_OFF() do {} while(0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Create some temporary symbols so we can calculate the number of */
|
||||||
|
/* enabled storage devices. */
|
||||||
|
#ifdef HAVE_SD
|
||||||
|
# define TMP_SD 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Remove the temporary symbols */
|
||||||
|
#undef TMP_SD
|
||||||
|
|
||||||
|
#endif
|
||||||
51
mk1-src/crc16.c
Normal file
51
mk1-src/crc16.c
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/**
|
||||||
|
* \file stdout
|
||||||
|
* Functions and types for CRC checks.
|
||||||
|
*
|
||||||
|
* Generated on Tue Jun 30 23:02:59 2009,
|
||||||
|
* by pycrc v0.7.1, http://www.tty1.net/pycrc/
|
||||||
|
* using the configuration:
|
||||||
|
* Width = 16
|
||||||
|
* Poly = 0x8005
|
||||||
|
* XorIn = 0x0000
|
||||||
|
* ReflectIn = True
|
||||||
|
* XorOut = 0x0000
|
||||||
|
* ReflectOut = True
|
||||||
|
* Algorithm = bit-by-bit-fast
|
||||||
|
* Direct = True
|
||||||
|
*****************************************************************************/
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "crc16.h"
|
||||||
|
/**
|
||||||
|
* Update the crc value with new data.
|
||||||
|
*
|
||||||
|
* \param crc The current crc value.
|
||||||
|
* \param data Pointer to a buffer of \a data_len bytes.
|
||||||
|
* \param data_len Number of bytes in the \a data buffer.
|
||||||
|
* \return The updated crc value.
|
||||||
|
*****************************************************************************/
|
||||||
|
crc_t crc16_update(crc_t crc, const unsigned char *data, size_t data_len)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
uint8_t bit;
|
||||||
|
unsigned char c;
|
||||||
|
|
||||||
|
while (data_len--) {
|
||||||
|
c = *data++;
|
||||||
|
for (i = 0x01; i & 0xff; i <<= 1) {
|
||||||
|
bit = (crc & 0x8000 ? 1 : 0);
|
||||||
|
if (c & i) {
|
||||||
|
bit ^= 1;
|
||||||
|
}
|
||||||
|
crc <<= 1;
|
||||||
|
if (bit) {
|
||||||
|
crc ^= 0x8005;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
crc &= 0xffff;
|
||||||
|
}
|
||||||
|
return crc & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
54
mk1-src/crc16.h
Normal file
54
mk1-src/crc16.h
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* \file stdout
|
||||||
|
* Functions and types for CRC checks.
|
||||||
|
*
|
||||||
|
* Generated on Tue Jun 30 23:02:56 2009,
|
||||||
|
* by pycrc v0.7.1, http://www.tty1.net/pycrc/
|
||||||
|
* using the configuration:
|
||||||
|
* Width = 16
|
||||||
|
* Poly = 0x8005
|
||||||
|
* XorIn = 0x0000
|
||||||
|
* ReflectIn = True
|
||||||
|
* XorOut = 0x0000
|
||||||
|
* ReflectOut = True
|
||||||
|
* Algorithm = bit-by-bit-fast
|
||||||
|
* Direct = True
|
||||||
|
*****************************************************************************/
|
||||||
|
#ifndef __STDOUT__
|
||||||
|
#define __STDOUT__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The definition of the used algorithm.
|
||||||
|
*****************************************************************************/
|
||||||
|
#define CRC_ALGO_BIT_BY_BIT_FAST 1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of the CRC values.
|
||||||
|
*
|
||||||
|
* This type must be big enough to contain at least 16 bits.
|
||||||
|
*****************************************************************************/
|
||||||
|
typedef uint16_t crc_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the crc value with new data.
|
||||||
|
*
|
||||||
|
* \param crc The current crc value.
|
||||||
|
* \param data Pointer to a buffer of \a data_len bytes.
|
||||||
|
* \param data_len Number of bytes in the \a data buffer.
|
||||||
|
* \return The updated crc value.
|
||||||
|
*****************************************************************************/
|
||||||
|
crc_t crc16_update(crc_t crc, const unsigned char *data, size_t data_len);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* closing brace for extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __STDOUT__ */
|
||||||
|
|
||||||
74
mk1-src/crc32.c
Normal file
74
mk1-src/crc32.c
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
/**
|
||||||
|
* \file stdout
|
||||||
|
* Functions and types for CRC checks.
|
||||||
|
*
|
||||||
|
* Generated on Tue Jun 30 21:35:13 2009,
|
||||||
|
* by pycrc v0.7.1, http://www.tty1.net/pycrc/
|
||||||
|
* using the configuration:
|
||||||
|
* Width = 32
|
||||||
|
* Poly = 0x04c11db7
|
||||||
|
* XorIn = 0xffffffff
|
||||||
|
* ReflectIn = True
|
||||||
|
* XorOut = 0xffffffff
|
||||||
|
* ReflectOut = True
|
||||||
|
* Algorithm = bit-by-bit-fast
|
||||||
|
* Direct = True
|
||||||
|
*****************************************************************************/
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "crc32.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reflect all bits of a \a data word of \a data_len bytes.
|
||||||
|
*
|
||||||
|
* \param data The data word to be reflected.
|
||||||
|
* \param data_len The width of \a data expressed in number of bits.
|
||||||
|
* \return The reflected data.
|
||||||
|
*****************************************************************************/
|
||||||
|
long crc_reflect(long data, size_t data_len)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
long ret;
|
||||||
|
|
||||||
|
ret = data & 0x01;
|
||||||
|
for (i = 1; i < data_len; i++)
|
||||||
|
{
|
||||||
|
data >>= 1;
|
||||||
|
ret = (ret << 1) | (data & 0x01);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the crc value with new data.
|
||||||
|
*
|
||||||
|
* \param crc The current crc value.
|
||||||
|
* \param data Pointer to a buffer of \a data_len bytes.
|
||||||
|
* \param data_len Number of bytes in the \a data buffer.
|
||||||
|
* \return The updated crc value.
|
||||||
|
*****************************************************************************/
|
||||||
|
crc_t crc_update(crc_t crc, const unsigned char *data, size_t data_len)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
uint8_t bit;
|
||||||
|
unsigned char c;
|
||||||
|
|
||||||
|
while (data_len--) {
|
||||||
|
c = *data++;
|
||||||
|
for (i = 0x01; i & 0xff; i <<= 1) {
|
||||||
|
bit = ((crc & 0x80000000) ? 1 : 0);
|
||||||
|
if (c & i) {
|
||||||
|
bit ^= 1;
|
||||||
|
}
|
||||||
|
crc <<= 1;
|
||||||
|
if (bit) {
|
||||||
|
crc ^= 0x04c11db7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
crc &= 0xffffffff;
|
||||||
|
}
|
||||||
|
return crc & 0xffffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
85
mk1-src/crc32.h
Normal file
85
mk1-src/crc32.h
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
/**
|
||||||
|
* \file stdout
|
||||||
|
* Functions and types for CRC checks.
|
||||||
|
*
|
||||||
|
* Generated on Tue Jun 30 21:35:19 2009,
|
||||||
|
* by pycrc v0.7.1, http://www.tty1.net/pycrc/
|
||||||
|
* using the configuration:
|
||||||
|
* Width = 32
|
||||||
|
* Poly = 0x04c11db7
|
||||||
|
* XorIn = 0xffffffff
|
||||||
|
* ReflectIn = True
|
||||||
|
* XorOut = 0xffffffff
|
||||||
|
* ReflectOut = True
|
||||||
|
* Algorithm = bit-by-bit-fast
|
||||||
|
* Direct = True
|
||||||
|
*****************************************************************************/
|
||||||
|
#ifndef __STDOUT__
|
||||||
|
#define __STDOUT__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The definition of the used algorithm.
|
||||||
|
*****************************************************************************/
|
||||||
|
#define CRC_ALGO_BIT_BY_BIT_FAST 1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of the CRC values.
|
||||||
|
*
|
||||||
|
* This type must be big enough to contain at least 32 bits.
|
||||||
|
*****************************************************************************/
|
||||||
|
typedef uint32_t crc_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reflect all bits of a \a data word of \a data_len bytes.
|
||||||
|
*
|
||||||
|
* \param data The data word to be reflected.
|
||||||
|
* \param data_len The width of \a data expressed in number of bits.
|
||||||
|
* \return The reflected data.
|
||||||
|
*****************************************************************************/
|
||||||
|
long crc_reflect(long data, size_t data_len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the initial crc value.
|
||||||
|
*
|
||||||
|
* \return The initial crc value.
|
||||||
|
*****************************************************************************/
|
||||||
|
static inline crc_t crc_init(void)
|
||||||
|
{
|
||||||
|
return 0xffffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the crc value with new data.
|
||||||
|
*
|
||||||
|
* \param crc The current crc value.
|
||||||
|
* \param data Pointer to a buffer of \a data_len bytes.
|
||||||
|
* \param data_len Number of bytes in the \a data buffer.
|
||||||
|
* \return The updated crc value.
|
||||||
|
*****************************************************************************/
|
||||||
|
crc_t crc_update(crc_t crc, const unsigned char *data, size_t data_len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the final crc value.
|
||||||
|
*
|
||||||
|
* \param crc The current crc value.
|
||||||
|
* \return The final crc value.
|
||||||
|
*****************************************************************************/
|
||||||
|
static inline crc_t crc_finalize(crc_t crc)
|
||||||
|
{
|
||||||
|
return crc_reflect(crc, 32) ^ 0xffffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* closing brace for extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __STDOUT__ */
|
||||||
|
|
||||||
107
mk1-src/crc7.c
Normal file
107
mk1-src/crc7.c
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
/* This file is a modified version of the output of pycrc.
|
||||||
|
*
|
||||||
|
* Licensing terms of pycrc:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006-2007, Thomas Pircher <tehpeh@gmx.net>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* crc7.c: Calculate CRC7 for SD card commands
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Functions and types for CRC checks.
|
||||||
|
*
|
||||||
|
* Generated on Thu Nov 8 13:52:05 2007,
|
||||||
|
* by pycrc v0.6.3, http://www.tty1.net/pycrc/
|
||||||
|
* using the configuration:
|
||||||
|
* Width = 7
|
||||||
|
* Poly = 0x09
|
||||||
|
* XorIn = 0x00
|
||||||
|
* ReflectIn = False
|
||||||
|
* XorOut = 0x00
|
||||||
|
* ReflectOut = False
|
||||||
|
* Algorithm = bit-by-bit-fast
|
||||||
|
*/
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
; MMC/SD CRC Polynom X^7 + X^3 + 1
|
||||||
|
crc7taba:
|
||||||
|
mov dptr,#CRC7_TABA ; (2)
|
||||||
|
clr c ; (1)
|
||||||
|
rrc a ; (1)
|
||||||
|
xrl a,crc7ta ; (1)
|
||||||
|
movc a,@a+dptr ; (2)
|
||||||
|
jnc crc7m ; (2)
|
||||||
|
xrl a,#00001001b ; (1)
|
||||||
|
crc7m: mov crc7ta,a ; (1)
|
||||||
|
ret ; (2) (LCALL=2)
|
||||||
|
*/
|
||||||
|
uint8_t crc7tab[128] = {
|
||||||
|
0x00,0x12,0x24,0x36,0x48,0x5a,0x6c,0x7e,
|
||||||
|
0x19,0x0b,0x3d,0x2f,0x51,0x43,0x75,0x67,
|
||||||
|
0x32,0x20,0x16,0x04,0x7a,0x68,0x5e,0x4c,
|
||||||
|
0x2b,0x39,0x0f,0x1d,0x63,0x71,0x47,0x55,
|
||||||
|
0x64,0x76,0x40,0x52,0x2c,0x3e,0x08,0x1a,
|
||||||
|
0x7d,0x6f,0x59,0x4b,0x35,0x27,0x11,0x03,
|
||||||
|
0x56,0x44,0x72,0x60,0x1e,0x0c,0x3a,0x28,
|
||||||
|
0x4f,0x5d,0x6b,0x79,0x07,0x15,0x23,0x31,
|
||||||
|
0x41,0x53,0x65,0x77,0x09,0x1b,0x2d,0x3f,
|
||||||
|
0x58,0x4a,0x7c,0x6e,0x10,0x02,0x34,0x26,
|
||||||
|
0x73,0x61,0x57,0x45,0x3b,0x29,0x1f,0x0d,
|
||||||
|
0x6a,0x78,0x4e,0x5c,0x22,0x30,0x06,0x14,
|
||||||
|
0x25,0x37,0x01,0x13,0x6d,0x7f,0x49,0x5b,
|
||||||
|
0x3c,0x2e,0x18,0x0a,0x74,0x66,0x50,0x42,
|
||||||
|
0x17,0x05,0x33,0x21,0x5f,0x4d,0x7b,0x69,
|
||||||
|
0x0e,0x1c,0x2a,0x38,0x46,0x54,0x62,0x70
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t crc7update(uint8_t crc, const uint8_t data) {
|
||||||
|
uint8_t a = data;
|
||||||
|
uint8_t b = data & 1;
|
||||||
|
a = crc7tab[(a>>1) ^ crc];
|
||||||
|
a ^= ((b<<3)|(b));
|
||||||
|
crc = a;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*uint8_t crc7update(uint8_t crc, const uint8_t data) {
|
||||||
|
uint8_t i;
|
||||||
|
bool bit;
|
||||||
|
uint8_t c;
|
||||||
|
|
||||||
|
c = data;
|
||||||
|
for (i = 0x80; i > 0; i >>= 1) {
|
||||||
|
bit = crc & 0x40;
|
||||||
|
if (c & i) {
|
||||||
|
bit = !bit;
|
||||||
|
}
|
||||||
|
crc <<= 1;
|
||||||
|
if (bit) {
|
||||||
|
crc ^= 0x09;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
crc &= 0x7f;
|
||||||
|
return crc & 0x7f;
|
||||||
|
}*/
|
||||||
33
mk1-src/crc7.h
Normal file
33
mk1-src/crc7.h
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/* sd2iec - SD/MMC to Commodore serial bus interface/controller
|
||||||
|
Copyright (C) 2007-2009 Ingo Korb <ingo@akana.de>
|
||||||
|
|
||||||
|
Inspiration and low-level SD/MMC access based on code from MMC2IEC
|
||||||
|
by Lars Pontoppidan et al., see sdcard.c|h and config.h.
|
||||||
|
|
||||||
|
FAT filesystem access based on code from ChaN and Jim Brain, see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
|
crc7.h: Definitions for CRC7 calculation routines
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CRC7_H
|
||||||
|
#define CRC7_H
|
||||||
|
|
||||||
|
uint8_t crc7update(uint8_t crc, const uint8_t data);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
85
mk1-src/crcgen-new.c
Normal file
85
mk1-src/crcgen-new.c
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define lo8(x) (x & 0xFF)
|
||||||
|
#define hi8(x) ((x >> 8) & 0xFF)
|
||||||
|
#define xhi8(x) ((x >> 16) & 0xff)
|
||||||
|
#define xxhi8(x) ((x >> 24) & 0xff)
|
||||||
|
|
||||||
|
unsigned short crc_ccitt_update (uint16_t crc, uint8_t data)
|
||||||
|
{
|
||||||
|
data ^= lo8 (crc);
|
||||||
|
data ^= data << 4;
|
||||||
|
return ((((uint16_t)data << 8) | hi8 (crc)) ^ (uint8_t)(data >> 4) ^ ((uint16_t)data << 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
if (argc != 5) {
|
||||||
|
printf("Usage: crcgen <filename> <length> <signature> <version>\r\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long length = strtol(argv[2],NULL,0);
|
||||||
|
unsigned long devid = strtol(argv[3],NULL,0);
|
||||||
|
unsigned long version = strtol(argv[4],NULL,0);
|
||||||
|
|
||||||
|
if (length > length+8) {
|
||||||
|
printf("Ha ha, very funny.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *data = malloc(length+8);
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
perror("malloc");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(data, 0xff, length);
|
||||||
|
|
||||||
|
FILE *f;
|
||||||
|
|
||||||
|
f = fopen(argv[1], "rb+");
|
||||||
|
|
||||||
|
if (f == 0) {
|
||||||
|
printf("Unable to open file %s\r\n", argv[1]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fread(data, 1, length, f);
|
||||||
|
|
||||||
|
data[length-8] = lo8(devid);
|
||||||
|
data[length-7] = hi8(devid);
|
||||||
|
data[length-6] = xhi8(devid);
|
||||||
|
data[length-5] = xxhi8(devid);
|
||||||
|
data[length-4] = lo8(version);
|
||||||
|
data[length-3] = hi8(version);
|
||||||
|
|
||||||
|
unsigned long l;
|
||||||
|
unsigned short crc = 0xFFFF;
|
||||||
|
|
||||||
|
for (l=0; l < length-2; l++)
|
||||||
|
crc = crc_ccitt_update(crc, data[l]);
|
||||||
|
|
||||||
|
data[length-2] = lo8(crc);
|
||||||
|
data[length-1] = hi8(crc);
|
||||||
|
|
||||||
|
if (fseek(f, 0, SEEK_SET)) {
|
||||||
|
perror("fseek");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fwrite(data, length, 1, f) != 1) {
|
||||||
|
perror("fwrite");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
202
mk1-src/diskio.c
Normal file
202
mk1-src/diskio.c
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
/* sd2snes - SD card based universal cartridge for the SNES
|
||||||
|
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
|
||||||
|
This file was adapted from sd2iec, written by Ingo Korb.
|
||||||
|
Original copyright header follows:
|
||||||
|
*/
|
||||||
|
/* sd2iec - SD/MMC to Commodore serial bus interface/controller
|
||||||
|
Copyright (C) 2007-2009 Ingo Korb <ingo@akana.de>
|
||||||
|
|
||||||
|
Inspiration and low-level SD/MMC access based on code from MMC2IEC
|
||||||
|
by Lars Pontoppidan et al., see sdcard.c|h and config.h.
|
||||||
|
|
||||||
|
FAT filesystem access based on code from ChaN and Jim Brain, see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
|
diskio.c: Generic disk access routines and supporting stuff
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "diskio.h"
|
||||||
|
#include "sdcard.h"
|
||||||
|
|
||||||
|
volatile enum diskstates disk_state;
|
||||||
|
|
||||||
|
#ifdef NEED_DISKMUX
|
||||||
|
|
||||||
|
uint32_t drive_config;
|
||||||
|
|
||||||
|
/* This function calculates the default drive configuration. */
|
||||||
|
/* Its result is static after compilation, but doing this in */
|
||||||
|
/* C in less messy than doing it with the preprocessor. */
|
||||||
|
uint32_t get_default_driveconfig(void) {
|
||||||
|
uint32_t result = 0xffffffffL;
|
||||||
|
|
||||||
|
/* Order matters: Whatever is checked first will be last in the config */
|
||||||
|
#ifdef HAVE_DF
|
||||||
|
result = (result << 4) + (DISK_TYPE_DF << DRIVE_BITS) + 0;
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_TWINSD
|
||||||
|
result = (result << 4) + (DISK_TYPE_SD << DRIVE_BITS) + 1;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SD
|
||||||
|
result = (result << 4) + (DISK_TYPE_SD << DRIVE_BITS) + 0;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_ATA
|
||||||
|
result = (result << 4) + (DISK_TYPE_ATA << DRIVE_BITS) + 0;
|
||||||
|
#endif
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void disk_init(void) {
|
||||||
|
#ifdef HAVE_SD
|
||||||
|
sd_init();
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_ATA
|
||||||
|
ata_init();
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_DF
|
||||||
|
df_init();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
DSTATUS disk_status(BYTE drv) {
|
||||||
|
switch(drv >> DRIVE_BITS) {
|
||||||
|
#ifdef HAVE_DF
|
||||||
|
case DISK_TYPE_DF:
|
||||||
|
return df_status(drv & DRIVE_MASK);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_ATA
|
||||||
|
case DISK_TYPE_ATA:
|
||||||
|
return ata_status(drv & DRIVE_MASK);
|
||||||
|
|
||||||
|
case DISK_TYPE_ATA2:
|
||||||
|
return ata_status((drv & DRIVE_MASK) + 2);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SD
|
||||||
|
case DISK_TYPE_SD:
|
||||||
|
return sd_status(drv & DRIVE_MASK);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
return STA_NOINIT|STA_NODISK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DSTATUS disk_initialize(BYTE drv) {
|
||||||
|
switch(drv >> DRIVE_BITS) {
|
||||||
|
#ifdef HAVE_DF
|
||||||
|
case DISK_TYPE_DF:
|
||||||
|
return df_initialize(drv & DRIVE_MASK);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_ATA
|
||||||
|
case DISK_TYPE_ATA:
|
||||||
|
return ata_initialize(drv & DRIVE_MASK);
|
||||||
|
|
||||||
|
case DISK_TYPE_ATA2:
|
||||||
|
return ata_initialize((drv & DRIVE_MASK) + 2);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SD
|
||||||
|
case DISK_TYPE_SD:
|
||||||
|
return sd_initialize(drv & DRIVE_MASK);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
return STA_NOINIT|STA_NODISK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DRESULT disk_read(BYTE drv, BYTE *buffer, DWORD sector, BYTE count) {
|
||||||
|
switch(drv >> DRIVE_BITS) {
|
||||||
|
#ifdef HAVE_DF
|
||||||
|
case DISK_TYPE_DF:
|
||||||
|
return df_read(drv & DRIVE_MASK,buffer,sector,count);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_ATA
|
||||||
|
case DISK_TYPE_ATA:
|
||||||
|
return ata_read(drv & DRIVE_MASK,buffer,sector,count);
|
||||||
|
|
||||||
|
case DISK_TYPE_ATA2:
|
||||||
|
return ata_read((drv & DRIVE_MASK) + 2,buffer,sector,count);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SD
|
||||||
|
case DISK_TYPE_SD:
|
||||||
|
return sd_read(drv & DRIVE_MASK,buffer,sector,count);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
return RES_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DRESULT disk_write(BYTE drv, const BYTE *buffer, DWORD sector, BYTE count) {
|
||||||
|
switch(drv >> DRIVE_BITS) {
|
||||||
|
#ifdef HAVE_DF
|
||||||
|
case DISK_TYPE_DF:
|
||||||
|
return df_write(drv & DRIVE_MASK,buffer,sector,count);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_ATA
|
||||||
|
case DISK_TYPE_ATA:
|
||||||
|
return ata_write(drv & DRIVE_MASK,buffer,sector,count);
|
||||||
|
|
||||||
|
case DISK_TYPE_ATA2:
|
||||||
|
return ata_write((drv & DRIVE_MASK) + 2,buffer,sector,count);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SD
|
||||||
|
case DISK_TYPE_SD:
|
||||||
|
return sd_write(drv & DRIVE_MASK,buffer,sector,count);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
return RES_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DRESULT disk_getinfo(BYTE drv, BYTE page, void *buffer) {
|
||||||
|
switch(drv >> DRIVE_BITS) {
|
||||||
|
#ifdef HAVE_DF
|
||||||
|
case DISK_TYPE_DF:
|
||||||
|
return df_getinfo(drv & DRIVE_MASK,page,buffer);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_ATA
|
||||||
|
case DISK_TYPE_ATA:
|
||||||
|
return ata_getinfo(drv & DRIVE_MASK,page,buffer);
|
||||||
|
|
||||||
|
case DISK_TYPE_ATA2:
|
||||||
|
return ata_getinfo((drv & DRIVE_MASK) + 2,page,buffer);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SD
|
||||||
|
case DISK_TYPE_SD:
|
||||||
|
return sd_getinfo(drv & DRIVE_MASK,page,buffer);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
return RES_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
132
mk1-src/diskio.h
Normal file
132
mk1-src/diskio.h
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
/* sd2snes - SD card based universal cartridge for the SNES
|
||||||
|
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
|
||||||
|
This file was adapted from sd2iec, written by Ingo Korb.
|
||||||
|
Original copyright header follows:
|
||||||
|
*/
|
||||||
|
/* sd2iec - SD/MMC to Commodore serial bus interface/controller
|
||||||
|
Copyright (C) 2007-2009 Ingo Korb <ingo@akana.de>
|
||||||
|
|
||||||
|
Inspiration and low-level SD/MMC access based on code from MMC2IEC
|
||||||
|
by Lars Pontoppidan et al., see sdcard.c|h and config.h.
|
||||||
|
|
||||||
|
FAT filesystem access based on code from ChaN and Jim Brain, see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
|
diskio.h: Definitions for the disk access routines
|
||||||
|
|
||||||
|
Based on diskio.h from FatFS by ChaN, see ff.c for
|
||||||
|
for full copyright details.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DISKIO_H
|
||||||
|
#define DISKIO_H
|
||||||
|
|
||||||
|
#include "integer.h"
|
||||||
|
|
||||||
|
/* Status of Disk Functions */
|
||||||
|
typedef BYTE DSTATUS;
|
||||||
|
|
||||||
|
/* Disk Status Bits (DSTATUS) */
|
||||||
|
#define STA_NOINIT 0x01 /* Drive not initialized */
|
||||||
|
#define STA_NODISK 0x02 /* No medium in the drive */
|
||||||
|
#define STA_PROTECT 0x04 /* Write protected */
|
||||||
|
|
||||||
|
/* Results of Disk Functions */
|
||||||
|
typedef enum {
|
||||||
|
RES_OK = 0, /* 0: Successful */
|
||||||
|
RES_ERROR, /* 1: R/W Error */
|
||||||
|
RES_WRPRT, /* 2: Write Protected */
|
||||||
|
RES_NOTRDY, /* 3: Not Ready */
|
||||||
|
RES_PARERR /* 4: Invalid Parameter */
|
||||||
|
} DRESULT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct diskinfo0_t - disk info data structure for page 0
|
||||||
|
* @validbytes : Number of valid bytes in this struct
|
||||||
|
* @maxpage : Highest diskinfo page supported
|
||||||
|
* @disktype : type of the disk (DISK_TYPE_* values)
|
||||||
|
* @sectorsize : sector size divided by 256
|
||||||
|
* @sectorcount: number of sectors on the disk
|
||||||
|
*
|
||||||
|
* This is the struct returned in the data buffer when disk_getinfo
|
||||||
|
* is called with page=0.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
uint8_t validbytes;
|
||||||
|
uint8_t maxpage;
|
||||||
|
uint8_t disktype;
|
||||||
|
uint8_t sectorsize; /* divided by 256 */
|
||||||
|
uint32_t sectorcount; /* 2 TB should be enough... (512 byte sectors) */
|
||||||
|
} diskinfo0_t;
|
||||||
|
|
||||||
|
/*---------------------------------------*/
|
||||||
|
/* Prototypes for disk control functions */
|
||||||
|
|
||||||
|
DSTATUS disk_initialize (BYTE);
|
||||||
|
DSTATUS disk_status (BYTE);
|
||||||
|
DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE);
|
||||||
|
DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE);
|
||||||
|
#define disk_ioctl(a,b,c) RES_OK
|
||||||
|
DRESULT disk_getinfo(BYTE drv, BYTE page, void *buffer);
|
||||||
|
|
||||||
|
void disk_init(void);
|
||||||
|
|
||||||
|
uint8_t SD_SPI_OFFLOAD;
|
||||||
|
|
||||||
|
/* Will be set to DISK_ERROR if any access on the card fails */
|
||||||
|
enum diskstates { DISK_CHANGED = 0, DISK_REMOVED, DISK_OK, DISK_ERROR };
|
||||||
|
|
||||||
|
extern volatile enum diskstates disk_state;
|
||||||
|
|
||||||
|
/* Disk type - part of the external API except for ATA2! */
|
||||||
|
#define DISK_TYPE_ATA 0
|
||||||
|
#define DISK_TYPE_ATA2 1
|
||||||
|
#define DISK_TYPE_SD 2
|
||||||
|
#define DISK_TYPE_DF 3
|
||||||
|
#define DISK_TYPE_NONE 7
|
||||||
|
|
||||||
|
#ifdef NEED_DISKMUX
|
||||||
|
|
||||||
|
/* Disk mux configuration */
|
||||||
|
|
||||||
|
extern uint32_t drive_config;
|
||||||
|
|
||||||
|
uint32_t get_default_driveconfig(void);
|
||||||
|
|
||||||
|
# define set_map_drive(drv,val) (drive_config = \
|
||||||
|
(drive_config & (0xffffffff - (0x0f << (drv * 4)))) \
|
||||||
|
| (val << (drv * 4)))
|
||||||
|
# define map_drive(drv) ((drive_config >> (4 * drv)) & 0x0f)
|
||||||
|
# define set_drive_config(config) drive_config = config
|
||||||
|
|
||||||
|
/* Number of bits used for the drive, the disk type */
|
||||||
|
/* uses the remainder (4 bits per entry). */
|
||||||
|
# define DRIVE_BITS 1
|
||||||
|
|
||||||
|
/* Calculate mask from the shift value */
|
||||||
|
# define DRIVE_MASK ((1 << DRIVE_BITS)-1)
|
||||||
|
|
||||||
|
#else // NEED_DISKMUX
|
||||||
|
|
||||||
|
# define set_map_drive(drv,val) do {} while(0)
|
||||||
|
# define map_drive(drv) (drv)
|
||||||
|
# define set_drive_config(conf) do {} while(0)
|
||||||
|
# define get_default_driveconfig() 0
|
||||||
|
|
||||||
|
#endif // NEED_DISKMUX
|
||||||
|
|
||||||
|
#endif
|
||||||
175
mk1-src/eeprom.c
Normal file
175
mk1-src/eeprom.c
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
/* sd2snes - SD card based universal cartridge for the SNES
|
||||||
|
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
|
||||||
|
This file was adapted from sd2iec, written by Ingo Korb.
|
||||||
|
Original copyright header follows:
|
||||||
|
*/
|
||||||
|
/* sd2iec - SD/MMC to Commodore serial bus interface/controller
|
||||||
|
Copyright (C) 2007-2009 Ingo Korb <ingo@akana.de>
|
||||||
|
|
||||||
|
Inspiration and low-level SD/MMC access based on code from MMC2IEC
|
||||||
|
by Lars Pontoppidan et al., see sdcard.c|h and config.h.
|
||||||
|
|
||||||
|
FAT filesystem access based on code from ChaN and Jim Brain, see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
|
eeprom.c: Persistent configuration storage
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <avr/eeprom.h>
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include "config.h"
|
||||||
|
#include "diskio.h"
|
||||||
|
#include "fatops.h"
|
||||||
|
#include "flags.h"
|
||||||
|
#include "iec.h"
|
||||||
|
#include "timer.h"
|
||||||
|
#include "eeprom.h"
|
||||||
|
|
||||||
|
#include "uart.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct storedconfig - in-eeprom data structure
|
||||||
|
* @dummy : EEPROM position 0 is unused
|
||||||
|
* @checksum : Checksum over the EEPROM contents
|
||||||
|
* @structsize : size of the eeprom structure
|
||||||
|
* @osccal : stored value of OSCCAL
|
||||||
|
* @globalflags: subset of the globalflags variable
|
||||||
|
* @address : device address set by software
|
||||||
|
* @hardaddress: device address set by jumpers
|
||||||
|
* @fileexts : file extension mapping mode
|
||||||
|
* @drvflags0 : 16 bits of drv mappings, organized as 4 nybbles.
|
||||||
|
* @drvflags1 : 16 bits of drv mappings, organized as 4 nybbles.
|
||||||
|
*
|
||||||
|
* This is the data structure for the contents of the EEPROM.
|
||||||
|
*/
|
||||||
|
static EEMEM struct {
|
||||||
|
uint8_t dummy;
|
||||||
|
uint8_t checksum;
|
||||||
|
uint16_t structsize;
|
||||||
|
uint8_t osccal;
|
||||||
|
uint8_t global_flags;
|
||||||
|
uint8_t address;
|
||||||
|
uint8_t hardaddress;
|
||||||
|
uint8_t fileexts;
|
||||||
|
uint16_t drvconfig0;
|
||||||
|
uint16_t drvconfig1;
|
||||||
|
} storedconfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* read_configuration - reads configuration from EEPROM
|
||||||
|
*
|
||||||
|
* This function reads the stored configuration values from the EEPROM.
|
||||||
|
* If the stored checksum doesn't match the calculated one nothing will
|
||||||
|
* be changed.
|
||||||
|
*/
|
||||||
|
void read_configuration(void) {
|
||||||
|
uint16_t i,size;
|
||||||
|
uint8_t checksum, tmp;
|
||||||
|
|
||||||
|
/* Set default values */
|
||||||
|
globalflags |= JIFFY_ENABLED; /* JiffyDos enabled */
|
||||||
|
globalflags |= POSTMATCH; /* Post-* matching enabled */
|
||||||
|
globalflags |= FAT32_FREEBLOCKS; /* Calculate the number of free blocks on FAT32 */
|
||||||
|
file_extension_mode = 1; /* Store x00 extensions except for PRG */
|
||||||
|
set_drive_config(get_default_driveconfig()); /* Set the default drive configuration */
|
||||||
|
|
||||||
|
/* Use the NEXT button to skip reading the EEPROM configuration */
|
||||||
|
if (!(BUTTON_PIN & BUTTON_NEXT)) {
|
||||||
|
ignore_keys();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = eeprom_read_word(&storedconfig.structsize);
|
||||||
|
|
||||||
|
/* Calculate checksum of EEPROM contents */
|
||||||
|
checksum = 0;
|
||||||
|
for (i=2; i<size; i++)
|
||||||
|
checksum += eeprom_read_byte((uint8_t *)i);
|
||||||
|
|
||||||
|
/* Abort if the checksum doesn't match */
|
||||||
|
if (checksum != eeprom_read_byte(&storedconfig.checksum)) {
|
||||||
|
EEAR = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read data from EEPROM */
|
||||||
|
OSCCAL = eeprom_read_byte(&storedconfig.osccal);
|
||||||
|
|
||||||
|
tmp = eeprom_read_byte(&storedconfig.global_flags);
|
||||||
|
globalflags &= (uint8_t)~(JIFFY_ENABLED | POSTMATCH |
|
||||||
|
EXTENSION_HIDING | FAT32_FREEBLOCKS);
|
||||||
|
globalflags |= tmp;
|
||||||
|
|
||||||
|
if (eeprom_read_byte(&storedconfig.hardaddress) == DEVICE_SELECT)
|
||||||
|
device_address = eeprom_read_byte(&storedconfig.address);
|
||||||
|
|
||||||
|
file_extension_mode = eeprom_read_byte(&storedconfig.fileexts);
|
||||||
|
|
||||||
|
#ifdef NEED_DISKMUX
|
||||||
|
if (size > 9) {
|
||||||
|
uint32_t tmpconfig;
|
||||||
|
tmpconfig = eeprom_read_word(&storedconfig.drvconfig0);
|
||||||
|
tmpconfig |= (uint32_t)eeprom_read_word(&storedconfig.drvconfig1) << 16;
|
||||||
|
set_drive_config(tmpconfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sanity check. If the user has truly turned off all drives, turn the
|
||||||
|
* defaults back on
|
||||||
|
*/
|
||||||
|
if(drive_config == 0xffffffff)
|
||||||
|
set_drive_config(get_default_driveconfig());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Paranoia: Set EEPROM address register to the dummy entry */
|
||||||
|
EEAR = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* write_configuration - stores configuration data to EEPROM
|
||||||
|
*
|
||||||
|
* This function stores the current configuration values to the EEPROM.
|
||||||
|
*/
|
||||||
|
void write_configuration(void) {
|
||||||
|
uint16_t i;
|
||||||
|
uint8_t checksum;
|
||||||
|
|
||||||
|
/* Write configuration to EEPROM */
|
||||||
|
eeprom_write_word(&storedconfig.structsize, sizeof(storedconfig));
|
||||||
|
eeprom_write_byte(&storedconfig.osccal, OSCCAL);
|
||||||
|
eeprom_write_byte(&storedconfig.global_flags,
|
||||||
|
globalflags & (JIFFY_ENABLED | POSTMATCH |
|
||||||
|
EXTENSION_HIDING | FAT32_FREEBLOCKS));
|
||||||
|
eeprom_write_byte(&storedconfig.address, device_address);
|
||||||
|
eeprom_write_byte(&storedconfig.hardaddress, DEVICE_SELECT);
|
||||||
|
eeprom_write_byte(&storedconfig.fileexts, file_extension_mode);
|
||||||
|
#ifdef NEED_DISKMUX
|
||||||
|
eeprom_write_word(&storedconfig.drvconfig0, drive_config);
|
||||||
|
eeprom_write_word(&storedconfig.drvconfig1, drive_config >> 16);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Calculate checksum over EEPROM contents */
|
||||||
|
checksum = 0;
|
||||||
|
for (i=2;i<sizeof(storedconfig);i++)
|
||||||
|
checksum += eeprom_read_byte((uint8_t *) i);
|
||||||
|
|
||||||
|
/* Store checksum to EEPROM */
|
||||||
|
eeprom_write_byte(&storedconfig.checksum, checksum);
|
||||||
|
|
||||||
|
/* Paranoia: Set EEPROM address register to the dummy entry */
|
||||||
|
EEAR = 0;
|
||||||
|
}
|
||||||
|
|
||||||
38
mk1-src/eeprom.h
Normal file
38
mk1-src/eeprom.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
/* sd2snes - SD card based universal cartridge for the SNES
|
||||||
|
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
|
||||||
|
This file was adapted from sd2iec, written by Ingo Korb.
|
||||||
|
Original copyright header follows:
|
||||||
|
*/
|
||||||
|
/* sd2iec - SD/MMC to Commodore serial bus interface/controller
|
||||||
|
Copyright (C) 2007-2009 Ingo Korb <ingo@akana.de>
|
||||||
|
|
||||||
|
Inspiration and low-level SD/MMC access based on code from MMC2IEC
|
||||||
|
by Lars Pontoppidan et al., see sdcard.c|h and config.h.
|
||||||
|
|
||||||
|
FAT filesystem access based on code from ChaN and Jim Brain, see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
|
eeprom.h: Persistent configuration storage
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EEPROM_H
|
||||||
|
#define EEPROM_H
|
||||||
|
|
||||||
|
void read_configuration(void);
|
||||||
|
void write_configuration(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
3066
mk1-src/ff.c
Normal file
3066
mk1-src/ff.c
Normal file
File diff suppressed because it is too large
Load Diff
448
mk1-src/ff.h
Normal file
448
mk1-src/ff.h
Normal file
@@ -0,0 +1,448 @@
|
|||||||
|
/*--------------------------------------------------------------------------/
|
||||||
|
/ FatFs - FAT file system module include file R0.06 (C)ChaN, 2008
|
||||||
|
/---------------------------------------------------------------------------/
|
||||||
|
/ FatFs module is an experimenal project to implement FAT file system to
|
||||||
|
/ cheap microcontrollers. This is a free software and is opened for education,
|
||||||
|
/ research and development under license policy of following trems.
|
||||||
|
/
|
||||||
|
/ Copyright (C) 2008, ChaN, all right reserved.
|
||||||
|
/
|
||||||
|
/ * The FatFs module is a free software and there is no warranty.
|
||||||
|
/ * You can use, modify and/or redistribute it for personal, non-profit or
|
||||||
|
/ * commercial use without any restriction under your responsibility.
|
||||||
|
/ * Redistributions of source code must retain the above copyright notice.
|
||||||
|
/
|
||||||
|
/---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef _FATFS
|
||||||
|
|
||||||
|
#define _MCU_ENDIAN 1
|
||||||
|
/* The _MCU_ENDIAN defines which access method is used to the FAT structure.
|
||||||
|
/ 1: Enable word access.
|
||||||
|
/ 2: Disable word access and use byte-by-byte access instead.
|
||||||
|
/ When the architectural byte order of the MCU is big-endian and/or address
|
||||||
|
/ miss-aligned access results incorrect behavior, the _MCU_ENDIAN must be set
|
||||||
|
/ to 2. If it is not the case, it can be set to 1 for good code efficiency. */
|
||||||
|
|
||||||
|
#define _FS_READONLY 0
|
||||||
|
/* Setting _FS_READONLY to 1 defines read only configuration. This removes
|
||||||
|
/ writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename,
|
||||||
|
/ f_truncate and useless f_getfree. */
|
||||||
|
|
||||||
|
#define _FS_MINIMIZE 0
|
||||||
|
/* The _FS_MINIMIZE option defines minimization level to remove some functions.
|
||||||
|
/ 0: Full function.
|
||||||
|
/ 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename are removed.
|
||||||
|
/ 2: f_opendir and f_readdir are removed in addition to level 1.
|
||||||
|
/ 3: f_lseek is removed in addition to level 2. */
|
||||||
|
|
||||||
|
#define _USE_STRFUNC 0
|
||||||
|
/* To enable string functions, set _USE_STRFUNC to 1 or 2. */
|
||||||
|
|
||||||
|
#define _DRIVES 1
|
||||||
|
/*MAX_DRIVES*/
|
||||||
|
/* Number of physical drives to be used. This affects the size of internal
|
||||||
|
* table. (when using _USE_DRIVE_PREFIX */
|
||||||
|
|
||||||
|
#define _USE_MKFS 0
|
||||||
|
/* When _USE_MKFS is set to 1 and _FS_READONLY is set to 0, f_mkfs function is
|
||||||
|
/ enabled. */
|
||||||
|
|
||||||
|
#define _MULTI_PARTITION 0
|
||||||
|
/* When _MULTI_PARTITION is set to 0, each logical drive is bound to the same
|
||||||
|
/ physical drive number and can mount only 1st primary partition.
|
||||||
|
/
|
||||||
|
/ When it is set to 1, the low _PARTITION_MASK bits of each partition represent
|
||||||
|
/ the partition and the high (8-_PARTITION_MASK) bits represent the physical
|
||||||
|
/ drive */
|
||||||
|
|
||||||
|
#define _PARTITION_MASK 4
|
||||||
|
|
||||||
|
#define _USE_FSINFO 1
|
||||||
|
/* To enable FSInfo support on FAT32 volume, set _USE_FSINFO to 1. */
|
||||||
|
|
||||||
|
#define _USE_SJIS 0
|
||||||
|
/* When _USE_SJIS is set to 1, Shift-JIS code transparency is enabled, otherwise
|
||||||
|
/ only US-ASCII(7bit) code can be accepted as file/directory name. */
|
||||||
|
|
||||||
|
#define _USE_NTFLAG 0
|
||||||
|
/* When _USE_NTFLAG is set to 1, upper/lower case of the file name is preserved.
|
||||||
|
/ Note that the files are always accessed in case insensitive. */
|
||||||
|
|
||||||
|
#define _USE_CHDIR 0
|
||||||
|
|
||||||
|
#define _USE_CURR_DIR 1
|
||||||
|
|
||||||
|
#define _USE_LFN 1
|
||||||
|
|
||||||
|
/* Maximum number of characters to return for a LFN */
|
||||||
|
/* The buffer used for FILINFO.lfn must be at least */
|
||||||
|
/* _MAX_LFN_LENGTH+1 characters long! */
|
||||||
|
/* Note that if _USE_LFN_DBCS is set, this value */
|
||||||
|
/* represents the characters needed, not bytes */
|
||||||
|
#define _MAX_LFN_LENGTH 255
|
||||||
|
|
||||||
|
/* When _USE_LFN_DBCS is set to 1, FILINFO.lfn will contain a DBCS string, not
|
||||||
|
/ a simple ASCII string */
|
||||||
|
#define _USE_LFN_DBCS 0
|
||||||
|
|
||||||
|
/* When set to 1, All FIL objects will use the buffer. This reduces memory
|
||||||
|
/ requirements as open files will only require space for a FIL object, but
|
||||||
|
/ operate slower. When set, ff.c will behave like tff.c, but will allow
|
||||||
|
/ multiple filesystems. */
|
||||||
|
#define _USE_FS_BUF 1
|
||||||
|
|
||||||
|
/* When set to 1, All objects will use a static buffer. This reduces memory
|
||||||
|
/ requirements to the absolute minimum ~512 bytes for the buffer, but will
|
||||||
|
/ operate slower. This option can only be set if _USE_FS_BUF is set. */
|
||||||
|
#define _USE_1_BUF 1
|
||||||
|
|
||||||
|
/* If set to 1, FatFs will manage the FATFS structures after mounting. If
|
||||||
|
/ set to 0, the caller must send the correct drive FATFS structure for each
|
||||||
|
/ call. Normally, this should be set to 1, but if the caller wants to use
|
||||||
|
/ low level l_* functions or skip sending the drive number in the path string,
|
||||||
|
/ this must be turned off. */
|
||||||
|
#define _USE_DRIVE_PREFIX 1
|
||||||
|
|
||||||
|
/* If set to 1, FatFS will delay mounting the drive until first use. Normally,
|
||||||
|
/ this should be turned on. However, it cannot be used with
|
||||||
|
/ _USE_DRIVE_PREFIX = 0 */
|
||||||
|
#define _USE_DEFERRED_MOUNT 0
|
||||||
|
|
||||||
|
/* New features in 0.05a, not required yet */
|
||||||
|
#define _USE_TRUNCATE 0
|
||||||
|
#define _USE_UTIME 0
|
||||||
|
|
||||||
|
#include "integer.h"
|
||||||
|
|
||||||
|
#if _USE_LFN_DBCS != 0
|
||||||
|
#define S_LFN_OFFSET 26
|
||||||
|
#define S_LFN_INCREMENT 2
|
||||||
|
#else
|
||||||
|
#define S_LFN_OFFSET 13
|
||||||
|
#define S_LFN_INCREMENT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Definitions corresponds to multiple sector size (not tested) */
|
||||||
|
#define S_MAX_SIZ 512U /* Do not change */
|
||||||
|
#if S_MAX_SIZ > 512U
|
||||||
|
#define SS(fs) ((fs)->s_size)
|
||||||
|
#else
|
||||||
|
#define SS(fs) 512U
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if _USE_1_BUF == 1 && _USE_FS_BUF == 0
|
||||||
|
#error You can only use 1_BUF with _USE_FS_BUF at present
|
||||||
|
#define _USE_1_BUF 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct _BUF {
|
||||||
|
DWORD sect;
|
||||||
|
BYTE dirty; /* dirty flag (1:must be written back) */
|
||||||
|
//BYTE pad1;
|
||||||
|
#if _USE_1_BUF != 0
|
||||||
|
struct _FATFS *fs;
|
||||||
|
#endif
|
||||||
|
BYTE data[S_MAX_SIZ]; /* Disk access window for Directory/FAT */
|
||||||
|
} BUF;
|
||||||
|
|
||||||
|
/* File system object structure */
|
||||||
|
typedef struct _FATFS {
|
||||||
|
//WORD id; /* File system mount ID */
|
||||||
|
WORD n_rootdir; /* Number of root directory entries */
|
||||||
|
DWORD sects_fat; /* Sectors per fat */
|
||||||
|
DWORD max_clust; /* Maximum cluster# + 1 */
|
||||||
|
DWORD fatbase; /* FAT start sector */
|
||||||
|
DWORD dirbase; /* Root directory start sector (cluster# for FAT32) */
|
||||||
|
DWORD database; /* Data start sector */
|
||||||
|
#if _USE_CHDIR != 0 || _USE_CURR_DIR != 0
|
||||||
|
DWORD curr_dir;
|
||||||
|
#endif
|
||||||
|
#if !_FS_READONLY
|
||||||
|
DWORD last_clust; /* Last allocated cluster */
|
||||||
|
DWORD free_clust; /* Number of free clusters */
|
||||||
|
#if _USE_FSINFO
|
||||||
|
DWORD fsi_sector; /* fsinfo sector */
|
||||||
|
BYTE fsi_flag; /* fsinfo dirty flag (1:must be written back) */
|
||||||
|
//BYTE pad2;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
BYTE fs_type; /* FAT sub type */
|
||||||
|
BYTE csize; /* Number of sectors per cluster */
|
||||||
|
#if S_MAX_SIZ > 512U
|
||||||
|
WORD s_size; /* Sector size */
|
||||||
|
#endif
|
||||||
|
BYTE n_fats; /* Number of FAT copies */
|
||||||
|
BYTE drive; /* Physical drive number */
|
||||||
|
#if _USE_1_BUF == 0
|
||||||
|
BUF buf;
|
||||||
|
#endif
|
||||||
|
} FATFS;
|
||||||
|
|
||||||
|
/* Directory object structure */
|
||||||
|
typedef struct _DIR {
|
||||||
|
//WORD id; /* Owner file system mount ID */
|
||||||
|
WORD index; /* Current index */
|
||||||
|
FATFS* fs; /* Pointer to the owner file system object */
|
||||||
|
DWORD sclust; /* Start cluster */
|
||||||
|
DWORD clust; /* Current cluster */
|
||||||
|
DWORD sect; /* Current sector */
|
||||||
|
} DIR;
|
||||||
|
|
||||||
|
|
||||||
|
/* File object structure */
|
||||||
|
typedef struct _FIL {
|
||||||
|
//WORD id; /* Owner file system mount ID */
|
||||||
|
BYTE flag; /* File status flags */
|
||||||
|
BYTE csect; /* Sector address in the cluster */
|
||||||
|
FATFS* fs; /* Pointer to the owner file system object */
|
||||||
|
DWORD fptr; /* File R/W pointer */
|
||||||
|
DWORD fsize; /* File size */
|
||||||
|
DWORD org_clust; /* File start cluster */
|
||||||
|
DWORD curr_clust; /* Current cluster */
|
||||||
|
DWORD curr_sect; /* Current sector */
|
||||||
|
#if _FS_READONLY == 0
|
||||||
|
DWORD dir_sect; /* Sector containing the directory entry */
|
||||||
|
BYTE* dir_ptr; /* Ponter to the directory entry in the window */
|
||||||
|
#endif
|
||||||
|
#if _USE_LESS_BUF == 0 && _USE_1_BUF == 0
|
||||||
|
BUF buf; /* File R/W buffer */
|
||||||
|
#endif
|
||||||
|
} FIL;
|
||||||
|
|
||||||
|
|
||||||
|
/* File status structure */
|
||||||
|
typedef struct _FILINFO {
|
||||||
|
DWORD fsize; /* Size */
|
||||||
|
WORD fdate; /* Date */
|
||||||
|
WORD ftime; /* Time */
|
||||||
|
BYTE fattrib; /* Attribute */
|
||||||
|
DWORD clust; /* Start cluster */
|
||||||
|
UCHAR fname[8+1+3+1]; /* Name (8.3 format) */
|
||||||
|
#if _USE_LFN != 0
|
||||||
|
UCHAR* lfn;
|
||||||
|
#endif
|
||||||
|
} FILINFO;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Definitions corresponds to multi partition */
|
||||||
|
|
||||||
|
#if _MULTI_PARTITION != 0 /* Multiple partition cfg */
|
||||||
|
|
||||||
|
#define LD2PD(drv) (drv >> (8-_PARTITION_MASK)) /* Get physical drive# */
|
||||||
|
#define LD2PT(drv) (drv & ((1<<_PARTITION_MASK)-1)) /* Get partition# */
|
||||||
|
#define _LOGICAL_DRIVES (_DRIVES * (1<<_PARTITION_MASK))
|
||||||
|
|
||||||
|
#else /* Single partition cfg */
|
||||||
|
|
||||||
|
#define LD2PD(drv) (drv) /* Physical drive# is equal to logical drive# */
|
||||||
|
#define LD2PT(drv) 0 /* Always mounts the 1st partition */
|
||||||
|
#define _LOGICAL_DRIVES _DRIVES
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* File function return code (FRESULT) */
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FR_OK = 0, /* 0 */
|
||||||
|
FR_NOT_READY, /* 1 */
|
||||||
|
FR_NO_FILE, /* 2 */
|
||||||
|
FR_NO_PATH, /* 3 */
|
||||||
|
FR_INVALID_NAME, /* 4 */
|
||||||
|
FR_INVALID_DRIVE, /* 5 */
|
||||||
|
FR_DENIED, /* 6 */
|
||||||
|
FR_EXIST, /* 7 */
|
||||||
|
FR_RW_ERROR, /* 8 */
|
||||||
|
FR_WRITE_PROTECTED, /* 9 */
|
||||||
|
FR_NOT_ENABLED, /* 10 */
|
||||||
|
FR_NO_FILESYSTEM, /* 11 */
|
||||||
|
FR_INVALID_OBJECT, /* 12 */
|
||||||
|
FR_MKFS_ABORTED, /* 13 */
|
||||||
|
FR_IS_DIRECTORY, /* 14 */
|
||||||
|
FR_IS_READONLY, /* 15 */
|
||||||
|
FR_DIR_NOT_EMPTY, /* 16 */
|
||||||
|
FR_NOT_DIRECTORY /* 17 */
|
||||||
|
} FRESULT;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------*/
|
||||||
|
/* FatFs module application interface */
|
||||||
|
|
||||||
|
#if _USE_DRIVE_PREFIX == 0
|
||||||
|
FRESULT f_mount (BYTE, FATFS*); /* Mount/Unmount a logical drive */
|
||||||
|
FRESULT f_open (FATFS*, FIL*, const UCHAR*, BYTE); /* Open or create a file */
|
||||||
|
FRESULT f_read (FIL*, void*, UINT, UINT*); /* Read data from a file */
|
||||||
|
FRESULT f_write (FIL*, const void*, UINT, UINT*); /* Write data to a file */
|
||||||
|
FRESULT f_lseek (FIL*, DWORD); /* Move file pointer of a file object */
|
||||||
|
FRESULT f_close (FIL*); /* Close an open file object */
|
||||||
|
FRESULT f_opendir (FATFS*, DIR*, const UCHAR*); /* Open an existing directory */
|
||||||
|
FRESULT f_readdir (DIR*, FILINFO*); /* Read a directory item */
|
||||||
|
FRESULT f_stat (FATFS*, const UCHAR*, FILINFO*); /* Get file status */
|
||||||
|
FRESULT f_getfree (FATFS*, const UCHAR*, DWORD*); /* Get number of free clusters on the drive */
|
||||||
|
FRESULT f_sync (FIL*); /* Flush cached data of a writing file */
|
||||||
|
FRESULT f_unlink (FATFS*, const UCHAR*); /* Delete an existing file or directory */
|
||||||
|
FRESULT f_mkdir (FATFS*, const UCHAR*); /* Create a new directory */
|
||||||
|
FRESULT f_chmod (FATFS*, const UCHAR*, BYTE, BYTE); /* Change file/dir attriburte */
|
||||||
|
FRESULT f_rename (FATFS*, const UCHAR*, const UCHAR*); /* Rename/Move a file or directory */
|
||||||
|
FRESULT f_mkfs (BYTE, BYTE, WORD); /* Create a file system on the drive */
|
||||||
|
FRESULT f_chdir (FATFS*, const UCHAR*); /* Change current directory */
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
FRESULT f_mount (BYTE, FATFS*); /* Mount/Unmount a logical drive */
|
||||||
|
FRESULT f_open (FIL*, const UCHAR*, BYTE); /* Open or create a file */
|
||||||
|
FRESULT f_read (FIL*, void*, UINT, UINT*); /* Read data from a file */
|
||||||
|
FRESULT f_write (FIL*, const void*, UINT, UINT*); /* Write data to a file */
|
||||||
|
FRESULT f_lseek (FIL*, DWORD); /* Move file pointer of a file object */
|
||||||
|
FRESULT f_close (FIL*); /* Close an open file object */
|
||||||
|
FRESULT f_opendir (DIR*, const UCHAR*); /* Open an existing directory */
|
||||||
|
FRESULT f_readdir (DIR*, FILINFO*); /* Read a directory item */
|
||||||
|
FRESULT f_stat (const UCHAR*, FILINFO*); /* Get file status */
|
||||||
|
FRESULT f_getfree (const UCHAR*, DWORD*, FATFS**); /* Get number of free clusters on the drive */
|
||||||
|
FRESULT f_sync (FIL*); /* Flush cached data of a writing file */
|
||||||
|
FRESULT f_unlink (const UCHAR*); /* Delete an existing file or directory */
|
||||||
|
FRESULT f_mkdir (const UCHAR*); /* Create a new directory */
|
||||||
|
FRESULT f_chmod (const UCHAR*, BYTE, BYTE); /* Change file/dir attriburte */
|
||||||
|
FRESULT f_rename (const UCHAR*, const UCHAR*); /* Rename/Move a file or directory */
|
||||||
|
FRESULT f_mkfs (BYTE, BYTE, WORD); /* Create a file system on the drive */
|
||||||
|
FRESULT f_chdir (const UCHAR*); /* Change current directory */
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Low Level functions */
|
||||||
|
FRESULT l_opendir(FATFS* fs, DWORD cluster, DIR *dirobj); /* Open an existing directory by its start cluster */
|
||||||
|
FRESULT l_opencluster(FATFS *fs, FIL *fp, DWORD clust); /* Open a cluster by number as a read-only file */
|
||||||
|
FRESULT l_openfilebycluster(FATFS *fs, FIL *fp, const UCHAR *path, DWORD clust, DWORD fsize); /* Open a file by its start cluster using supplied file size */
|
||||||
|
FRESULT l_getfree (FATFS*, const UCHAR*, DWORD*, DWORD); /* Get number of free clusters on the drive, limited */
|
||||||
|
|
||||||
|
#if _USE_STRFUNC
|
||||||
|
#define feof(fp) ((fp)->fptr == (fp)->fsize)
|
||||||
|
#define EOF -1
|
||||||
|
int fputc (int, FIL*); /* Put a character to the file */
|
||||||
|
int fputs (const char*, FIL*); /* Put a string to the file */
|
||||||
|
int fprintf (FIL*, const char*, ...); /* Put a formatted string to the file */
|
||||||
|
char* fgets (char*, int, FIL*); /* Get a string from the file */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* User defined function to give a current time to fatfs module */
|
||||||
|
|
||||||
|
#if CONFIG_RTC_VARIANT > 0
|
||||||
|
DWORD get_fattime (void); /* 31-25: Year(0-127 org.1980), 24-21: Month(1-12), 20-16: Day(1-31) */
|
||||||
|
/* 15-11: Hour(0-23), 10-5: Minute(0-59), 4-0: Second(0-29 *2) */
|
||||||
|
#else
|
||||||
|
/* Fixed time: 1982-08-31 0:00:00, same month as the introduction of the C64 */
|
||||||
|
# define get_fattime() 0x51f0000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* File access control and file status flags (FIL.flag) */
|
||||||
|
|
||||||
|
#define FA_READ 0x01
|
||||||
|
#define FA_OPEN_EXISTING 0x00
|
||||||
|
#if _FS_READONLY == 0
|
||||||
|
#define FA_WRITE 0x02
|
||||||
|
#define FA_CREATE_NEW 0x04
|
||||||
|
#define FA_CREATE_ALWAYS 0x08
|
||||||
|
#define FA_OPEN_ALWAYS 0x10
|
||||||
|
#define FA__WRITTEN 0x20
|
||||||
|
#define FA__DIRTY 0x40
|
||||||
|
#endif
|
||||||
|
#define FA__ERROR 0x80
|
||||||
|
|
||||||
|
|
||||||
|
/* FAT sub type (FATFS.fs_type) */
|
||||||
|
|
||||||
|
#define FS_FAT12 1
|
||||||
|
#define FS_FAT16 2
|
||||||
|
#define FS_FAT32 3
|
||||||
|
|
||||||
|
|
||||||
|
/* File attribute bits for directory entry */
|
||||||
|
|
||||||
|
#define AM_RDO 0x01 /* Read only */
|
||||||
|
#define AM_HID 0x02 /* Hidden */
|
||||||
|
#define AM_SYS 0x04 /* System */
|
||||||
|
#define AM_VOL 0x08 /* Volume label */
|
||||||
|
#define AM_LFN 0x0F /* LFN entry */
|
||||||
|
#define AM_DIR 0x10 /* Directory */
|
||||||
|
#define AM_ARC 0x20 /* Archive */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Offset of FAT structure members */
|
||||||
|
|
||||||
|
#define BS_jmpBoot 0
|
||||||
|
#define BS_OEMName 3
|
||||||
|
#define BPB_BytsPerSec 11
|
||||||
|
#define BPB_SecPerClus 13
|
||||||
|
#define BPB_RsvdSecCnt 14
|
||||||
|
#define BPB_NumFATs 16
|
||||||
|
#define BPB_RootEntCnt 17
|
||||||
|
#define BPB_TotSec16 19
|
||||||
|
#define BPB_Media 21
|
||||||
|
#define BPB_FATSz16 22
|
||||||
|
#define BPB_SecPerTrk 24
|
||||||
|
#define BPB_NumHeads 26
|
||||||
|
#define BPB_HiddSec 28
|
||||||
|
#define BPB_TotSec32 32
|
||||||
|
#define BS_55AA 510
|
||||||
|
|
||||||
|
#define BS_DrvNum 36
|
||||||
|
#define BS_BootSig 38
|
||||||
|
#define BS_VolID 39
|
||||||
|
#define BS_VolLab 43
|
||||||
|
#define BS_FilSysType 54
|
||||||
|
|
||||||
|
#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 BS_DrvNum32 64
|
||||||
|
#define BS_BootSig32 66
|
||||||
|
#define BS_VolID32 67
|
||||||
|
#define BS_VolLab32 71
|
||||||
|
#define BS_FilSysType32 82
|
||||||
|
|
||||||
|
#define FSI_LeadSig 0
|
||||||
|
#define FSI_StrucSig 484
|
||||||
|
#define FSI_Free_Count 488
|
||||||
|
#define FSI_Nxt_Free 492
|
||||||
|
|
||||||
|
#define MBR_Table 446
|
||||||
|
|
||||||
|
#define DIR_Name 0
|
||||||
|
#define DIR_Attr 11
|
||||||
|
#define DIR_NTres 12
|
||||||
|
#define DIR_Chksum 13
|
||||||
|
#define DIR_CrtTime 14
|
||||||
|
#define DIR_CrtDate 16
|
||||||
|
#define DIR_FstClusHI 20
|
||||||
|
#define DIR_WrtTime 22
|
||||||
|
#define DIR_WrtDate 24
|
||||||
|
#define DIR_FstClusLO 26
|
||||||
|
#define DIR_FileSize 28
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Multi-byte word access macros */
|
||||||
|
|
||||||
|
#if _MCU_ENDIAN == 1 /* Use word access */
|
||||||
|
#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr))
|
||||||
|
#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr))
|
||||||
|
#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val)
|
||||||
|
#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val)
|
||||||
|
#elif _MCU_ENDIAN == 2 /* Use byte-by-byte access */
|
||||||
|
#define LD_WORD(ptr) (WORD)(((WORD)*(volatile BYTE*)((ptr)+1)<<8)|(WORD)*(volatile BYTE*)(ptr))
|
||||||
|
#define LD_DWORD(ptr) (DWORD)(((DWORD)*(volatile BYTE*)((ptr)+3)<<24)|((DWORD)*(volatile BYTE*)((ptr)+2)<<16)|((WORD)*(volatile BYTE*)((ptr)+1)<<8)|*(volatile BYTE*)(ptr))
|
||||||
|
#define ST_WORD(ptr,val) *(volatile BYTE*)(ptr)=(BYTE)(val); *(volatile BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8)
|
||||||
|
#define ST_DWORD(ptr,val) *(volatile BYTE*)(ptr)=(BYTE)(val); *(volatile BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8); *(volatile BYTE*)((ptr)+2)=(BYTE)((DWORD)(val)>>16); *(volatile BYTE*)((ptr)+3)=(BYTE)((DWORD)(val)>>24)
|
||||||
|
#else
|
||||||
|
#error Do not forget to set _MCU_ENDIAN properly!
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define _FATFS
|
||||||
|
#endif /* _FATFS */
|
||||||
80
mk1-src/fileops.c
Normal file
80
mk1-src/fileops.c
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
/* sd2snes - SD card based universal cartridge for the SNES
|
||||||
|
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
|
||||||
|
AVR firmware portion
|
||||||
|
|
||||||
|
Inspired by and based on code from sd2iec, written by Ingo Korb et al.
|
||||||
|
See sdcard.c|h, config.h.
|
||||||
|
|
||||||
|
FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
|
||||||
|
see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
fileops.c: simple file access functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <util/delay.h>
|
||||||
|
#include "config.h"
|
||||||
|
#include "uart.h"
|
||||||
|
#include "ff.h"
|
||||||
|
#include "fileops.h"
|
||||||
|
|
||||||
|
WCHAR ff_convert(WCHAR w, UINT dir) {
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
void file_init() {
|
||||||
|
f_mount(0, &fatfs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void file_open_by_filinfo(FILINFO* fno) {
|
||||||
|
file_res = l_openfilebycluster(&fatfs, &file_handle, (UCHAR*)"", fno->clust, fno->fsize);
|
||||||
|
}
|
||||||
|
void file_open(uint8_t* filename, BYTE flags) {
|
||||||
|
file_res = f_open(&file_handle, (unsigned char*)filename, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
void file_close() {
|
||||||
|
file_res = f_close(&file_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT file_read() {
|
||||||
|
UINT bytes_read;
|
||||||
|
file_res = f_read(&file_handle, file_buf, sizeof(file_buf), &bytes_read);
|
||||||
|
return bytes_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT file_write() {
|
||||||
|
UINT bytes_written;
|
||||||
|
file_res = f_write(&file_handle, file_buf, sizeof(file_buf), &bytes_written);
|
||||||
|
return bytes_written;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT file_readblock(void* buf, uint32_t addr, uint16_t size) {
|
||||||
|
UINT bytes_read;
|
||||||
|
file_res = f_lseek(&file_handle, addr);
|
||||||
|
if(file_handle.fptr != addr) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
file_res = f_read(&file_handle, buf, size, &bytes_read);
|
||||||
|
return bytes_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT file_writeblock(void* buf, uint32_t addr, uint16_t size) {
|
||||||
|
UINT bytes_written;
|
||||||
|
file_res = f_lseek(&file_handle, addr);
|
||||||
|
if(file_res) return 0;
|
||||||
|
file_res = f_write(&file_handle, buf, size, &bytes_written);
|
||||||
|
return bytes_written;
|
||||||
|
}
|
||||||
45
mk1-src/fileops.h
Normal file
45
mk1-src/fileops.h
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/* sd2snes - SD card based universal cartridge for the SNES
|
||||||
|
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
|
||||||
|
AVR firmware portion
|
||||||
|
|
||||||
|
Inspired by and based on code from sd2iec, written by Ingo Korb et al.
|
||||||
|
See sdcard.c|h, config.h.
|
||||||
|
|
||||||
|
FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
|
||||||
|
see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
fileops.h: simple file access functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FILEOPS_H
|
||||||
|
#define FILEOPS_H
|
||||||
|
#include "ff.h"
|
||||||
|
|
||||||
|
BYTE file_buf[512];
|
||||||
|
FATFS fatfs;
|
||||||
|
FIL file_handle;
|
||||||
|
FRESULT file_res;
|
||||||
|
uint8_t file_lfn[256];
|
||||||
|
|
||||||
|
void file_init(void);
|
||||||
|
void file_open(uint8_t* filename, BYTE flags);
|
||||||
|
void file_open_by_filinfo(FILINFO* fno);
|
||||||
|
void file_close(void);
|
||||||
|
UINT file_read(void);
|
||||||
|
UINT file_write(void);
|
||||||
|
UINT file_readblock(void* buf, uint32_t addr, uint16_t size);
|
||||||
|
UINT file_writeblock(void* buf, uint32_t addr, uint16_t size);
|
||||||
|
#endif
|
||||||
273
mk1-src/filetypes.c
Normal file
273
mk1-src/filetypes.c
Normal file
@@ -0,0 +1,273 @@
|
|||||||
|
/* sd2snes - SD card based universal cartridge for the SNES
|
||||||
|
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
|
||||||
|
AVR firmware portion
|
||||||
|
|
||||||
|
Inspired by and based on code from sd2iec, written by Ingo Korb et al.
|
||||||
|
See sdcard.c|h, config.h.
|
||||||
|
|
||||||
|
FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
|
||||||
|
see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
filetypes.c: directory scanning and file type detection
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
#include <util/delay.h>
|
||||||
|
#include "config.h"
|
||||||
|
#include "uart.h"
|
||||||
|
#include "filetypes.h"
|
||||||
|
#include "ff.h"
|
||||||
|
#include "smc.h"
|
||||||
|
#include "fileops.h"
|
||||||
|
#include "crc16.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "led.h"
|
||||||
|
|
||||||
|
uint16_t scan_flat(const char* path) {
|
||||||
|
DIR dir;
|
||||||
|
FRESULT res;
|
||||||
|
FILINFO fno;
|
||||||
|
fno.lfn = NULL;
|
||||||
|
res = f_opendir(&dir, (unsigned char*)path);
|
||||||
|
uint16_t numentries = 0;
|
||||||
|
if (res == FR_OK) {
|
||||||
|
for (;;) {
|
||||||
|
res = f_readdir(&dir, &fno);
|
||||||
|
if(res != FR_OK || fno.fname[0] == 0)break;
|
||||||
|
numentries++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return numentries;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t scan_dir(char* path, char mkdb, uint32_t this_dir_tgt) {
|
||||||
|
DIR dir;
|
||||||
|
FILINFO fno;
|
||||||
|
FRESULT res;
|
||||||
|
uint8_t len;
|
||||||
|
unsigned char* fn;
|
||||||
|
static unsigned char depth = 0;
|
||||||
|
static uint16_t crc;
|
||||||
|
static uint32_t db_tgt;
|
||||||
|
static uint32_t next_subdir_tgt;
|
||||||
|
static uint32_t parent_tgt;
|
||||||
|
static uint32_t dir_end = 0;
|
||||||
|
static uint8_t was_empty = 0;
|
||||||
|
uint32_t dir_tgt;
|
||||||
|
uint16_t numentries;
|
||||||
|
uint32_t dirsize;
|
||||||
|
uint8_t pass = 0;
|
||||||
|
|
||||||
|
dir_tgt = this_dir_tgt;
|
||||||
|
if(depth==0) {
|
||||||
|
crc = 0;
|
||||||
|
db_tgt = SRAM_DB_ADDR+0x10;
|
||||||
|
dir_tgt = SRAM_DIR_ADDR;
|
||||||
|
next_subdir_tgt = SRAM_DIR_ADDR;
|
||||||
|
this_dir_tgt = SRAM_DIR_ADDR;
|
||||||
|
parent_tgt = 0;
|
||||||
|
dprintf("root dir @%lx\n", dir_tgt);
|
||||||
|
}
|
||||||
|
|
||||||
|
fno.lfn = file_lfn;
|
||||||
|
numentries=0;
|
||||||
|
for(pass = 0; pass < 2; pass++) {
|
||||||
|
if(pass) {
|
||||||
|
dirsize = 4*(numentries);
|
||||||
|
// dir_tgt_next = dir_tgt + dirsize + 4; // number of entries + end marker
|
||||||
|
next_subdir_tgt += dirsize + 4;
|
||||||
|
if(parent_tgt) next_subdir_tgt += 4;
|
||||||
|
if(next_subdir_tgt > dir_end) {
|
||||||
|
dir_end = next_subdir_tgt;
|
||||||
|
}
|
||||||
|
dprintf("path=%s depth=%d ptr=%lx entries=%d parent=%lx next subdir @%lx\n", path, depth, db_tgt, numentries, parent_tgt, next_subdir_tgt /*dir_tgt_next*/);
|
||||||
|
// _delay_ms(50);
|
||||||
|
if(mkdb) {
|
||||||
|
dprintf("d=%d Saving %lX to Address %lX [end]\n", depth, 0L, next_subdir_tgt - 4);
|
||||||
|
// _delay_ms(50);
|
||||||
|
sram_writelong(0L, next_subdir_tgt - 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res = f_opendir(&dir, (unsigned char*)path);
|
||||||
|
if (res == FR_OK) {
|
||||||
|
if(pass && parent_tgt && mkdb) {
|
||||||
|
// write backlink to parent dir
|
||||||
|
// switch to next bank if record does not fit in current bank
|
||||||
|
if((db_tgt&0xffff) > ((0x10000-(sizeof(next_subdir_tgt)+sizeof(len)+4))&0xffff)) {
|
||||||
|
dprintf("switch! old=%lx ", db_tgt);
|
||||||
|
db_tgt &= 0xffff0000;
|
||||||
|
db_tgt += 0x00010000;
|
||||||
|
dprintf("new=%lx\n", db_tgt);
|
||||||
|
}
|
||||||
|
sram_writelong((parent_tgt-SRAM_MENU_ADDR), db_tgt);
|
||||||
|
sram_writebyte(0, db_tgt+sizeof(next_subdir_tgt));
|
||||||
|
sram_writeblock("../\0", db_tgt+sizeof(next_subdir_tgt)+sizeof(len), 4);
|
||||||
|
sram_writelong((db_tgt-SRAM_MENU_ADDR)|((uint32_t)0x80<<24), dir_tgt);
|
||||||
|
db_tgt += sizeof(next_subdir_tgt)+sizeof(len)+4;
|
||||||
|
dir_tgt += 4;
|
||||||
|
}
|
||||||
|
len = strlen((char*)path);
|
||||||
|
for (;;) {
|
||||||
|
toggle_busy_led();
|
||||||
|
res = f_readdir(&dir, &fno);
|
||||||
|
if (res != FR_OK || fno.fname[0] == 0) {
|
||||||
|
if(pass) {
|
||||||
|
if(!numentries) was_empty=1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fn = *fno.lfn ? fno.lfn : fno.fname;
|
||||||
|
// dprintf("%s\n", fn);
|
||||||
|
// _delay_ms(100);
|
||||||
|
if (*fn == '.') continue;
|
||||||
|
if (fno.fattrib & AM_DIR) {
|
||||||
|
numentries++;
|
||||||
|
if(pass) {
|
||||||
|
path[len]='/';
|
||||||
|
strncpy(path+len+1, (char*)fn, sizeof(fs_path)-len);
|
||||||
|
depth++;
|
||||||
|
if(mkdb) {
|
||||||
|
uint16_t pathlen = strlen(path);
|
||||||
|
// write element pointer to current dir structure
|
||||||
|
dprintf("d=%d Saving %lX to Address %lX [dir]\n", depth, db_tgt, dir_tgt);
|
||||||
|
// _delay_ms(50);
|
||||||
|
sram_writelong((db_tgt-SRAM_MENU_ADDR)|((uint32_t)0x80<<24), dir_tgt);
|
||||||
|
// sram_writeblock((uint8_t*)&db_tgt, dir_tgt_save, sizeof(dir_tgt_save));
|
||||||
|
|
||||||
|
// save element:
|
||||||
|
// - path name
|
||||||
|
// - pointer to sub dir structure
|
||||||
|
if((db_tgt&0xffff) > ((0x10000-(sizeof(next_subdir_tgt) + sizeof(len) + pathlen + 2))&0xffff)) {
|
||||||
|
dprintf("switch! old=%lx ", db_tgt);
|
||||||
|
db_tgt &= 0xffff0000;
|
||||||
|
db_tgt += 0x00010000;
|
||||||
|
dprintf("new=%lx\n", db_tgt);
|
||||||
|
}
|
||||||
|
dprintf(" Saving dir descriptor to %lX, tgt=%lX, path=%s\n", db_tgt, next_subdir_tgt, path);
|
||||||
|
// _delay_ms(100);
|
||||||
|
sram_writelong((next_subdir_tgt-SRAM_MENU_ADDR), db_tgt);
|
||||||
|
sram_writebyte(len+1, db_tgt+sizeof(next_subdir_tgt));
|
||||||
|
sram_writeblock(path, db_tgt+sizeof(next_subdir_tgt)+sizeof(len), pathlen);
|
||||||
|
sram_writeblock("/\0", db_tgt + sizeof(next_subdir_tgt) + sizeof(len) + pathlen, 2);
|
||||||
|
// sram_writeblock((uint8_t*)&dir_tgt, db_tgt+256, sizeof(dir_tgt));
|
||||||
|
db_tgt += sizeof(next_subdir_tgt) + sizeof(len) + pathlen + 2;
|
||||||
|
}
|
||||||
|
parent_tgt = this_dir_tgt;
|
||||||
|
scan_dir(path, mkdb, next_subdir_tgt);
|
||||||
|
dir_tgt += 4;
|
||||||
|
// if(was_empty)dir_tgt_next += 4;
|
||||||
|
was_empty = 0;
|
||||||
|
depth--;
|
||||||
|
path[len]=0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SNES_FTYPE type = determine_filetype((char*)fn);
|
||||||
|
if(type != TYPE_UNKNOWN) {
|
||||||
|
numentries++;
|
||||||
|
if(pass) {
|
||||||
|
if(mkdb) {
|
||||||
|
snes_romprops_t romprops;
|
||||||
|
path[len]='/';
|
||||||
|
strncpy(path+len+1, (char*)fn, sizeof(fs_path)-len);
|
||||||
|
uint16_t pathlen = strlen(path);
|
||||||
|
switch(type) {
|
||||||
|
case TYPE_SMC:
|
||||||
|
// XXX file_open_by_filinfo(&fno);
|
||||||
|
// XXX if(file_res){
|
||||||
|
// XXX dprintf("ZOMG NOOOO %d\n", file_res);
|
||||||
|
// XXX _delay_ms(30);
|
||||||
|
// XXX }
|
||||||
|
// XXX smc_id(&romprops);
|
||||||
|
// XXX file_close();
|
||||||
|
// _delay_ms(30);
|
||||||
|
// write element pointer to current dir structure
|
||||||
|
// dprintf("d=%d Saving %lX to Address %lX [file]\n", depth, db_tgt, dir_tgt);
|
||||||
|
// _delay_ms(50);
|
||||||
|
if((db_tgt&0xffff) > ((0x10000-(sizeof(romprops) + sizeof(len) + pathlen + 1))&0xffff)) {
|
||||||
|
dprintf("switch! old=%lx ", db_tgt);
|
||||||
|
db_tgt &= 0xffff0000;
|
||||||
|
db_tgt += 0x00010000;
|
||||||
|
dprintf("new=%lx\n", db_tgt);
|
||||||
|
}
|
||||||
|
sram_writelong((db_tgt-SRAM_MENU_ADDR), dir_tgt);
|
||||||
|
// sram_writeblock((uint8_t*)&db_tgt, dir_tgt, sizeof(db_tgt));
|
||||||
|
dir_tgt += 4;
|
||||||
|
// save element:
|
||||||
|
// - SNES header information
|
||||||
|
// - file name
|
||||||
|
sram_writeblock((uint8_t*)&romprops, db_tgt, sizeof(romprops));
|
||||||
|
sram_writebyte(len+1, db_tgt + sizeof(romprops));
|
||||||
|
sram_writeblock(path, db_tgt + sizeof(romprops) + sizeof(len), pathlen + 1);
|
||||||
|
db_tgt += sizeof(romprops) + sizeof(len) + pathlen + 1;
|
||||||
|
break;
|
||||||
|
case TYPE_UNKNOWN:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
path[len]=0;
|
||||||
|
// dprintf("%s ", path);
|
||||||
|
// _delay_ms(30);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unsigned char* sfn = fno.fname;
|
||||||
|
while(*sfn != 0) {
|
||||||
|
crc += crc16_update(crc, sfn++, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// dprintf("%s/%s\n", path, fn);
|
||||||
|
// _delay_ms(50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else uart_putc(0x30+res);
|
||||||
|
}
|
||||||
|
// dprintf("%x\n", crc);
|
||||||
|
// _delay_ms(50);
|
||||||
|
sram_writelong(db_tgt, SRAM_DB_ADDR+4);
|
||||||
|
sram_writelong(dir_end, SRAM_DB_ADDR+8);
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SNES_FTYPE determine_filetype(char* filename) {
|
||||||
|
char* ext = strrchr(filename, '.');
|
||||||
|
if(ext == NULL)
|
||||||
|
return TYPE_UNKNOWN;
|
||||||
|
if(!strcasecmp_P(ext+1, PSTR("SMC"))) {
|
||||||
|
return TYPE_SMC;
|
||||||
|
}/* later
|
||||||
|
if(!strcasecmp_P(ext+1, PSTR("SRM"))) {
|
||||||
|
return TYPE_SRM;
|
||||||
|
}
|
||||||
|
if(!strcasecmp_P(ext+1, PSTR("SPC"))) {
|
||||||
|
return TYPE_SPC;
|
||||||
|
}*/
|
||||||
|
return TYPE_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
FRESULT get_db_id(uint16_t* id) {
|
||||||
|
file_open((uint8_t*)"/sd2snes/sd2snes.db", FA_READ);
|
||||||
|
if(file_res == FR_OK) {
|
||||||
|
file_readblock(id, 0, 2);
|
||||||
|
/* XXX */// *id=0xdead;
|
||||||
|
file_close();
|
||||||
|
} else {
|
||||||
|
*id=0xdead;
|
||||||
|
}
|
||||||
|
return file_res;
|
||||||
|
}
|
||||||
45
mk1-src/filetypes.h
Normal file
45
mk1-src/filetypes.h
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/* sd2snes - SD card based universal cartridge for the SNES
|
||||||
|
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
|
||||||
|
AVR firmware portion
|
||||||
|
|
||||||
|
Inspired by and based on code from sd2iec, written by Ingo Korb et al.
|
||||||
|
See sdcard.c|h, config.h.
|
||||||
|
|
||||||
|
FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
|
||||||
|
see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
filetypes.h: directory scanning and file type detection
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FILETYPES_H
|
||||||
|
#define FILETYPES_H
|
||||||
|
|
||||||
|
#include "ff.h"
|
||||||
|
typedef enum {
|
||||||
|
TYPE_UNKNOWN = 0, /* 0 */
|
||||||
|
TYPE_SMC, /* 1 */
|
||||||
|
TYPE_SRM, /* 2 */
|
||||||
|
TYPE_SPC /* 3 */
|
||||||
|
} SNES_FTYPE;
|
||||||
|
|
||||||
|
|
||||||
|
char fs_path[256];
|
||||||
|
SNES_FTYPE determine_filetype(char* filename);
|
||||||
|
//uint32_t scan_fs();
|
||||||
|
uint16_t scan_dir(char* path, char mkdb, uint32_t this_subdir_tgt);
|
||||||
|
FRESULT get_db_id(uint16_t*);
|
||||||
|
|
||||||
|
#endif
|
||||||
181
mk1-src/fpga.c
Normal file
181
mk1-src/fpga.c
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
/* sd2snes - SD card based universal cartridge for the SNES
|
||||||
|
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
|
||||||
|
AVR firmware portion
|
||||||
|
|
||||||
|
Inspired by and based on code from sd2iec, written by Ingo Korb et al.
|
||||||
|
See sdcard.c|h, config.h.
|
||||||
|
|
||||||
|
FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
|
||||||
|
see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
fpga.c: FPGA (re)configuration
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
FPGA pin mapping
|
||||||
|
================
|
||||||
|
PROG_B PD3 OUT
|
||||||
|
CCLK PD4 OUT
|
||||||
|
INIT_B PD7 IN
|
||||||
|
DIN PC7 OUT
|
||||||
|
DONE PA3 IN
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
#include <util/delay.h>
|
||||||
|
#include "fpga.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "uart.h"
|
||||||
|
#include "sdcard.h"
|
||||||
|
#include "diskio.h"
|
||||||
|
#include "integer.h"
|
||||||
|
#include "ff.h"
|
||||||
|
#include "fileops.h"
|
||||||
|
#include "fpga_spi.h"
|
||||||
|
#include "spi.h"
|
||||||
|
#include "avrcompat.h"
|
||||||
|
#include "led.h"
|
||||||
|
|
||||||
|
/*DWORD get_fattime(void) {
|
||||||
|
return 0L;
|
||||||
|
}*/
|
||||||
|
void set_prog_b(uint8_t val) {
|
||||||
|
if(val) {
|
||||||
|
PORTD |= _BV(PD3);
|
||||||
|
} else {
|
||||||
|
PORTD &= ~_BV(PD3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_cclk(uint8_t val) {
|
||||||
|
if(val) {
|
||||||
|
PORTD |= _BV(PD4);
|
||||||
|
} else {
|
||||||
|
PORTD &= ~_BV(PD4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fpga_init() {
|
||||||
|
DDRD &= ~_BV(PD7); // PD7 is input
|
||||||
|
|
||||||
|
DDRC = _BV(PC7); // for FPGA config, PC7 is output
|
||||||
|
|
||||||
|
DDRD |= _BV(PD3) | _BV(PD4); // PD3, PD4 are outputs
|
||||||
|
|
||||||
|
DDRA = ~_BV(PA3); // PA3 is input <- DONE
|
||||||
|
|
||||||
|
DDRB |= _BV(PB2); // DMA_CTRL preinit
|
||||||
|
PORTB |= _BV(PB2);
|
||||||
|
SPI_OFFLOAD=0;
|
||||||
|
set_cclk(0); // initial clk=0
|
||||||
|
}
|
||||||
|
|
||||||
|
int fpga_get_done(void) {
|
||||||
|
return PINA & _BV(PA3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fpga_postinit() {
|
||||||
|
DDRA |= _BV(PA0) | _BV(PA1) | _BV(PA2) | _BV(PA4) | _BV(PA5) | _BV(PA6); // MAPPER+NEXTADDR output
|
||||||
|
DDRB |= _BV(PB1) | _BV(PB0); // turn PB2 into output, enable AVR_BANK
|
||||||
|
DDRD |= _BV(PD7); // turn PD7 into output
|
||||||
|
}
|
||||||
|
|
||||||
|
void fpga_pgm(uint8_t* filename) {
|
||||||
|
int MAXRETRIES = 10;
|
||||||
|
int retries = MAXRETRIES;
|
||||||
|
int j=0;
|
||||||
|
do {
|
||||||
|
set_prog_b(0);
|
||||||
|
uart_putc('P');
|
||||||
|
set_prog_b(1);
|
||||||
|
loop_until_bit_is_set(PIND, PD7);
|
||||||
|
uart_putc('p');
|
||||||
|
|
||||||
|
UINT bytes_read;
|
||||||
|
|
||||||
|
// open configware file
|
||||||
|
file_open(filename, FA_READ);
|
||||||
|
if(file_res) {
|
||||||
|
uart_putc('?');
|
||||||
|
uart_putc(0x30+file_res);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if(!(j++ % 8)) {
|
||||||
|
toggle_pwr_led();
|
||||||
|
}
|
||||||
|
bytes_read = file_read();
|
||||||
|
if (file_res || bytes_read == 0) break; // error or eof
|
||||||
|
for(int i=0; i<bytes_read; i++) {
|
||||||
|
FPGA_SEND_BYTE_SERIAL(file_buf[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_close();
|
||||||
|
_delay_ms(100);
|
||||||
|
} while (!fpga_get_done() && retries--);
|
||||||
|
if(!fpga_get_done()) {
|
||||||
|
dprintf("FPGA failed to configure after %d tries.\n", MAXRETRIES);
|
||||||
|
_delay_ms(50);
|
||||||
|
led_panic();
|
||||||
|
}
|
||||||
|
fpga_postinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_avr_ena(uint8_t val) {
|
||||||
|
if(val) { // shared mode
|
||||||
|
PORTD |= _BV(PD7);
|
||||||
|
// Disable SPI double speed mode -> clock = f/4
|
||||||
|
SPSR = 0;
|
||||||
|
dprintf("SPI slow\n");
|
||||||
|
} else { // avr only
|
||||||
|
PORTD &= ~_BV(PD7);
|
||||||
|
// Enable SPI double speed mode -> clock = f/2
|
||||||
|
SPSR = _BV(SPI2X);
|
||||||
|
dprintf("SPI fast\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_avr_mapper(uint8_t val) {
|
||||||
|
SPI_SS_HIGH();
|
||||||
|
FPGA_SS_LOW();
|
||||||
|
spiTransferByte(0x30 | (val & 0x0f));
|
||||||
|
FPGA_SS_HIGH();
|
||||||
|
SPI_SS_LOW();
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_avr_bank(uint8_t val) {
|
||||||
|
SPI_SS_HIGH();
|
||||||
|
FPGA_SS_LOW();
|
||||||
|
spiTransferByte(0x00); // SET ADDRESS
|
||||||
|
spiTransferByte(val * 0x20); // select chip
|
||||||
|
spiTransferByte(0x00); // select chip
|
||||||
|
spiTransferByte(0x00); // select chip
|
||||||
|
FPGA_SS_HIGH();
|
||||||
|
SPI_SS_LOW();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t fpga_test() {
|
||||||
|
spi_fpga();
|
||||||
|
spiTransferByte(0xF0); // TEST
|
||||||
|
spiTransferByte(0x00); // dummy
|
||||||
|
uint8_t result = spiTransferByte(0x00);
|
||||||
|
spi_none();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
78
mk1-src/fpga.h
Normal file
78
mk1-src/fpga.h
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
/* sd2snes - SD card based universal cartridge for the SNES
|
||||||
|
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
|
||||||
|
AVR firmware portion
|
||||||
|
|
||||||
|
Inspired by and based on code from sd2iec, written by Ingo Korb et al.
|
||||||
|
See sdcard.c|h, config.h.
|
||||||
|
|
||||||
|
FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
|
||||||
|
see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
fpga.h: FPGA (re)configuration
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FPGA_H
|
||||||
|
#define FPGA_H
|
||||||
|
|
||||||
|
void fpga_init(void);
|
||||||
|
uint8_t fpga_test(void);
|
||||||
|
void fpga_postinit(void);
|
||||||
|
void fpga_pgm(uint8_t* filename);
|
||||||
|
|
||||||
|
void set_avr_read(uint8_t val);
|
||||||
|
void set_avr_write(uint8_t val);
|
||||||
|
void set_avr_ena(uint8_t val);
|
||||||
|
void set_avr_nextaddr(uint8_t val);
|
||||||
|
void set_avr_addr_reset(uint8_t val);
|
||||||
|
void set_avr_data(uint8_t data);
|
||||||
|
void set_avr_addr_en(uint8_t val);
|
||||||
|
void set_avr_mapper(uint8_t val);
|
||||||
|
void set_avr_bank(uint8_t val);
|
||||||
|
|
||||||
|
uint8_t SPI_OFFLOAD;
|
||||||
|
|
||||||
|
#define FPGA_TEST_TOKEN (0xa5)
|
||||||
|
|
||||||
|
// some macros for bulk transfers (faster)
|
||||||
|
#define FPGA_SEND_BYTE(data) do {SET_AVR_DATA(data); CCLK();} while (0)
|
||||||
|
#define FPGA_SEND_BYTE_SERIAL(data) do {SET_AVR_DATA(data); CCLK();\
|
||||||
|
SET_AVR_DATA(data<<1); CCLK(); SET_AVR_DATA(data<<2); CCLK();\
|
||||||
|
SET_AVR_DATA(data<<3); CCLK(); SET_AVR_DATA(data<<4); CCLK();\
|
||||||
|
SET_AVR_DATA(data<<5); CCLK(); SET_AVR_DATA(data<<6); CCLK();\
|
||||||
|
SET_AVR_DATA(data<<7); CCLK();} while (0)
|
||||||
|
#define SET_CCLK() do {PORTD |= _BV(PD4);} while (0)
|
||||||
|
#define CLR_CCLK() do {PORTD &= ~_BV(PD4);} while (0)
|
||||||
|
#define CCLK() do {SET_CCLK(); CLR_CCLK();} while (0)
|
||||||
|
#define SET_AVR_READ() do {PORTB |= _BV(PB3);} while (0)
|
||||||
|
#define CLR_AVR_READ() do {PORTB &= ~_BV(PB3);} while (0)
|
||||||
|
#define SET_AVR_WRITE() do {PORTB |= _BV(PB2);} while (0)
|
||||||
|
#define CLR_AVR_WRITE() do {PORTB &= ~_BV(PB2);} while (0)
|
||||||
|
#define SET_AVR_EXCL() do {PORTD |= _BV(PD7);} while (0)
|
||||||
|
#define CLR_AVR_EXCL() do {PORTD &= ~_BV(PD7);} while (0)
|
||||||
|
#define SET_AVR_NEXTADDR() do {PORTA |= _BV(PA4);} while (0)
|
||||||
|
#define CLR_AVR_NEXTADDR() do {PORTA &= ~_BV(PA4);} while (0)
|
||||||
|
#define SET_AVR_ADDR_RESET() do {PORTA |= _BV(PA5);} while (0)
|
||||||
|
#define CLR_AVR_ADDR_RESET() do {PORTA &= ~_BV(PA5);} while (0)
|
||||||
|
#define SET_AVR_ADDR_EN() do {PORTA |= _BV(PA6);} while (0)
|
||||||
|
#define CLR_AVR_ADDR_EN() do {PORTA &= ~_BV(PA6);} while (0)
|
||||||
|
#define AVR_NEXTADDR() do {SET_AVR_NEXTADDR(); CLR_AVR_NEXTADDR();} while (0)
|
||||||
|
#define AVR_ADDR_RESET() do {CLR_AVR_ADDR_RESET();\
|
||||||
|
AVR_NEXTADDR();SET_AVR_ADDR_RESET();} while (0)
|
||||||
|
#define SET_AVR_DATA(data) do {PORTC = (uint8_t)data;} while (0)
|
||||||
|
#define AVR_READ() do {CLR_AVR_READ(); SET_AVR_READ();} while (0)
|
||||||
|
#define AVR_WRITE() do {CLR_AVR_WRITE(); SET_AVR_WRITE();} while (0)
|
||||||
|
#define AVR_DATA (PINC)
|
||||||
|
#endif
|
||||||
99
mk1-src/fpga_spi.c
Normal file
99
mk1-src/fpga_spi.c
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
/* sd2snes - SD card based universal cartridge for the SNES
|
||||||
|
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
|
||||||
|
AVR firmware portion
|
||||||
|
|
||||||
|
Inspired by and based on code from sd2iec, written by Ingo Korb et al.
|
||||||
|
See sdcard.c|h, config.h.
|
||||||
|
|
||||||
|
FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
|
||||||
|
see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
fpga_spi.h: functions for SPI ctrl, SRAM interfacing and feature configuration
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
|
||||||
|
SPI commands
|
||||||
|
|
||||||
|
cmd param function
|
||||||
|
=============================================
|
||||||
|
00 bb[hh[ll]] set address to 0xbb0000, 0xbbhh00, or 0xbbhhll
|
||||||
|
10 bbhhll set SNES input address mask to 0xbbhhll
|
||||||
|
20 bbhhll set SRAM address mask to 0xbbhhll
|
||||||
|
3m - set mapper to m
|
||||||
|
0=HiROM, 1=LoROM, 2=ExHiROM, 7=Menu
|
||||||
|
80 - read with increment
|
||||||
|
81 - read w/o increment
|
||||||
|
90 {xx}* write xx with increment
|
||||||
|
91 {xx}* write xx w/o increment
|
||||||
|
F0 - receive test token (to see if FPGA is alive)
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
#include <util/delay.h>
|
||||||
|
#include "avrcompat.h"
|
||||||
|
#include "fpga.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "uart.h"
|
||||||
|
#include "spi.h"
|
||||||
|
#include "fpga_spi.h"
|
||||||
|
|
||||||
|
void spi_fpga(void) {
|
||||||
|
SPI_SS_HIGH();
|
||||||
|
FPGA_SS_LOW();
|
||||||
|
}
|
||||||
|
|
||||||
|
void spi_sd(void) {
|
||||||
|
FPGA_SS_HIGH();
|
||||||
|
SPI_SS_LOW();
|
||||||
|
}
|
||||||
|
|
||||||
|
void spi_none(void) {
|
||||||
|
FPGA_SS_HIGH();
|
||||||
|
SPI_SS_HIGH();
|
||||||
|
}
|
||||||
|
|
||||||
|
void fpga_spi_init(void) {
|
||||||
|
DDRC = _BV(PC7);
|
||||||
|
FPGA_SS_HIGH();
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_avr_addr(uint32_t address) {
|
||||||
|
spi_fpga();
|
||||||
|
spiTransferByte(0x00);
|
||||||
|
spiTransferByte((address>>16)&0xff);
|
||||||
|
spiTransferByte((address>>8)&0xff);
|
||||||
|
spiTransferByte((address)&0xff);
|
||||||
|
spi_none();
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_saveram_mask(uint32_t mask) {
|
||||||
|
spi_fpga();
|
||||||
|
spiTransferByte(0x20);
|
||||||
|
spiTransferByte((mask>>16)&0xff);
|
||||||
|
spiTransferByte((mask>>8)&0xff);
|
||||||
|
spiTransferByte((mask)&0xff);
|
||||||
|
spi_none();
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_rom_mask(uint32_t mask) {
|
||||||
|
spi_fpga();
|
||||||
|
spiTransferByte(0x10);
|
||||||
|
spiTransferByte((mask>>16)&0xff);
|
||||||
|
spiTransferByte((mask>>8)&0xff);
|
||||||
|
spiTransferByte((mask)&0xff);
|
||||||
|
spi_none();
|
||||||
|
}
|
||||||
38
mk1-src/fpga_spi.h
Normal file
38
mk1-src/fpga_spi.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
/* sd2snes - SD card based universal cartridge for the SNES
|
||||||
|
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
|
||||||
|
AVR firmware portion
|
||||||
|
|
||||||
|
Inspired by and based on code from sd2iec, written by Ingo Korb et al.
|
||||||
|
See sdcard.c|h, config.h.
|
||||||
|
|
||||||
|
FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
|
||||||
|
see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
fpga_spi.h: functions for SPI ctrl, SRAM interfacing and feature configuration
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FPGA_SS_HIGH() do {PORTC |= _BV(PC7);} while (0)
|
||||||
|
#define FPGA_SS_LOW() do {PORTC &= ~_BV(PC7);} while (0)
|
||||||
|
|
||||||
|
void fpga_spi_init(void);
|
||||||
|
void fpga_spi_test(void);
|
||||||
|
void spi_fpga(void);
|
||||||
|
void spi_sd(void);
|
||||||
|
void spi_none(void);
|
||||||
|
void set_avr_addr(uint32_t);
|
||||||
|
void set_saveram_mask(uint32_t);
|
||||||
|
void set_rom_mask(uint32_t);
|
||||||
|
|
||||||
15
mk1-src/gcctest.awk
Executable file
15
mk1-src/gcctest.awk
Executable file
@@ -0,0 +1,15 @@
|
|||||||
|
#! /usr/bin/gawk -f
|
||||||
|
#
|
||||||
|
# Parse the output of (avr-)gcc --version for the version number
|
||||||
|
# and output YES if it is at least 4.3.
|
||||||
|
|
||||||
|
{
|
||||||
|
match($0, /\) ([0-9]+)\.([0-9]+)\./, ver);
|
||||||
|
if (RLENGTH > 0) {
|
||||||
|
major = 0+ver[1];
|
||||||
|
minor = 0+ver[2];
|
||||||
|
if (major > 4 || (major == 4 && minor > 2)) {
|
||||||
|
print "YES";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
31
mk1-src/integer.h
Normal file
31
mk1-src/integer.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/* Integer definitions for ff, based on example code from ChaN */
|
||||||
|
|
||||||
|
#ifndef _INTEGER
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* These types are assumed as 16-bit or larger integer */
|
||||||
|
typedef int16_t INT;
|
||||||
|
typedef uint16_t UINT;
|
||||||
|
|
||||||
|
/* These types are assumed as 8-bit integer */
|
||||||
|
typedef int8_t CHAR;
|
||||||
|
typedef uint8_t UCHAR;
|
||||||
|
typedef uint8_t BYTE;
|
||||||
|
|
||||||
|
/* These types are assumed as 16-bit integer */
|
||||||
|
typedef int16_t SHORT;
|
||||||
|
typedef uint16_t USHORT;
|
||||||
|
typedef uint16_t WORD;
|
||||||
|
typedef uint16_t WCHAR;
|
||||||
|
|
||||||
|
/* These types are assumed as 32-bit integer */
|
||||||
|
typedef int32_t LONG;
|
||||||
|
typedef uint32_t ULONG;
|
||||||
|
typedef uint32_t DWORD;
|
||||||
|
|
||||||
|
/* Boolean type */
|
||||||
|
typedef enum { FALSE = 0, TRUE } BOOL;
|
||||||
|
|
||||||
|
#define _INTEGER
|
||||||
|
#endif
|
||||||
110
mk1-src/led.c
Normal file
110
mk1-src/led.c
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
/* sd2snes - SD card based universal cartridge for the SNES
|
||||||
|
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
|
||||||
|
AVR firmware portion
|
||||||
|
|
||||||
|
Inspired by and based on code from sd2iec, written by Ingo Korb et al.
|
||||||
|
See sdcard.c|h, config.h.
|
||||||
|
|
||||||
|
FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
|
||||||
|
see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
led.c: LED control
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <util/delay.h>
|
||||||
|
#include "config.h"
|
||||||
|
#include "led.h"
|
||||||
|
|
||||||
|
static uint8_t led_bright[16]={255,253,252,251,249,247,244,239,232,223,210,191,165,127,74,0};
|
||||||
|
static uint8_t curr_bright = 15;
|
||||||
|
static uint8_t led_bounce_dir = 1;
|
||||||
|
|
||||||
|
volatile uint8_t led_state;
|
||||||
|
|
||||||
|
void led_panic(void) {
|
||||||
|
led_std();
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
set_pwr_led(1);
|
||||||
|
set_busy_led(1);
|
||||||
|
_delay_ms(150);
|
||||||
|
set_pwr_led(0);
|
||||||
|
set_busy_led(0);
|
||||||
|
_delay_ms(150);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggle_busy_led(void) {
|
||||||
|
PORTB &= ~_BV(PB3);
|
||||||
|
DDRB ^= _BV(PB3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggle_pwr_led(void) {
|
||||||
|
PORTB &= ~_BV(PB0);
|
||||||
|
DDRB ^= _BV(PB0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_busy_led(uint8_t state) {
|
||||||
|
PORTB &= ~_BV(PB3);
|
||||||
|
if(state) {
|
||||||
|
DDRB |= _BV(PB3);
|
||||||
|
} else {
|
||||||
|
DDRB &= ~_BV(PB3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_pwr_led(uint8_t state) {
|
||||||
|
PORTB &= ~_BV(PB0);
|
||||||
|
if(state) {
|
||||||
|
DDRB |= _BV(PB0);
|
||||||
|
} else {
|
||||||
|
DDRB &= ~_BV(PB0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_busy_pwm(uint8_t brightness) {
|
||||||
|
OCR0A = led_bright[brightness];
|
||||||
|
set_busy_led(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bounce_busy_led() {
|
||||||
|
set_busy_pwm(curr_bright);
|
||||||
|
if(led_bounce_dir) {
|
||||||
|
curr_bright--;
|
||||||
|
if(curr_bright==0) {
|
||||||
|
led_bounce_dir = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
curr_bright++;
|
||||||
|
if(curr_bright==15) {
|
||||||
|
led_bounce_dir = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void led_pwm() {
|
||||||
|
set_busy_led(1);
|
||||||
|
TCCR0A = 0x83;
|
||||||
|
TCCR0B = 0x01;
|
||||||
|
}
|
||||||
|
|
||||||
|
void led_std() {
|
||||||
|
set_busy_led(0);
|
||||||
|
TCCR0A = 0;
|
||||||
|
TCCR0B = 0;
|
||||||
|
}
|
||||||
50
mk1-src/led.h
Normal file
50
mk1-src/led.h
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/* sd2snes - SD card based universal cartridge for the SNES
|
||||||
|
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
|
||||||
|
AVR firmware portion
|
||||||
|
|
||||||
|
Inspired by and based on code from sd2iec, written by Ingo Korb et al.
|
||||||
|
See sdcard.c|h, config.h.
|
||||||
|
|
||||||
|
FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
|
||||||
|
see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
led.c: LED control
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LED_H
|
||||||
|
#define LED_H
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "uart.h"
|
||||||
|
|
||||||
|
/* LED-to-bit mapping - BUSY/DIRTY are only used for SINGLE_LED */
|
||||||
|
#define LED_ERROR 1
|
||||||
|
#define LED_BUSY 2
|
||||||
|
#define LED_DIRTY 4
|
||||||
|
|
||||||
|
extern volatile uint8_t led_state;
|
||||||
|
|
||||||
|
/* Update the LEDs to match the buffer state */
|
||||||
|
void toggle_busy_led(void);
|
||||||
|
void toggle_pwr_led(void);
|
||||||
|
void set_busy_led(uint8_t);
|
||||||
|
void set_pwr_led(uint8_t);
|
||||||
|
void set_busy_pwm(uint8_t brightness);
|
||||||
|
void bounce_busy_led(void);
|
||||||
|
void led_pwm(void);
|
||||||
|
void led_std(void);
|
||||||
|
void led_panic(void);
|
||||||
|
#endif
|
||||||
400
mk1-src/main.c
Normal file
400
mk1-src/main.c
Normal file
@@ -0,0 +1,400 @@
|
|||||||
|
/* sd2snes - SD card based universal cartridge for the SNES
|
||||||
|
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
|
||||||
|
AVR firmware portion
|
||||||
|
|
||||||
|
Inspired by and based on code from sd2iec, written by Ingo Korb et al.
|
||||||
|
See sdcard.c|h, config.h.
|
||||||
|
|
||||||
|
FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
|
||||||
|
see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
main.c: initialization and flow
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <avr/boot.h>
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
#include <avr/power.h>
|
||||||
|
#include <avr/wdt.h>
|
||||||
|
#include <util/delay.h>
|
||||||
|
#include "config.h"
|
||||||
|
#include "diskio.h"
|
||||||
|
#include "ff.h"
|
||||||
|
#include "led.h"
|
||||||
|
/* #include "timer.h" */
|
||||||
|
#include "fpga.h"
|
||||||
|
#include "uart.h"
|
||||||
|
#include "ustring.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "snes.h"
|
||||||
|
#include "fileops.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "fpga_spi.h"
|
||||||
|
#include "spi.h"
|
||||||
|
#include "avrcompat.h"
|
||||||
|
#include "filetypes.h"
|
||||||
|
#include "sdcard.h"
|
||||||
|
|
||||||
|
void writetest(void) {
|
||||||
|
// HERE BE LIONS, GET IN THE CAR
|
||||||
|
char teststring[58];
|
||||||
|
while(1) {
|
||||||
|
sram_writeblock((void*)"Testtext of DOOM!!1! 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", SRAM_SCRATCHPAD+0x20, 58);
|
||||||
|
sram_readblock((void*)teststring, SRAM_SCRATCHPAD+0x20, 58);
|
||||||
|
teststring[57]=0;
|
||||||
|
dprintf("%s\n", teststring);
|
||||||
|
}
|
||||||
|
// END OF LIONS
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void memtest(void) {
|
||||||
|
/* HERE BE DRAGONS */
|
||||||
|
uint32_t dbg_i;
|
||||||
|
for(dbg_i=0; dbg_i < 65536; dbg_i++) {
|
||||||
|
sram_writeshort((uint16_t)dbg_i&0xffff, dbg_i*2);
|
||||||
|
}
|
||||||
|
save_sram((uint8_t*)"/sd2snes/memtest", 0x20000, 0);
|
||||||
|
set_pwr_led(0);
|
||||||
|
while(1);
|
||||||
|
/* END OF DRAGONS */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Make sure the watchdog is disabled as soon as possible */
|
||||||
|
/* Copy this code to your bootloader if you use one and your */
|
||||||
|
/* MCU doesn't disable the WDT after reset! */
|
||||||
|
void get_mcusr(void) \
|
||||||
|
__attribute__((naked)) \
|
||||||
|
__attribute__((section(".init3")));
|
||||||
|
void get_mcusr(void)
|
||||||
|
{
|
||||||
|
MCUSR = 0;
|
||||||
|
wdt_disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_MEMPOISON
|
||||||
|
void poison_memory(void) \
|
||||||
|
__attribute__((naked)) \
|
||||||
|
__attribute__((section(".init1")));
|
||||||
|
void poison_memory(void) {
|
||||||
|
register uint16_t i;
|
||||||
|
register uint8_t *ptr;
|
||||||
|
|
||||||
|
asm("clr r1\n");
|
||||||
|
/* There is no RAMSTARt variable =( */
|
||||||
|
if (RAMEND > 2048 && RAMEND < 4096) {
|
||||||
|
/* 2K memory */
|
||||||
|
ptr = (void *)RAMEND-2047;
|
||||||
|
for (i=0;i<2048;i++)
|
||||||
|
ptr[i] = 0x55;
|
||||||
|
} else if (RAMEND > 4096 && RAMEND < 8192) {
|
||||||
|
/* 4K memory */
|
||||||
|
ptr = (void *)RAMEND-4095;
|
||||||
|
for (i=0;i<4096;i++)
|
||||||
|
ptr[i] = 0x55;
|
||||||
|
} else {
|
||||||
|
/* Assume 8K memory */
|
||||||
|
ptr = (void *)RAMEND-8191;
|
||||||
|
for (i=0;i<8192;i++)
|
||||||
|
ptr[i] = 0x55;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 1)
|
||||||
|
int main(void) __attribute__((OS_main));
|
||||||
|
#endif
|
||||||
|
int main(void) {
|
||||||
|
#if defined __AVR_ATmega644__ || defined __AVR_ATmega644P__ || defined __AVR_ATmega2561__
|
||||||
|
asm volatile("in r24, %0\n"
|
||||||
|
"ori r24, 0x80\n"
|
||||||
|
"out %0, r24\n"
|
||||||
|
"out %0, r24\n"
|
||||||
|
:
|
||||||
|
: "I" (_SFR_IO_ADDR(MCUCR))
|
||||||
|
: "r24"
|
||||||
|
);
|
||||||
|
#elif defined __AVR_ATmega32__
|
||||||
|
asm volatile ("in r24, %0\n"
|
||||||
|
"ori r24, 0x80\n"
|
||||||
|
"out %0, r24\n"
|
||||||
|
"out %0, r24\n"
|
||||||
|
:
|
||||||
|
: "I" (_SFR_IO_ADDR(MCUCSR))
|
||||||
|
: "r24"
|
||||||
|
);
|
||||||
|
#elif defined __AVR_ATmega128__ || defined __AVR_ATmega1281__
|
||||||
|
/* Just assume that JTAG doesn't hurt us on the m128 */
|
||||||
|
#else
|
||||||
|
# error Unknown chip!
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CLOCK_PRESCALE
|
||||||
|
clock_prescale_set(CLOCK_PRESCALE);
|
||||||
|
#endif
|
||||||
|
set_pwr_led(0);
|
||||||
|
set_busy_led(1);
|
||||||
|
spi_none();
|
||||||
|
snes_reset(1);
|
||||||
|
uart_init();
|
||||||
|
sei();
|
||||||
|
_delay_ms(100);
|
||||||
|
disk_init();
|
||||||
|
snes_init();
|
||||||
|
/* timer_init(); */
|
||||||
|
uart_puts_P(PSTR("\nsd2snes " VERSION));
|
||||||
|
uart_putcrlf();
|
||||||
|
|
||||||
|
file_init();
|
||||||
|
FATFS fatfs;
|
||||||
|
f_mount(0,&fatfs);
|
||||||
|
uart_putc('W');
|
||||||
|
fpga_init();
|
||||||
|
fpga_pgm((uint8_t*)"/sd2snes/main.bit");
|
||||||
|
_delay_ms(100);
|
||||||
|
set_pwr_led(1);
|
||||||
|
fpga_spi_init();
|
||||||
|
uart_putc('!');
|
||||||
|
_delay_ms(100);
|
||||||
|
|
||||||
|
restart:
|
||||||
|
set_avr_ena(0);
|
||||||
|
snes_reset(1);
|
||||||
|
|
||||||
|
*fs_path=0;
|
||||||
|
uint16_t saved_dir_id;
|
||||||
|
get_db_id(&saved_dir_id);
|
||||||
|
|
||||||
|
uint16_t mem_dir_id = sram_readshort(SRAM_DIRID);
|
||||||
|
uint32_t mem_magic = sram_readlong(SRAM_SCRATCHPAD);
|
||||||
|
|
||||||
|
while(0) {
|
||||||
|
SD_SPI_OFFLOAD=0;
|
||||||
|
set_avr_addr(0L);
|
||||||
|
sd_read(0, file_buf, 0L, 1);
|
||||||
|
uart_trace((void*)file_buf, 0, 0x200);
|
||||||
|
// sram_writeblock((void*)file_buf, 0, 0x200);
|
||||||
|
// sram_hexdump(0,0x200);
|
||||||
|
uart_putc('+');
|
||||||
|
}
|
||||||
|
/* here be strange monsters */
|
||||||
|
while(0){
|
||||||
|
// uint16_t hurdur1 = 0, hurdur2 = 0;
|
||||||
|
spiTransferByte(0x00);
|
||||||
|
spiTransferByte(0x00);
|
||||||
|
spiTransferByte(0x00);
|
||||||
|
spiTransferByte(0x00);
|
||||||
|
spiTransferByte(0x00);
|
||||||
|
spiTransferByte(0x00);
|
||||||
|
spiTransferByte(0x00);
|
||||||
|
spiTransferByte(0x00);
|
||||||
|
spiTransferByte(0x00);
|
||||||
|
spiTransferByte(0x00);
|
||||||
|
spiTransferByte(0x00);
|
||||||
|
spiTransferByte(0x00);
|
||||||
|
spiTransferByte(0x00);
|
||||||
|
PORTB |= _BV(PB2);
|
||||||
|
DDRB |= _BV(PB2);
|
||||||
|
PORTB &= ~_BV(PB2);
|
||||||
|
DDRB &= ~_BV(PB7); // tristate SCK
|
||||||
|
PORTB |= _BV(PB2);
|
||||||
|
DDRB &= ~_BV(PB2);
|
||||||
|
while(!(PINB & _BV(PB2))) {
|
||||||
|
}
|
||||||
|
DDRB |= _BV(PB7);
|
||||||
|
_delay_ms(1);
|
||||||
|
// dprintf("hurdur1=%d hurdur2=%d\n", hurdur1, hurdur2);
|
||||||
|
}
|
||||||
|
if((mem_magic != 0x12345678) || (mem_dir_id != saved_dir_id)) {
|
||||||
|
uint16_t curr_dir_id = scan_dir(fs_path, 0, 0); // generate files footprint
|
||||||
|
dprintf("curr dir id = %x\n", curr_dir_id);
|
||||||
|
if((get_db_id(&saved_dir_id) != FR_OK) // no database?
|
||||||
|
|| saved_dir_id != curr_dir_id) { // files changed? // XXX
|
||||||
|
dprintf("saved dir id = %x\n", saved_dir_id);
|
||||||
|
dprintf("rebuilding database...");
|
||||||
|
_delay_ms(50);
|
||||||
|
curr_dir_id = scan_dir(fs_path, 1, 0); // then rebuild database
|
||||||
|
sram_writeblock(&curr_dir_id, SRAM_DB_ADDR, 2);
|
||||||
|
uint32_t endaddr, direndaddr;
|
||||||
|
sram_readblock(&endaddr, SRAM_DB_ADDR+4, 4);
|
||||||
|
sram_readblock(&direndaddr, SRAM_DB_ADDR+8, 4);
|
||||||
|
dprintf("%lx %lx\n", endaddr, direndaddr);
|
||||||
|
save_sram((uint8_t*)"/sd2snes/sd2snes.db", endaddr-SRAM_DB_ADDR, SRAM_DB_ADDR);
|
||||||
|
save_sram((uint8_t*)"/sd2snes/sd2snes.dir", direndaddr-(SRAM_DIR_ADDR), SRAM_DIR_ADDR);
|
||||||
|
dprintf("done\n");
|
||||||
|
// sram_hexdump(SRAM_DB_ADDR, 0x400);
|
||||||
|
} else {
|
||||||
|
dprintf("saved dir id = %x\n", saved_dir_id);
|
||||||
|
dprintf("different card, consistent db, loading db...\n");
|
||||||
|
load_sram((uint8_t*)"/sd2snes/sd2snes.db", SRAM_DB_ADDR);
|
||||||
|
load_sram((uint8_t*)"/sd2snes/sd2snes.dir", SRAM_DIR_ADDR);
|
||||||
|
}
|
||||||
|
// save_sram((uint8_t*)"/debug.smc", 0x400000, 0);
|
||||||
|
// uart_putc('[');
|
||||||
|
// load_sram((uint8_t*)"/test.srm", SRAM_SAVE_ADDR);
|
||||||
|
// uart_putc(']');
|
||||||
|
|
||||||
|
sram_writeshort(curr_dir_id, SRAM_DIRID);
|
||||||
|
sram_writelong(0x12345678, SRAM_SCRATCHPAD);
|
||||||
|
} else {
|
||||||
|
dprintf("same card, loading db...\n");
|
||||||
|
load_sram((uint8_t*)"/sd2snes/sd2snes.db", SRAM_DB_ADDR);
|
||||||
|
load_sram((uint8_t*)"/sd2snes/sd2snes.dir", SRAM_DIR_ADDR);
|
||||||
|
}
|
||||||
|
|
||||||
|
led_pwm();
|
||||||
|
|
||||||
|
// sram_hexdump(0, 0x200);
|
||||||
|
uart_putc('(');
|
||||||
|
load_rom((uint8_t*)"/sd2snes/menu.bin", SRAM_MENU_ADDR);
|
||||||
|
set_rom_mask(0x3fffff); // force mirroring off
|
||||||
|
set_avr_mapper(0x7); // menu mapper XXX
|
||||||
|
uart_putc(')');
|
||||||
|
uart_putcrlf();
|
||||||
|
// sram_hexdump(0x7ffff0, 0x10);
|
||||||
|
// sram_hexdump(0, 0x400);
|
||||||
|
// save_sram((uint8_t*)"/sd2snes/dump", 65536, 0);
|
||||||
|
|
||||||
|
sram_writebyte(0, SRAM_CMD_ADDR);
|
||||||
|
|
||||||
|
set_busy_led(0);
|
||||||
|
set_avr_ena(1);
|
||||||
|
|
||||||
|
_delay_ms(100);
|
||||||
|
uart_puts_P(PSTR("SNES GO!\r\n"));
|
||||||
|
snes_reset(0);
|
||||||
|
// writetest();
|
||||||
|
/* snes_reset(1);
|
||||||
|
set_avr_ena(0);
|
||||||
|
led_std();
|
||||||
|
set_busy_led(1);
|
||||||
|
save_sram((uint8_t*)"/sd2snes/dump", 65536, SRAM_MENU_ADDR);
|
||||||
|
set_busy_led(0);
|
||||||
|
set_avr_ena(1);
|
||||||
|
snes_reset(0); */
|
||||||
|
uint8_t cmd = 0;
|
||||||
|
|
||||||
|
while(!sram_reliable());
|
||||||
|
while(!cmd) {
|
||||||
|
cmd=menu_main_loop();
|
||||||
|
switch(cmd) {
|
||||||
|
case 0x01: // SNES_CMD_LOADROM:
|
||||||
|
get_selected_name(file_lfn);
|
||||||
|
_delay_ms(100);
|
||||||
|
// snes_reset(1);
|
||||||
|
set_avr_ena(0);
|
||||||
|
dprintf("Selected name: %s\n", file_lfn);
|
||||||
|
load_rom(file_lfn, SRAM_ROM_ADDR);
|
||||||
|
// save_sram((uint8_t*)"/sd2snes/test.smc", romprops.romsize_bytes, 0);
|
||||||
|
if(romprops.ramsize_bytes) {
|
||||||
|
strcpy(strrchr((char*)file_lfn, (int)'.'), ".srm");
|
||||||
|
dprintf("SRM file: %s\n", file_lfn);
|
||||||
|
load_sram(file_lfn, SRAM_SAVE_ADDR);
|
||||||
|
} else {
|
||||||
|
dprintf("No SRAM\n");
|
||||||
|
}
|
||||||
|
set_avr_ena(1);
|
||||||
|
snes_reset(1);
|
||||||
|
_delay_ms(100);
|
||||||
|
snes_reset(0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dprintf("unknown cmd: %d\n", cmd);
|
||||||
|
cmd=0; // unknown cmd: stay in loop
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
dprintf("cmd was %x, going to snes main loop\n", cmd);
|
||||||
|
led_std();
|
||||||
|
cmd=0;
|
||||||
|
uint8_t snes_reset_prev=0, snes_reset_now=0, snes_reset_state=0;
|
||||||
|
uint16_t reset_count=0;
|
||||||
|
while(fpga_test() == FPGA_TEST_TOKEN) {
|
||||||
|
snes_reset_now=get_snes_reset();
|
||||||
|
if(snes_reset_now) {
|
||||||
|
if(!snes_reset_prev) {
|
||||||
|
dprintf("RESET BUTTON DOWN\n");
|
||||||
|
snes_reset_state=1;
|
||||||
|
// reset reset counter
|
||||||
|
reset_count=0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(snes_reset_prev) {
|
||||||
|
dprintf("RESET BUTTON UP\n");
|
||||||
|
snes_reset_state=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(snes_reset_state) {
|
||||||
|
_delay_ms(10);
|
||||||
|
reset_count++;
|
||||||
|
} else {
|
||||||
|
sram_reliable();
|
||||||
|
snes_main_loop();
|
||||||
|
}
|
||||||
|
if(reset_count>100) {
|
||||||
|
reset_count=0;
|
||||||
|
led_std();
|
||||||
|
set_avr_ena(0);
|
||||||
|
snes_reset(1);
|
||||||
|
_delay_ms(100);
|
||||||
|
if(romprops.ramsize_bytes && fpga_test() == 0xa5) {
|
||||||
|
set_busy_led(1);
|
||||||
|
save_sram(file_lfn, romprops.ramsize_bytes, SRAM_SAVE_ADDR);
|
||||||
|
set_busy_led(0);
|
||||||
|
}
|
||||||
|
_delay_ms(1000);
|
||||||
|
set_busy_led(1);
|
||||||
|
goto restart;
|
||||||
|
}
|
||||||
|
snes_reset_prev = snes_reset_now;
|
||||||
|
}
|
||||||
|
// FPGA TEST FAIL. PANIC.
|
||||||
|
led_panic();
|
||||||
|
|
||||||
|
/* HERE BE LIONS */
|
||||||
|
while(1) {
|
||||||
|
set_avr_addr(0x600000);
|
||||||
|
spi_fpga();
|
||||||
|
spiTransferByte(0x81); // read w/ increment... hopefully
|
||||||
|
spiTransferByte(0x00); // 1 dummy read
|
||||||
|
uart_putcrlf();
|
||||||
|
uint8_t buff[21];
|
||||||
|
for(uint8_t cnt=0; cnt<21; cnt++) {
|
||||||
|
uint8_t data=spiTransferByte(0x00);
|
||||||
|
buff[cnt]=data;
|
||||||
|
}
|
||||||
|
for(uint8_t cnt=0; cnt<21; cnt++) {
|
||||||
|
uint8_t data = buff[cnt];
|
||||||
|
_delay_ms(2);
|
||||||
|
if(data>=0x20 && data <= 0x7a) {
|
||||||
|
uart_putc(data);
|
||||||
|
} else {
|
||||||
|
// uart_putc('.');
|
||||||
|
uart_putc("0123456789ABCDEF"[data>>4]);
|
||||||
|
uart_putc("0123456789ABCDEF"[data&15]);
|
||||||
|
uart_putc(' ');
|
||||||
|
}
|
||||||
|
// set_avr_bank(3);
|
||||||
|
}
|
||||||
|
spi_none();
|
||||||
|
}
|
||||||
|
while(1);
|
||||||
|
}
|
||||||
|
|
||||||
335
mk1-src/memory.c
Normal file
335
mk1-src/memory.c
Normal file
@@ -0,0 +1,335 @@
|
|||||||
|
/* sd2snes - SD card based universal cartridge for the SNES
|
||||||
|
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
|
||||||
|
AVR firmware portion
|
||||||
|
|
||||||
|
Inspired by and based on code from sd2iec, written by Ingo Korb et al.
|
||||||
|
See sdcard.c|h, config.h.
|
||||||
|
|
||||||
|
FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
|
||||||
|
see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
memory.c: RAM operations
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
#include <util/delay.h>
|
||||||
|
#include "config.h"
|
||||||
|
#include "uart.h"
|
||||||
|
#include "fpga.h"
|
||||||
|
#include "crc16.h"
|
||||||
|
#include "ff.h"
|
||||||
|
#include "fileops.h"
|
||||||
|
#include "spi.h"
|
||||||
|
#include "fpga_spi.h"
|
||||||
|
#include "avrcompat.h"
|
||||||
|
#include "led.h"
|
||||||
|
#include "smc.h"
|
||||||
|
#include "fpga_spi.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "snes.h"
|
||||||
|
|
||||||
|
char* hex = "0123456789ABCDEF";
|
||||||
|
|
||||||
|
void sram_hexdump(uint32_t addr, uint32_t len) {
|
||||||
|
static uint8_t buf[16];
|
||||||
|
uint32_t ptr;
|
||||||
|
for(ptr=0; ptr < len; ptr += 16) {
|
||||||
|
sram_readblock((void*)buf, ptr+addr, 16);
|
||||||
|
uart_trace(buf, 0, 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sram_writebyte(uint8_t val, uint32_t addr) {
|
||||||
|
set_avr_addr(addr);
|
||||||
|
spi_fpga();
|
||||||
|
spiTransferByte(0x91); // WRITE
|
||||||
|
spiTransferByte(val);
|
||||||
|
spiTransferByte(0x00); // dummy
|
||||||
|
spi_none();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t sram_readbyte(uint32_t addr) {
|
||||||
|
set_avr_addr(addr);
|
||||||
|
spi_fpga();
|
||||||
|
spiTransferByte(0x81); // READ
|
||||||
|
spiTransferByte(0x00); // dummy
|
||||||
|
uint8_t val = spiTransferByte(0x00);
|
||||||
|
spi_none();
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sram_writeshort(uint16_t val, uint32_t addr) {
|
||||||
|
set_avr_addr(addr);
|
||||||
|
spi_fpga();
|
||||||
|
spiTransferByte(0x91); // WRITE
|
||||||
|
spiTransferByte(val&0xff); // 7-0
|
||||||
|
spiTransferByte((val>>8)&0xff); // 15-8
|
||||||
|
spiTransferByte(0x00); // dummy
|
||||||
|
spi_none();
|
||||||
|
}
|
||||||
|
|
||||||
|
void sram_writelong(uint32_t val, uint32_t addr) {
|
||||||
|
set_avr_addr(addr);
|
||||||
|
spi_fpga();
|
||||||
|
spiTransferByte(0x91); // WRITE
|
||||||
|
spiTransferByte(val&0xff); // 7-0
|
||||||
|
spiTransferByte((val>>8)&0xff); // 15-8
|
||||||
|
spiTransferByte((val>>16)&0xff); // 23-15
|
||||||
|
spiTransferByte((val>>24)&0xff); // 31-24
|
||||||
|
spiTransferByte(0x00); // dummy
|
||||||
|
spi_none();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t sram_readshort(uint32_t addr) {
|
||||||
|
set_avr_addr(addr);
|
||||||
|
spi_fpga();
|
||||||
|
spiTransferByte(0x81);
|
||||||
|
spiTransferByte(0x00);
|
||||||
|
|
||||||
|
uint32_t val = spiTransferByte(0x00);
|
||||||
|
val |= ((uint32_t)spiTransferByte(0x00)<<8);
|
||||||
|
spi_none();
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t sram_readlong(uint32_t addr) {
|
||||||
|
set_avr_addr(addr);
|
||||||
|
spi_fpga();
|
||||||
|
spiTransferByte(0x81);
|
||||||
|
spiTransferByte(0x00);
|
||||||
|
uint32_t count=0;
|
||||||
|
uint32_t val = spiTransferByte(count & 0xff);
|
||||||
|
count++;
|
||||||
|
val |= ((uint32_t)spiTransferByte(count & val)<<8);
|
||||||
|
count++;
|
||||||
|
val |= ((uint32_t)spiTransferByte(count & val)<<16);
|
||||||
|
count++;
|
||||||
|
val |= ((uint32_t)spiTransferByte(count & val)<<24);
|
||||||
|
count++;
|
||||||
|
spi_none();
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sram_readblock(void* buf, uint32_t addr, uint16_t size) {
|
||||||
|
uint16_t count=size;
|
||||||
|
uint8_t* tgt = buf;
|
||||||
|
set_avr_addr(addr);
|
||||||
|
spi_fpga();
|
||||||
|
spiTransferByte(0x81); // READ
|
||||||
|
spiTransferByte(0x00); // dummy
|
||||||
|
while(count--) {
|
||||||
|
*(tgt++) = spiTransferByte(0x00);
|
||||||
|
}
|
||||||
|
spi_none();
|
||||||
|
}
|
||||||
|
|
||||||
|
void sram_writeblock(void* buf, uint32_t addr, uint16_t size) {
|
||||||
|
uint16_t count=size;
|
||||||
|
uint8_t* src = buf;
|
||||||
|
set_avr_addr(addr);
|
||||||
|
spi_fpga();
|
||||||
|
spiTransferByte(0x91); // WRITE
|
||||||
|
while(count--) {
|
||||||
|
spiTransferByte(*src++);
|
||||||
|
}
|
||||||
|
spiTransferByte(0x00); // dummy
|
||||||
|
spi_none();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t load_rom(uint8_t* filename, uint32_t base_addr) {
|
||||||
|
// uint8_t dummy;
|
||||||
|
UINT bytes_read;
|
||||||
|
DWORD filesize;
|
||||||
|
UINT count=0;
|
||||||
|
file_open(filename, FA_READ);
|
||||||
|
filesize = file_handle.fsize;
|
||||||
|
smc_id(&romprops);
|
||||||
|
set_avr_addr(base_addr);
|
||||||
|
dprintf("no nervous breakdown beyond this point! or else!\n");
|
||||||
|
if(file_res) {
|
||||||
|
uart_putc('?');
|
||||||
|
uart_putc(0x30+file_res);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
f_lseek(&file_handle, romprops.offset);
|
||||||
|
spi_none();
|
||||||
|
for(;;) {
|
||||||
|
SPI_OFFLOAD=1;
|
||||||
|
spi_none();
|
||||||
|
bytes_read = file_read();
|
||||||
|
if (file_res || !bytes_read) break;
|
||||||
|
if(!(count++ % 8)) {
|
||||||
|
// toggle_busy_led();
|
||||||
|
bounce_busy_led();
|
||||||
|
uart_putc('.');
|
||||||
|
}
|
||||||
|
/* spi_fpga();
|
||||||
|
spiTransferByte(0x91); // write w/ increment
|
||||||
|
if(!(count++ % 8)) {
|
||||||
|
// toggle_busy_led();
|
||||||
|
bounce_busy_led();
|
||||||
|
uart_putc('.');
|
||||||
|
}
|
||||||
|
for(int j=0; j<bytes_read; j++) {
|
||||||
|
// spiTransferByte(file_buf[j]);
|
||||||
|
SPDR = file_buf[j];
|
||||||
|
loop_until_bit_is_set(SPSR, SPIF);
|
||||||
|
dummy = SPDR;
|
||||||
|
}
|
||||||
|
spiTransferByte(0x00); // dummy tx for increment+write pulse */
|
||||||
|
}
|
||||||
|
file_close();
|
||||||
|
spi_none();
|
||||||
|
set_avr_mapper(romprops.mapper_id);
|
||||||
|
uart_puthex(romprops.header.map);
|
||||||
|
uart_putc(0x30+romprops.mapper_id);
|
||||||
|
|
||||||
|
uint32_t rammask;
|
||||||
|
uint32_t rommask;
|
||||||
|
|
||||||
|
if(filesize > (romprops.romsize_bytes + romprops.offset)) {
|
||||||
|
romprops.romsize_bytes <<= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(romprops.header.ramsize == 0) {
|
||||||
|
rammask = 0;
|
||||||
|
} else {
|
||||||
|
rammask = romprops.ramsize_bytes - 1;
|
||||||
|
}
|
||||||
|
rommask = romprops.romsize_bytes - 1;
|
||||||
|
|
||||||
|
uart_putc(' ');
|
||||||
|
uart_puthex(romprops.header.ramsize);
|
||||||
|
uart_putc('-');
|
||||||
|
uart_puthexlong(rammask);
|
||||||
|
uart_putc(' ');
|
||||||
|
uart_puthex(romprops.header.romsize);
|
||||||
|
uart_putc('-');
|
||||||
|
uart_puthexlong(rommask);
|
||||||
|
set_saveram_mask(rammask);
|
||||||
|
set_rom_mask(rommask);
|
||||||
|
|
||||||
|
return (uint32_t)filesize;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t load_sram(uint8_t* filename, uint32_t base_addr) {
|
||||||
|
set_avr_addr(base_addr);
|
||||||
|
UINT bytes_read;
|
||||||
|
DWORD filesize;
|
||||||
|
file_open(filename, FA_READ);
|
||||||
|
filesize = file_handle.fsize;
|
||||||
|
if(file_res) return 0;
|
||||||
|
for(;;) {
|
||||||
|
// FPGA_SS_HIGH();
|
||||||
|
// SPI_SS_LOW();
|
||||||
|
SPI_OFFLOAD=1;
|
||||||
|
bytes_read = file_read();
|
||||||
|
// SPI_SS_HIGH();
|
||||||
|
if (file_res || !bytes_read) break;
|
||||||
|
// FPGA_SS_LOW();
|
||||||
|
/* spiTransferByte(0x91);
|
||||||
|
for(int j=0; j<bytes_read; j++) {
|
||||||
|
spiTransferByte(file_buf[j]);
|
||||||
|
}
|
||||||
|
spiTransferByte(0x00); // dummy tx
|
||||||
|
FPGA_SS_HIGH(); // */
|
||||||
|
}
|
||||||
|
file_close();
|
||||||
|
return (uint32_t)filesize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void save_sram(uint8_t* filename, uint32_t sram_size, uint32_t base_addr) {
|
||||||
|
uint32_t count = 0;
|
||||||
|
uint32_t num = 0;
|
||||||
|
|
||||||
|
spi_none();
|
||||||
|
file_open(filename, FA_CREATE_ALWAYS | FA_WRITE);
|
||||||
|
if(file_res) {
|
||||||
|
uart_putc(0x30+file_res);
|
||||||
|
}
|
||||||
|
while(count<sram_size) {
|
||||||
|
set_avr_addr(base_addr+count);
|
||||||
|
spi_fpga();
|
||||||
|
spiTransferByte(0x81); // read
|
||||||
|
spiTransferByte(0); // dummy
|
||||||
|
for(int j=0; j<sizeof(file_buf); j++) {
|
||||||
|
file_buf[j] = spiTransferByte(0x00);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
spi_none();
|
||||||
|
num = file_write();
|
||||||
|
if(file_res) {
|
||||||
|
uart_putc(0x30+file_res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t calc_sram_crc(uint32_t base_addr, uint32_t size) {
|
||||||
|
uint8_t data;
|
||||||
|
uint32_t count;
|
||||||
|
uint16_t crc;
|
||||||
|
crc=0;
|
||||||
|
crc_valid=1;
|
||||||
|
set_avr_addr(base_addr);
|
||||||
|
spi_fpga();
|
||||||
|
spiTransferByte(0x81);
|
||||||
|
spiTransferByte(0x00);
|
||||||
|
for(count=0; count<size; count++) {
|
||||||
|
data = spiTransferByte(0);
|
||||||
|
if(get_snes_reset()) {
|
||||||
|
crc_valid = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
crc += crc16_update(crc, &data, 1);
|
||||||
|
}
|
||||||
|
spi_none();
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t sram_reliable() {
|
||||||
|
uint16_t score=0;
|
||||||
|
uint32_t val;
|
||||||
|
// uint32_t val = sram_readlong(SRAM_SCRATCHPAD);
|
||||||
|
uint8_t result = 0;
|
||||||
|
/* while(score<SRAM_RELIABILITY_SCORE) {
|
||||||
|
if(sram_readlong(SRAM_SCRATCHPAD)==val) {
|
||||||
|
score++;
|
||||||
|
} else {
|
||||||
|
set_pwr_led(0);
|
||||||
|
score=0;
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
for(uint16_t i = 0; i < SRAM_RELIABILITY_SCORE; i++) {
|
||||||
|
val=sram_readlong(SRAM_SCRATCHPAD);
|
||||||
|
if(val==0x12345678) {
|
||||||
|
score++;
|
||||||
|
// } else {
|
||||||
|
// dprintf("i=%d val=%08lX\n", i, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(score<SRAM_RELIABILITY_SCORE) {
|
||||||
|
result = 0;
|
||||||
|
// dprintf("score=%d\n", score);
|
||||||
|
} else {
|
||||||
|
result = 1;
|
||||||
|
}
|
||||||
|
set_pwr_led(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
60
mk1-src/memory.h
Normal file
60
mk1-src/memory.h
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/* sd2snes - SD card based universal cartridge for the SNES
|
||||||
|
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
|
||||||
|
AVR firmware portion
|
||||||
|
|
||||||
|
Inspired by and based on code from sd2iec, written by Ingo Korb et al.
|
||||||
|
See sdcard.c|h, config.h.
|
||||||
|
|
||||||
|
FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
|
||||||
|
see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
memory.h: RAM operations
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MEMORY_H
|
||||||
|
#define MEMORY_H
|
||||||
|
|
||||||
|
#define SRAM_ROM_ADDR (0x000000L)
|
||||||
|
#define SRAM_SAVE_ADDR (0x600000L)
|
||||||
|
|
||||||
|
#define SRAM_MENU_ADDR (0x600000L)
|
||||||
|
#define SRAM_DB_ADDR (0x620000L)
|
||||||
|
#define SRAM_DIR_ADDR (0x610000L)
|
||||||
|
#define SRAM_CMD_ADDR (0x7F1004L)
|
||||||
|
#define SRAM_FD_ADDR (0x7F1000L)
|
||||||
|
#define SRAM_MENU_SAVE_ADDR (0x7F0000L)
|
||||||
|
#define SRAM_SCRATCHPAD (0x7FFF00L)
|
||||||
|
#define SRAM_DIRID (0x7FFFF0L)
|
||||||
|
#define SRAM_RELIABILITY_SCORE (0x100)
|
||||||
|
|
||||||
|
uint32_t load_rom(uint8_t* filename, uint32_t base_addr);
|
||||||
|
uint32_t load_sram(uint8_t* filename, uint32_t base_addr);
|
||||||
|
void sram_hexdump(uint32_t addr, uint32_t len);
|
||||||
|
uint8_t sram_readbyte(uint32_t addr);
|
||||||
|
uint16_t sram_readshort(uint32_t addr);
|
||||||
|
uint32_t sram_readlong(uint32_t addr);
|
||||||
|
void sram_writebyte(uint8_t val, uint32_t addr);
|
||||||
|
void sram_writeshort(uint16_t val, uint32_t addr);
|
||||||
|
void sram_writelong(uint32_t val, uint32_t addr);
|
||||||
|
void sram_readblock(void* buf, uint32_t addr, uint16_t size);
|
||||||
|
void sram_writeblock(void* buf, uint32_t addr, uint16_t size);
|
||||||
|
void save_sram(uint8_t* filename, uint32_t sram_size, uint32_t base_addr);
|
||||||
|
uint32_t calc_sram_crc(uint32_t base_addr, uint32_t size);
|
||||||
|
uint8_t sram_reliable(void);
|
||||||
|
|
||||||
|
#include "smc.h"
|
||||||
|
snes_romprops_t romprops;
|
||||||
|
#endif
|
||||||
773
mk1-src/sdcard.c
Normal file
773
mk1-src/sdcard.c
Normal file
@@ -0,0 +1,773 @@
|
|||||||
|
/* sd2iec - SD/MMC to Commodore serial bus interface/controller
|
||||||
|
Copyright (C) 2007-2009 Ingo Korb <ingo@akana.de>
|
||||||
|
|
||||||
|
Inspiration and low-level SD/MMC access based on code from MMC2IEC
|
||||||
|
by Lars Pontoppidan et al., see sdcard.c|h and config.h.
|
||||||
|
|
||||||
|
FAT filesystem access based on code from ChaN and Jim Brain, see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
|
sdcard.c: SD/MMC access routines
|
||||||
|
|
||||||
|
Extended, optimized and cleaned version of code from MMC2IEC,
|
||||||
|
original copyright header follows:
|
||||||
|
|
||||||
|
//
|
||||||
|
// Title : SD/MMC Card driver
|
||||||
|
// Author : Lars Pontoppidan, Aske Olsson, Pascal Dufour,
|
||||||
|
// Date : Jan. 2006
|
||||||
|
// Version : 0.42
|
||||||
|
// Target MCU : Atmel AVR Series
|
||||||
|
//
|
||||||
|
// CREDITS:
|
||||||
|
// This module is developed as part of a project at the technical univerisity of
|
||||||
|
// Denmark, DTU.
|
||||||
|
//
|
||||||
|
// DESCRIPTION:
|
||||||
|
// This SD card driver implements the fundamental communication with a SD card.
|
||||||
|
// The driver is confirmed working on 8 MHz and 14.7456 MHz AtMega32 and has
|
||||||
|
// been tested successfully with a large number of different SD and MMC cards.
|
||||||
|
//
|
||||||
|
// DISCLAIMER:
|
||||||
|
// The author is in no way responsible for any problems or damage caused by
|
||||||
|
// using this code. Use at your own risk.
|
||||||
|
//
|
||||||
|
// LICENSE:
|
||||||
|
// This code is distributed under the GNU Public License
|
||||||
|
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
||||||
|
//
|
||||||
|
|
||||||
|
The exported functions in this file are weak-aliased to their corresponding
|
||||||
|
versions defined in diskio.h so when this file is the only diskio provider
|
||||||
|
compiled in they will be automatically used by the linker.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
#include <util/crc16.h>
|
||||||
|
#include <util/delay.h>
|
||||||
|
#include "config.h"
|
||||||
|
#include "avrcompat.h"
|
||||||
|
#include "crc7.h"
|
||||||
|
#include "diskio.h"
|
||||||
|
#include "spi.h"
|
||||||
|
#include "uart.h"
|
||||||
|
#include "sdcard.h"
|
||||||
|
#include "fpga_spi.h"
|
||||||
|
#ifndef TRUE
|
||||||
|
#define TRUE -1
|
||||||
|
#endif
|
||||||
|
#ifndef FALSE
|
||||||
|
#define FALSE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_TWINSD
|
||||||
|
# define MAX_CARDS 2
|
||||||
|
#else
|
||||||
|
# define MAX_CARDS 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// SD/MMC commands
|
||||||
|
#define GO_IDLE_STATE 0
|
||||||
|
#define SEND_OP_COND 1
|
||||||
|
#define SWITCH_FUNC 6
|
||||||
|
#define SEND_IF_COND 8
|
||||||
|
#define SEND_CSD 9
|
||||||
|
#define SEND_CID 10
|
||||||
|
#define STOP_TRANSMISSION 12
|
||||||
|
#define SEND_STATUS 13
|
||||||
|
#define SET_BLOCKLEN 16
|
||||||
|
#define READ_SINGLE_BLOCK 17
|
||||||
|
#define READ_MULTIPLE_BLOCK 18
|
||||||
|
#define WRITE_BLOCK 24
|
||||||
|
#define WRITE_MULTIPLE_BLOCK 25
|
||||||
|
#define PROGRAM_CSD 27
|
||||||
|
#define SET_WRITE_PROT 28
|
||||||
|
#define CLR_WRITE_PROT 29
|
||||||
|
#define SEND_WRITE_PROT 30
|
||||||
|
#define ERASE_WR_BLK_STAR_ADDR 32
|
||||||
|
#define ERASE_WR_BLK_END_ADDR 33
|
||||||
|
#define ERASE 38
|
||||||
|
#define LOCK_UNLOCK 42
|
||||||
|
#define APP_CMD 55
|
||||||
|
#define GEN_CMD 56
|
||||||
|
#define READ_OCR 58
|
||||||
|
#define CRC_ON_OFF 59
|
||||||
|
|
||||||
|
// SD ACMDs
|
||||||
|
#define SD_STATUS 13
|
||||||
|
#define SD_SEND_NUM_WR_BLOCKS 22
|
||||||
|
#define SD_SET_WR_BLK_ERASE_COUNT 23
|
||||||
|
#define SD_SEND_OP_COND 41
|
||||||
|
#define SD_SET_CLR_CARD_DETECT 42
|
||||||
|
#define SD_SEND_SCR 51
|
||||||
|
|
||||||
|
// R1 status bits
|
||||||
|
#define STATUS_IN_IDLE 1
|
||||||
|
#define STATUS_ERASE_RESET 2
|
||||||
|
#define STATUS_ILLEGAL_COMMAND 4
|
||||||
|
#define STATUS_CRC_ERROR 8
|
||||||
|
#define STATUS_ERASE_SEQ_ERROR 16
|
||||||
|
#define STATUS_ADDRESS_ERROR 32
|
||||||
|
#define STATUS_PARAMETER_ERROR 64
|
||||||
|
|
||||||
|
|
||||||
|
/* Card types - cardtype == 0 is MMC */
|
||||||
|
#define CARD_SD (1<<0)
|
||||||
|
#define CARD_SDHC (1<<1)
|
||||||
|
|
||||||
|
static uint8_t cardtype[MAX_CARDS];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getbits - read value from bit buffer
|
||||||
|
* @buffer: pointer to the data buffer
|
||||||
|
* @start : index of the first bit in the value
|
||||||
|
* @bits : number of bits in the value
|
||||||
|
*
|
||||||
|
* This function returns a value from the memory region passed as
|
||||||
|
* buffer, starting with bit "start" and "bits" bit long. The buffer
|
||||||
|
* is assumed to be MSB first, passing 0 for start will read starting
|
||||||
|
* from the highest-value bit of the first byte of the buffer.
|
||||||
|
*/
|
||||||
|
static uint32_t getbits(void *buffer, uint16_t start, int8_t bits) {
|
||||||
|
uint8_t *buf = buffer;
|
||||||
|
uint32_t result = 0;
|
||||||
|
|
||||||
|
if ((start % 8) != 0) {
|
||||||
|
/* Unaligned start */
|
||||||
|
result += buf[start / 8] & (0xff >> (start % 8));
|
||||||
|
bits -= 8 - (start % 8);
|
||||||
|
start += 8 - (start % 8);
|
||||||
|
}
|
||||||
|
while (bits >= 8) {
|
||||||
|
result = (result << 8) + buf[start / 8];
|
||||||
|
start += 8;
|
||||||
|
bits -= 8;
|
||||||
|
}
|
||||||
|
if (bits > 0) {
|
||||||
|
result = result << bits;
|
||||||
|
result = result + (buf[start / 8] >> (8-bits));
|
||||||
|
} else if (bits < 0) {
|
||||||
|
/* Fraction of a single byte */
|
||||||
|
result = result >> -bits;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t sdResponse(uint8_t expected)
|
||||||
|
{
|
||||||
|
unsigned short count = 0x0FFF;
|
||||||
|
|
||||||
|
while ((spiTransferByte(0xFF) != expected) && count )
|
||||||
|
count--;
|
||||||
|
|
||||||
|
// If count didn't run out, return success
|
||||||
|
return (count != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t sdWaitWriteFinish(void)
|
||||||
|
{
|
||||||
|
uint32_t count = 0x1FFFF; // wait for quite some time
|
||||||
|
|
||||||
|
while ((spiTransferByte(0xFF) == 0) && count )
|
||||||
|
count--;
|
||||||
|
|
||||||
|
// If count didn't run out, return success
|
||||||
|
return (count != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void deselectCard(uint8_t card) {
|
||||||
|
// Send 8 clock cycles
|
||||||
|
SPI_SS_HIGH(card);
|
||||||
|
spiTransferByte(0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sendCommand - send a command to the SD card
|
||||||
|
* @card : card number to be accessed
|
||||||
|
* @command : command to be sent
|
||||||
|
* @parameter: parameter to be sent
|
||||||
|
* @deselect : Flags if the card should be deselected afterwards
|
||||||
|
*
|
||||||
|
* This function calculates the correct CRC7 for the command and
|
||||||
|
* parameter and transmits all of it to the SD card. If requested
|
||||||
|
* the card will be deselected afterwards.
|
||||||
|
*/
|
||||||
|
static int sendCommand(const uint8_t card,
|
||||||
|
const uint8_t command,
|
||||||
|
const uint32_t parameter,
|
||||||
|
const uint8_t deselect) {
|
||||||
|
union {
|
||||||
|
uint32_t l;
|
||||||
|
uint8_t c[4];
|
||||||
|
} long2char;
|
||||||
|
|
||||||
|
uint8_t i,crc=0,errorcount;
|
||||||
|
uint16_t counter;
|
||||||
|
|
||||||
|
long2char.l = parameter;
|
||||||
|
crc = crc7update(0 , 0x40+command);
|
||||||
|
crc = crc7update(crc, long2char.c[3]);
|
||||||
|
crc = crc7update(crc, long2char.c[2]);
|
||||||
|
crc = crc7update(crc, long2char.c[1]);
|
||||||
|
crc = crc7update(crc, long2char.c[0]);
|
||||||
|
crc = (crc << 1) | 1;
|
||||||
|
|
||||||
|
errorcount = 0;
|
||||||
|
while (errorcount < CONFIG_SD_AUTO_RETRIES) {
|
||||||
|
// Select card
|
||||||
|
SPI_SS_LOW(card);
|
||||||
|
#ifdef CONFIG_TWINSD
|
||||||
|
if (card == 0 && command == GO_IDLE_STATE)
|
||||||
|
/* Force both cards to SPI mode simultaneously */
|
||||||
|
SPI_SS_LOW(1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Transfer command
|
||||||
|
spiTransferByte(0x40+command);
|
||||||
|
spiTransferLong(parameter);
|
||||||
|
spiTransferByte(crc);
|
||||||
|
|
||||||
|
// Wait for a valid response
|
||||||
|
counter = 0;
|
||||||
|
do {
|
||||||
|
i = spiTransferByte(0xff);
|
||||||
|
counter++;
|
||||||
|
} while (i & 0x80 && counter < 0x1000);
|
||||||
|
|
||||||
|
#ifdef CONFIG_TWINSD
|
||||||
|
if (card == 0 && command == GO_IDLE_STATE)
|
||||||
|
SPI_SS_HIGH(1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Check for CRC error
|
||||||
|
// can't reliably retry unless deselect is allowed
|
||||||
|
if (deselect && (i & STATUS_CRC_ERROR)) {
|
||||||
|
uart_putc('x');
|
||||||
|
deselectCard(card);
|
||||||
|
errorcount++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deselect) deselectCard(card);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extended init sequence for SDHC support
|
||||||
|
static uint8_t extendedInit(const uint8_t card) {
|
||||||
|
uint8_t i;
|
||||||
|
uint32_t answer;
|
||||||
|
// Send CMD8: SEND_IF_COND
|
||||||
|
// 0b000110101010 == 2.7-3.6V supply, check pattern 0xAA
|
||||||
|
i = sendCommand(card, SEND_IF_COND, 0b000110101010, 0);
|
||||||
|
if (i > 1) {
|
||||||
|
// Card returned an error, ok (MMC oder SD1.x) but not SDHC
|
||||||
|
deselectCard(card);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No error, continue SDHC initialization
|
||||||
|
answer = spiTransferLong(0);
|
||||||
|
deselectCard(card);
|
||||||
|
|
||||||
|
if (((answer >> 8) & 0x0f) != 0b0001) {
|
||||||
|
// Card didn't accept our voltage specification
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify echo-back of check pattern
|
||||||
|
if ((answer & 0xff) != 0b10101010) {
|
||||||
|
// Check pattern mismatch, working but not SD2.0 compliant
|
||||||
|
// The specs say we should not use the card, but let's try anyway.
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SD common initialisation
|
||||||
|
static void sdInit(const uint8_t card) {
|
||||||
|
uint8_t i;
|
||||||
|
uint16_t counter;
|
||||||
|
|
||||||
|
SD_SPI_OFFLOAD = 0;
|
||||||
|
|
||||||
|
counter = 0xffff;
|
||||||
|
do {
|
||||||
|
// Prepare for ACMD, send CMD55: APP_CMD
|
||||||
|
i = sendCommand(card, APP_CMD, 0, 1);
|
||||||
|
if (i > 1)
|
||||||
|
// Command not accepted, could be MMC
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Send ACMD41: SD_SEND_OP_COND
|
||||||
|
// 1L<<30 == Host has High Capacity Support
|
||||||
|
i = sendCommand(card, SD_SEND_OP_COND, 1L<<30, 1);
|
||||||
|
// Repeat while card card accepts command but isn't ready
|
||||||
|
} while (i == 1 && --counter > 0);
|
||||||
|
|
||||||
|
// Ignore failures, there is at least one Sandisk MMC card
|
||||||
|
// that accepts CMD55, but not ACMD41.
|
||||||
|
if (i == 0)
|
||||||
|
/* We know that a card is SD if ACMD41 was accepted. */
|
||||||
|
cardtype[card] |= CARD_SD;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Detect changes of SD card 0 */
|
||||||
|
#ifdef SD_CHANGE_VECT
|
||||||
|
ISR(SD_CHANGE_VECT) {
|
||||||
|
if (SDCARD_DETECT)
|
||||||
|
disk_state = DISK_CHANGED;
|
||||||
|
else
|
||||||
|
disk_state = DISK_REMOVED;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_TWINSD
|
||||||
|
/* Detect changes of SD card 1 */
|
||||||
|
ISR(SD2_CHANGE_VECT) {
|
||||||
|
if (SD2_DETECT)
|
||||||
|
disk_state = DISK_CHANGED;
|
||||||
|
else
|
||||||
|
disk_state = DISK_REMOVED;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// Public functions
|
||||||
|
//
|
||||||
|
void sd_init(void) {
|
||||||
|
SDCARD_DETECT_SETUP();
|
||||||
|
SDCARD_WP_SETUP();
|
||||||
|
SD_CHANGE_SETUP();
|
||||||
|
#ifdef CONFIG_TWINSD
|
||||||
|
/* Initialize the control lines for card 2 */
|
||||||
|
SD2_SETUP();
|
||||||
|
SD2_CHANGE_SETUP();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
void disk_init(void) __attribute__ ((weak, alias("sd_init")));
|
||||||
|
|
||||||
|
|
||||||
|
DSTATUS sd_status(BYTE drv) {
|
||||||
|
#ifdef CONFIG_TWINSD
|
||||||
|
if (drv != 0) {
|
||||||
|
if (SD2_DETECT) {
|
||||||
|
if (SD2_PIN & SD2_WP) {
|
||||||
|
return STA_PROTECT;
|
||||||
|
} else {
|
||||||
|
return RES_OK;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return STA_NOINIT|STA_NODISK;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
if (SDCARD_DETECT) {
|
||||||
|
// uart_putc('0');
|
||||||
|
if (SDCARD_WP) {
|
||||||
|
// uart_putc('1');
|
||||||
|
return STA_PROTECT;
|
||||||
|
} else {
|
||||||
|
// uart_putc('2');
|
||||||
|
return RES_OK;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// uart_putc('3');
|
||||||
|
return STA_NOINIT|STA_NODISK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DSTATUS disk_status(BYTE drv) __attribute__ ((weak, alias("sd_status")));
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sd_initialize - initialize SD card
|
||||||
|
* @drv : drive
|
||||||
|
*
|
||||||
|
* This function tries to initialize the selected SD card.
|
||||||
|
*/
|
||||||
|
DSTATUS sd_initialize(BYTE drv) {
|
||||||
|
uint8_t i;
|
||||||
|
uint16_t counter;
|
||||||
|
uint32_t answer;
|
||||||
|
|
||||||
|
if (drv >= MAX_CARDS)
|
||||||
|
return STA_NOINIT|STA_NODISK;
|
||||||
|
|
||||||
|
/* Don't bother initializing a card that isn't there */
|
||||||
|
// uart_putc('#');
|
||||||
|
if (sd_status(drv) & STA_NODISK)
|
||||||
|
return sd_status(drv);
|
||||||
|
|
||||||
|
/* JLB: Should be in sd_init, but some uIEC versions have
|
||||||
|
* IEC lines tied to SPI, so I moved it here to resolve the
|
||||||
|
* conflict.
|
||||||
|
*/
|
||||||
|
spiInit();
|
||||||
|
|
||||||
|
disk_state = DISK_ERROR;
|
||||||
|
|
||||||
|
cardtype[drv] = 0;
|
||||||
|
|
||||||
|
SPI_SS_HIGH(drv);
|
||||||
|
|
||||||
|
// Send 80 clks
|
||||||
|
for (i=0; i<10; i++) {
|
||||||
|
spiTransferByte(0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset card
|
||||||
|
i = sendCommand(drv, GO_IDLE_STATE, 0, 1);
|
||||||
|
if (i != 1) {
|
||||||
|
return STA_NOINIT | STA_NODISK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!extendedInit(drv))
|
||||||
|
return STA_NOINIT | STA_NODISK;
|
||||||
|
|
||||||
|
sdInit(drv);
|
||||||
|
|
||||||
|
counter = 0xffff;
|
||||||
|
// According to the spec READ_OCR should work at this point
|
||||||
|
// without retries. One of my Sandisk-cards thinks otherwise.
|
||||||
|
do {
|
||||||
|
// Send CMD58: READ_OCR
|
||||||
|
i = sendCommand(drv, READ_OCR, 0, 0);
|
||||||
|
if (i > 1)
|
||||||
|
deselectCard(drv);
|
||||||
|
} while (i > 1 && counter-- > 0);
|
||||||
|
|
||||||
|
if (counter > 0) {
|
||||||
|
answer = spiTransferLong(0);
|
||||||
|
|
||||||
|
// See if the card likes our supply voltage
|
||||||
|
if (!(answer & SD_SUPPLY_VOLTAGE)) {
|
||||||
|
// The code isn't set up to completely ignore the card,
|
||||||
|
// but at least report it as nonworking
|
||||||
|
deselectCard(drv);
|
||||||
|
return STA_NOINIT | STA_NODISK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// See what card we've got
|
||||||
|
if (answer & 0x40000000) {
|
||||||
|
cardtype[drv] |= CARD_SDHC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep sending CMD1 (SEND_OP_COND) command until zero response
|
||||||
|
counter = 0xffff;
|
||||||
|
do {
|
||||||
|
i = sendCommand(drv, SEND_OP_COND, 1L<<30, 1);
|
||||||
|
counter--;
|
||||||
|
} while (i != 0 && counter > 0);
|
||||||
|
|
||||||
|
if (counter==0) {
|
||||||
|
return STA_NOINIT | STA_NODISK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_SD_DATACRC
|
||||||
|
// Enable CRC checking
|
||||||
|
// The SD spec says that the host "should" send CRC_ON_OFF before ACMD_SEND_OP_COND.
|
||||||
|
// The MMC manual I have says that CRC_ON_OFF isn't allowed before SEND_OP_COND.
|
||||||
|
// Let's just hope that all SD cards work with this order. =(
|
||||||
|
i = sendCommand(drv, CRC_ON_OFF, 1, 1);
|
||||||
|
if (i > 1) {
|
||||||
|
return STA_NOINIT | STA_NODISK;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Send MMC CMD16(SET_BLOCKLEN) to 512 bytes
|
||||||
|
i = sendCommand(drv, SET_BLOCKLEN, 512, 1);
|
||||||
|
if (i != 0) {
|
||||||
|
return STA_NOINIT | STA_NODISK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Thats it!
|
||||||
|
disk_state = DISK_OK;
|
||||||
|
return sd_status(drv);
|
||||||
|
}
|
||||||
|
DSTATUS disk_initialize(BYTE drv) __attribute__ ((weak, alias("sd_initialize")));
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sd_read - reads sectors from the SD card to buffer
|
||||||
|
* @drv : drive
|
||||||
|
* @buffer: pointer to the buffer
|
||||||
|
* @sector: first sector to be read
|
||||||
|
* @count : number of sectors to be read
|
||||||
|
*
|
||||||
|
* This function reads count sectors from the SD card starting
|
||||||
|
* at sector to buffer. Returns RES_ERROR if an error occured or
|
||||||
|
* RES_OK if successful. Up to SD_AUTO_RETRIES will be made if
|
||||||
|
* the calculated data CRC does not match the one sent by the
|
||||||
|
* card. If there were errors during the command transmission
|
||||||
|
* disk_state will be set to DISK_ERROR and no retries are made.
|
||||||
|
*/
|
||||||
|
DRESULT sd_read(BYTE drv, BYTE *buffer, DWORD sector, BYTE count) {
|
||||||
|
uint8_t sec,res,tmp,errorcount;
|
||||||
|
uint16_t crc,recvcrc;
|
||||||
|
if (drv >= MAX_CARDS)
|
||||||
|
return RES_PARERR;
|
||||||
|
|
||||||
|
for (sec=0;sec<count;sec++) {
|
||||||
|
errorcount = 0;
|
||||||
|
while (errorcount < CONFIG_SD_AUTO_RETRIES) {
|
||||||
|
if (cardtype[drv] & CARD_SDHC)
|
||||||
|
res = sendCommand(drv, READ_SINGLE_BLOCK, sector+sec, 0);
|
||||||
|
else
|
||||||
|
res = sendCommand(drv, READ_SINGLE_BLOCK, (sector+sec) << 9, 0);
|
||||||
|
|
||||||
|
if (res != 0) {
|
||||||
|
uart_putc('?');
|
||||||
|
dprintf("SD error: %02x\n", res);
|
||||||
|
SPI_SS_HIGH(drv);
|
||||||
|
disk_state = DISK_ERROR;
|
||||||
|
return RES_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for data token
|
||||||
|
if (!sdResponse(0xFE)) {
|
||||||
|
uart_putc('-');
|
||||||
|
SPI_SS_HIGH(drv);
|
||||||
|
disk_state = DISK_ERROR;
|
||||||
|
return RES_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t i;
|
||||||
|
#ifdef CONFIG_SD_DATACRC
|
||||||
|
BYTE *oldbuffer = buffer;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Get data
|
||||||
|
crc = 0;
|
||||||
|
|
||||||
|
if(SD_SPI_OFFLOAD) {
|
||||||
|
// uart_putc('O');
|
||||||
|
PORTB |= _BV(PB2);
|
||||||
|
DDRB |= _BV(PB2);
|
||||||
|
_delay_us(1);
|
||||||
|
PORTB &= ~_BV(PB2);
|
||||||
|
DDRB &= ~_BV(PB7); // tristate SCK
|
||||||
|
PORTB |= _BV(PB2);
|
||||||
|
DDRB &= ~_BV(PB2);
|
||||||
|
_delay_us(1);
|
||||||
|
while(!(PINB & _BV(PB2)));
|
||||||
|
DDRB |= _BV(PB7);
|
||||||
|
DDRB |= _BV(PB2);
|
||||||
|
// _delay_us(1);
|
||||||
|
deselectCard(drv);
|
||||||
|
SD_SPI_OFFLOAD = 0;
|
||||||
|
return RES_OK;
|
||||||
|
SPDR = 0xff;
|
||||||
|
} else {
|
||||||
|
// Initiate data exchange over SPI
|
||||||
|
SPDR = 0xff;
|
||||||
|
|
||||||
|
for (i=0; i<512; i++) {
|
||||||
|
// Wait until data has been received
|
||||||
|
loop_until_bit_is_set(SPSR, SPIF);
|
||||||
|
tmp = SPDR;
|
||||||
|
// Transmit the next byte while we store the current one
|
||||||
|
SPDR = 0xff;
|
||||||
|
|
||||||
|
*(buffer++) = tmp;
|
||||||
|
#ifdef CONFIG_SD_DATACRC
|
||||||
|
crc = _crc_xmodem_update(crc, tmp);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Wait until the first CRC byte is received
|
||||||
|
loop_until_bit_is_set(SPSR, SPIF);
|
||||||
|
|
||||||
|
// Check CRC
|
||||||
|
recvcrc = (SPDR << 8) + spiTransferByte(0xff);
|
||||||
|
#ifdef CONFIG_SD_DATACRC
|
||||||
|
if (recvcrc != crc) {
|
||||||
|
uart_putc('X');
|
||||||
|
deselectCard(drv);
|
||||||
|
errorcount++;
|
||||||
|
buffer = oldbuffer;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
deselectCard(drv);
|
||||||
|
|
||||||
|
if (errorcount >= CONFIG_SD_AUTO_RETRIES) return RES_ERROR;
|
||||||
|
}
|
||||||
|
return RES_OK;
|
||||||
|
}
|
||||||
|
DRESULT disk_read(BYTE drv, BYTE *buffer, DWORD sector, BYTE count) __attribute__ ((weak, alias("sd_read")));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sd_write - writes sectors from buffer to the SD card
|
||||||
|
* @drv : drive
|
||||||
|
* @buffer: pointer to the buffer
|
||||||
|
* @sector: first sector to be written
|
||||||
|
* @count : number of sectors to be written
|
||||||
|
*
|
||||||
|
* This function writes count sectors from buffer to the SD card
|
||||||
|
* starting at sector. Returns RES_ERROR if an error occured,
|
||||||
|
* RES_WPRT if the card is currently write-protected or RES_OK
|
||||||
|
* if successful. Up to SD_AUTO_RETRIES will be made if the card
|
||||||
|
* signals a CRC error. If there were errors during the command
|
||||||
|
* transmission disk_state will be set to DISK_ERROR and no retries
|
||||||
|
* are made.
|
||||||
|
*/
|
||||||
|
DRESULT sd_write(BYTE drv, const BYTE *buffer, DWORD sector, BYTE count) {
|
||||||
|
uint8_t res,sec,errorcount,status;
|
||||||
|
uint16_t crc;
|
||||||
|
|
||||||
|
if (drv >= MAX_CARDS)
|
||||||
|
return RES_PARERR;
|
||||||
|
|
||||||
|
#ifdef CONFIG_TWINSD
|
||||||
|
if (drv != 0) {
|
||||||
|
if (SD2_PIN & SD2_WP)
|
||||||
|
return RES_WRPRT;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (SDCARD_WP) return RES_WRPRT;
|
||||||
|
|
||||||
|
for (sec=0;sec<count;sec++) {
|
||||||
|
errorcount = 0;
|
||||||
|
while (errorcount < CONFIG_SD_AUTO_RETRIES) {
|
||||||
|
if (cardtype[drv] & CARD_SDHC)
|
||||||
|
res = sendCommand(drv, WRITE_BLOCK, sector+sec, 0);
|
||||||
|
else
|
||||||
|
res = sendCommand(drv, WRITE_BLOCK, (sector+sec)<<9, 0);
|
||||||
|
|
||||||
|
if (res != 0) {
|
||||||
|
uart_putc('C');
|
||||||
|
SPI_SS_HIGH(drv);
|
||||||
|
disk_state = DISK_ERROR;
|
||||||
|
return RES_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send data token
|
||||||
|
spiTransferByte(0xFE);
|
||||||
|
|
||||||
|
uint16_t i;
|
||||||
|
const BYTE *oldbuffer = buffer;
|
||||||
|
|
||||||
|
// Send data
|
||||||
|
crc = 0;
|
||||||
|
for (i=0; i<512; i++) {
|
||||||
|
#ifdef CONFIG_SD_DATACRC
|
||||||
|
crc = _crc_xmodem_update(crc, *buffer);
|
||||||
|
#endif
|
||||||
|
spiTransferByte(*(buffer++));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send CRC
|
||||||
|
spiTransferByte(crc >> 8);
|
||||||
|
spiTransferByte(crc & 0xff);
|
||||||
|
|
||||||
|
// Get and check status feedback
|
||||||
|
status = spiTransferByte(0xFF);
|
||||||
|
|
||||||
|
// Retry if neccessary
|
||||||
|
if ((status & 0x0F) != 0x05) {
|
||||||
|
uart_putc('X');
|
||||||
|
deselectCard(drv);
|
||||||
|
errorcount++;
|
||||||
|
buffer = oldbuffer;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for write finish
|
||||||
|
if (!sdWaitWriteFinish()) {
|
||||||
|
uart_putc('W');
|
||||||
|
SPI_SS_HIGH(drv);
|
||||||
|
disk_state = DISK_ERROR;
|
||||||
|
return RES_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
deselectCard(drv);
|
||||||
|
|
||||||
|
if (errorcount >= CONFIG_SD_AUTO_RETRIES) {
|
||||||
|
if (!(status & STATUS_CRC_ERROR))
|
||||||
|
disk_state = DISK_ERROR;
|
||||||
|
return RES_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return RES_OK;
|
||||||
|
}
|
||||||
|
DRESULT disk_write(BYTE drv, const BYTE *buffer, DWORD sector, BYTE count) __attribute__ ((weak, alias("sd_write")));
|
||||||
|
|
||||||
|
DRESULT sd_getinfo(BYTE drv, BYTE page, void *buffer) {
|
||||||
|
uint8_t i;
|
||||||
|
uint8_t buf[18];
|
||||||
|
uint32_t capacity;
|
||||||
|
|
||||||
|
if (drv >= MAX_CARDS)
|
||||||
|
return RES_NOTRDY;
|
||||||
|
|
||||||
|
if (sd_status(drv) & STA_NODISK)
|
||||||
|
return RES_NOTRDY;
|
||||||
|
|
||||||
|
if (page != 0)
|
||||||
|
return RES_ERROR;
|
||||||
|
|
||||||
|
/* Try to calculate the total number of sectors on the card */
|
||||||
|
/* FIXME: Write a generic data read function and merge with sd_read */
|
||||||
|
if (sendCommand(drv, SEND_CSD, 0, 0) != 0) {
|
||||||
|
deselectCard(drv);
|
||||||
|
return RES_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait for data token */
|
||||||
|
if (!sdResponse(0xfe)) {
|
||||||
|
deselectCard(drv);
|
||||||
|
return RES_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0;i<18;i++) {
|
||||||
|
buf[i] = spiTransferByte(0xff);
|
||||||
|
}
|
||||||
|
deselectCard(drv);
|
||||||
|
|
||||||
|
if (cardtype[drv] & CARD_SDHC) {
|
||||||
|
/* Special CSD for SDHC cards */
|
||||||
|
capacity = (1 + getbits(buf,127-69,22)) * 1024;
|
||||||
|
} else {
|
||||||
|
/* Assume that MMC-CSD 1.0/1.1/1.2 and SD-CSD 1.1 are the same... */
|
||||||
|
uint8_t exponent = 2 + getbits(buf, 127-49, 3);
|
||||||
|
capacity = 1 + getbits(buf, 127-73, 12);
|
||||||
|
exponent += getbits(buf, 127-83,4) - 9;
|
||||||
|
while (exponent--) capacity *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
diskinfo0_t *di = buffer;
|
||||||
|
di->validbytes = sizeof(diskinfo0_t);
|
||||||
|
di->disktype = DISK_TYPE_SD;
|
||||||
|
di->sectorsize = 2;
|
||||||
|
di->sectorcount = capacity;
|
||||||
|
|
||||||
|
return RES_OK;
|
||||||
|
}
|
||||||
|
DRESULT disk_getinfo(BYTE drv, BYTE page, void *buffer) __attribute__ ((weak, alias("sd_getinfo")));
|
||||||
40
mk1-src/sdcard.h
Normal file
40
mk1-src/sdcard.h
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/* sd2iec - SD/MMC to Commodore serial bus interface/controller
|
||||||
|
Copyright (C) 2007-2009 Ingo Korb <ingo@akana.de>
|
||||||
|
|
||||||
|
Inspiration and low-level SD/MMC access based on code from MMC2IEC
|
||||||
|
by Lars Pontoppidan et al., see sdcard.c|h and config.h.
|
||||||
|
|
||||||
|
FAT filesystem access based on code from ChaN and Jim Brain, see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
|
sdcard.h: Definitions for the SD/MMC access routines
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SDCARD_H
|
||||||
|
#define SDCARD_H
|
||||||
|
|
||||||
|
#include "diskio.h"
|
||||||
|
|
||||||
|
/* These functions are weak-aliased to disk_... */
|
||||||
|
void sd_init(void);
|
||||||
|
DSTATUS sd_status(BYTE drv);
|
||||||
|
DSTATUS sd_initialize(BYTE drv);
|
||||||
|
DRESULT sd_read(BYTE drv, BYTE *buffer, DWORD sector, BYTE count);
|
||||||
|
DRESULT sd_write(BYTE drv, const BYTE *buffer, DWORD sector, BYTE count);
|
||||||
|
DRESULT sd_getinfo(BYTE drv, BYTE page, void *buffer);
|
||||||
|
|
||||||
|
#endif
|
||||||
175
mk1-src/smc.c
Normal file
175
mk1-src/smc.c
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
/* sd2snes - SD card based universal cartridge for the SNES
|
||||||
|
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
|
||||||
|
AVR firmware portion
|
||||||
|
|
||||||
|
Inspired by and based on code from sd2iec, written by Ingo Korb et al.
|
||||||
|
See sdcard.c|h, config.h.
|
||||||
|
|
||||||
|
FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
|
||||||
|
see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
smc.c: SMC file related operations
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <util/delay.h>
|
||||||
|
#include "fileops.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "uart.h"
|
||||||
|
#include "smc.h"
|
||||||
|
|
||||||
|
uint32_t hdr_addr[6] = {0xffb0, 0x101b0, 0x7fb0, 0x81b0, 0x40ffb0, 0x4101b0};
|
||||||
|
uint8_t countAllASCII(uint8_t* data, int size) {
|
||||||
|
uint8_t res = 0;
|
||||||
|
do {
|
||||||
|
size--;
|
||||||
|
if(data[size] >= 0x20 && data[size] <= 0x7e) {
|
||||||
|
res++;
|
||||||
|
}
|
||||||
|
} while (size);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t countAllJISX0201(uint8_t* data, int size) {
|
||||||
|
uint8_t res = 0;
|
||||||
|
do {
|
||||||
|
size--;
|
||||||
|
if((data[size] >= 0x20 && data[size] <= 0x7e)
|
||||||
|
||(data[size] >= 0xa1 && data[size] <= 0xdf)) {
|
||||||
|
res++;
|
||||||
|
}
|
||||||
|
} while (size);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t isFixed(uint8_t* data, int size, uint8_t value) {
|
||||||
|
uint8_t res = 1;
|
||||||
|
do {
|
||||||
|
size--;
|
||||||
|
if(data[size] != value) {
|
||||||
|
res = 0;
|
||||||
|
}
|
||||||
|
} while (size);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t checkChksum(uint16_t cchk, uint16_t chk) {
|
||||||
|
uint32_t sum = cchk + chk;
|
||||||
|
uint8_t res = 0;
|
||||||
|
if(sum==0x0000ffff) {
|
||||||
|
res = 0x10;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void smc_id(snes_romprops_t* props) {
|
||||||
|
uint8_t score, maxscore=1, score_idx=2; // assume LoROM
|
||||||
|
|
||||||
|
snes_header_t* header = &(props->header);
|
||||||
|
|
||||||
|
for(uint8_t num = 0; num < 6; num++) {
|
||||||
|
if(!file_readblock(header, hdr_addr[num], sizeof(snes_header_t))
|
||||||
|
|| file_res) {
|
||||||
|
// dprintf("uh oh... %d\n", file_res);
|
||||||
|
// _delay_ms(30);
|
||||||
|
score = 0;
|
||||||
|
} else {
|
||||||
|
score = smc_headerscore(header)/(1+(num&1));
|
||||||
|
if((file_handle.fsize & 0x2ff) == 0x200) {
|
||||||
|
if(num&1) {
|
||||||
|
score+=20;
|
||||||
|
} else {
|
||||||
|
score=0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(!(num&1)) {
|
||||||
|
score+=20;
|
||||||
|
} else {
|
||||||
|
score=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// dprintf("%d: offset = %lX; score = %d\n", num, hdr_addr[num], score);
|
||||||
|
// _delay_ms(100);
|
||||||
|
if(score>=maxscore) {
|
||||||
|
score_idx=num;
|
||||||
|
maxscore=score;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(score_idx & 1) {
|
||||||
|
props->offset = 0x200;
|
||||||
|
} else {
|
||||||
|
props->offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// restore the chosen one
|
||||||
|
// dprintf("winner is %d\n", score_idx);
|
||||||
|
// _delay_ms(30);
|
||||||
|
file_readblock(header, hdr_addr[score_idx], sizeof(snes_header_t));
|
||||||
|
switch(header->map & 0xef) {
|
||||||
|
case 0x20:
|
||||||
|
props->mapper_id = 1;
|
||||||
|
break;
|
||||||
|
case 0x21:
|
||||||
|
props->mapper_id = 0;
|
||||||
|
break;
|
||||||
|
case 0x25:
|
||||||
|
props->mapper_id = 2;
|
||||||
|
break;
|
||||||
|
default: // invalid/unsupported mapper, use header location
|
||||||
|
switch(score_idx) {
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
props->mapper_id = 0;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
props->mapper_id = 1;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
case 5:
|
||||||
|
props->mapper_id = 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
props->mapper_id = 1; // whatever
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(header->romsize == 0 || header->romsize > 13) {
|
||||||
|
header->romsize = 13;
|
||||||
|
}
|
||||||
|
props->ramsize_bytes = (uint32_t)1024 << header->ramsize;
|
||||||
|
props->romsize_bytes = (uint32_t)1024 << header->romsize;
|
||||||
|
props->expramsize_bytes = (uint32_t)1024 << header->expramsize;
|
||||||
|
// dprintf("ramsize_bytes: %ld\n", props->ramsize_bytes);
|
||||||
|
if(props->ramsize_bytes > 32768 || props->ramsize_bytes < 2048) {
|
||||||
|
props->ramsize_bytes = 0;
|
||||||
|
}
|
||||||
|
// dprintf("ramsize_bytes: %ld\n", props->ramsize_bytes);
|
||||||
|
f_lseek(&file_handle, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t smc_headerscore(snes_header_t* header) {
|
||||||
|
uint8_t score=0;
|
||||||
|
score += countAllASCII(header->maker, sizeof(header->maker));
|
||||||
|
score += countAllASCII(header->gamecode, sizeof(header->gamecode));
|
||||||
|
score += isFixed(header->fixed_00, sizeof(header->fixed_00), 0x00);
|
||||||
|
score += countAllJISX0201(header->name, sizeof(header->name));
|
||||||
|
score += 3*isFixed(&header->fixed_33, sizeof(header->fixed_33), 0x33);
|
||||||
|
score += checkChksum(header->cchk, header->chk);
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
|
||||||
62
mk1-src/smc.h
Normal file
62
mk1-src/smc.h
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
/* sd2snes - SD card based universal cartridge for the SNES
|
||||||
|
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
|
||||||
|
AVR firmware portion
|
||||||
|
|
||||||
|
Inspired by and based on code from sd2iec, written by Ingo Korb et al.
|
||||||
|
See sdcard.c|h, config.h.
|
||||||
|
|
||||||
|
FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
|
||||||
|
see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
smc.h: SMC file structures
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SMC_H
|
||||||
|
#define SMC_H
|
||||||
|
|
||||||
|
typedef struct _snes_header {
|
||||||
|
uint8_t maker[2]; // 0xB0
|
||||||
|
uint8_t gamecode[4]; // 0xB2
|
||||||
|
uint8_t fixed_00[7]; // 0xB6
|
||||||
|
uint8_t expramsize; // 0xBD
|
||||||
|
uint8_t specver; // 0xBE
|
||||||
|
uint8_t carttype2; // 0xBF
|
||||||
|
uint8_t name[21]; // 0xC0
|
||||||
|
uint8_t map; // 0xD5
|
||||||
|
uint8_t carttype; // 0xD6
|
||||||
|
uint8_t romsize; // 0xD7
|
||||||
|
uint8_t ramsize; // 0xD8
|
||||||
|
uint8_t destcode; // 0xD9
|
||||||
|
uint8_t fixed_33; // 0xDA
|
||||||
|
uint8_t ver; // 0xDB
|
||||||
|
uint16_t cchk; // 0xDC
|
||||||
|
uint16_t chk; // 0xDE
|
||||||
|
} snes_header_t;
|
||||||
|
|
||||||
|
typedef struct _snes_romprops {
|
||||||
|
uint16_t offset; // start of actual ROM image
|
||||||
|
uint8_t mapper_id; // FPGA mapper
|
||||||
|
uint8_t pad1; // for alignment
|
||||||
|
uint32_t expramsize_bytes; // ExpRAM size in bytes
|
||||||
|
uint32_t ramsize_bytes; // CartRAM size in bytes
|
||||||
|
uint32_t romsize_bytes; // ROM size in bytes (rounded up)
|
||||||
|
snes_header_t header; // original header from ROM image
|
||||||
|
} snes_romprops_t;
|
||||||
|
|
||||||
|
void smc_id(snes_romprops_t*);
|
||||||
|
uint8_t smc_headerscore(snes_header_t*);
|
||||||
|
|
||||||
|
#endif
|
||||||
146
mk1-src/snes.c
Normal file
146
mk1-src/snes.c
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
/* sd2snes - SD card based universal cartridge for the SNES
|
||||||
|
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
|
||||||
|
AVR firmware portion
|
||||||
|
|
||||||
|
Inspired by and based on code from sd2iec, written by Ingo Korb et al.
|
||||||
|
See sdcard.c|h, config.h.
|
||||||
|
|
||||||
|
FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
|
||||||
|
see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
snes.c: SNES hardware control and monitoring
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include "avrcompat.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "uart.h"
|
||||||
|
#include "snes.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "fileops.h"
|
||||||
|
#include "ff.h"
|
||||||
|
#include "led.h"
|
||||||
|
#include "smc.h"
|
||||||
|
|
||||||
|
uint8_t initloop=1;
|
||||||
|
uint32_t saveram_crc, saveram_crc_old;
|
||||||
|
void snes_init() {
|
||||||
|
DDRD |= _BV(PD5); // PD5 = RESET_DIR
|
||||||
|
DDRD |= _BV(PD6); // PD6 = RESET
|
||||||
|
snes_reset(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sets the SNES reset state.
|
||||||
|
*
|
||||||
|
* state: put SNES in reset state when 1, release when 0
|
||||||
|
*/
|
||||||
|
void snes_reset(int state) {
|
||||||
|
if(state) {
|
||||||
|
DDRD |= _BV(PD6); // /RESET pin -> out
|
||||||
|
PORTD &= ~_BV(PD6); // /RESET = 0
|
||||||
|
PORTD |= _BV(PD5); // RESET_DIR = 1;
|
||||||
|
} else {
|
||||||
|
PORTD &= ~_BV(PD5); // RESET_DIR = 0;
|
||||||
|
DDRD &= ~_BV(PD6); // /RESET pin -> in
|
||||||
|
PORTD |= _BV(PD6); // /RESET = pullup
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* gets the SNES reset state.
|
||||||
|
*
|
||||||
|
* returns: 1 when reset, 0 when not reset
|
||||||
|
*/
|
||||||
|
uint8_t get_snes_reset() {
|
||||||
|
// DDRD &= ~_BV(PD6); // /RESET pin -> in
|
||||||
|
// PORTD &= ~_BV(PD5); // RESET_DIR (external buffer) = 0
|
||||||
|
return !(PIND & _BV(PD6));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SD2SNES main loop.
|
||||||
|
* monitors SRAM changes and other things
|
||||||
|
*/
|
||||||
|
uint32_t diffcount = 0, samecount = 0, didnotsave = 0;
|
||||||
|
uint8_t sram_valid = 0;
|
||||||
|
void snes_main_loop() {
|
||||||
|
if(!romprops.ramsize_bytes)return;
|
||||||
|
if(initloop) {
|
||||||
|
saveram_crc_old = calc_sram_crc(SRAM_SAVE_ADDR, romprops.ramsize_bytes);
|
||||||
|
initloop=0;
|
||||||
|
}
|
||||||
|
saveram_crc = calc_sram_crc(SRAM_SAVE_ADDR, romprops.ramsize_bytes);
|
||||||
|
sram_valid = sram_reliable();
|
||||||
|
if(crc_valid && sram_valid) {
|
||||||
|
if(saveram_crc != saveram_crc_old) {
|
||||||
|
if(samecount) {
|
||||||
|
diffcount=1;
|
||||||
|
} else {
|
||||||
|
diffcount++;
|
||||||
|
didnotsave++;
|
||||||
|
}
|
||||||
|
samecount=0;
|
||||||
|
}
|
||||||
|
if(saveram_crc == saveram_crc_old) {
|
||||||
|
samecount++;
|
||||||
|
}
|
||||||
|
if(diffcount>=1 && samecount==5) {
|
||||||
|
uart_putc('U');
|
||||||
|
uart_puthexshort(saveram_crc);
|
||||||
|
uart_putcrlf();
|
||||||
|
set_busy_led(1);
|
||||||
|
save_sram(file_lfn, romprops.ramsize_bytes, SRAM_SAVE_ADDR);
|
||||||
|
set_busy_led(0);
|
||||||
|
didnotsave=0;
|
||||||
|
}
|
||||||
|
if(didnotsave>50) {
|
||||||
|
diffcount=0;
|
||||||
|
uart_putc('V');
|
||||||
|
set_busy_led(1);
|
||||||
|
save_sram(file_lfn, romprops.ramsize_bytes, SRAM_SAVE_ADDR);
|
||||||
|
didnotsave=0;
|
||||||
|
set_busy_led(0);
|
||||||
|
}
|
||||||
|
saveram_crc_old = saveram_crc;
|
||||||
|
}
|
||||||
|
dprintf("crc_valid=%d sram_valid=%d diffcount=%ld samecount=%ld, didnotsave=%ld\n", crc_valid, sram_valid, diffcount, samecount, didnotsave);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SD2SNES menu loop.
|
||||||
|
* monitors menu selection. return when selection was made.
|
||||||
|
*/
|
||||||
|
uint8_t menu_main_loop() {
|
||||||
|
uint8_t cmd = 0;
|
||||||
|
sram_writebyte(0, SRAM_CMD_ADDR);
|
||||||
|
while(!cmd) {
|
||||||
|
if(!get_snes_reset()) {
|
||||||
|
while(!sram_reliable());
|
||||||
|
cmd = sram_readbyte(SRAM_CMD_ADDR);
|
||||||
|
}
|
||||||
|
if(get_snes_reset()) {
|
||||||
|
cmd = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_selected_name(uint8_t* fn) {
|
||||||
|
uint32_t addr = sram_readlong(SRAM_FD_ADDR);
|
||||||
|
dprintf("fd addr=%lX\n", addr);
|
||||||
|
sram_readblock(fn, addr+0x41+SRAM_MENU_ADDR, 256);
|
||||||
|
}
|
||||||
37
mk1-src/snes.h
Normal file
37
mk1-src/snes.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/* sd2snes - SD card based universal cartridge for the SNES
|
||||||
|
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
|
||||||
|
AVR firmware portion
|
||||||
|
|
||||||
|
Inspired by and based on code from sd2iec, written by Ingo Korb et al.
|
||||||
|
See sdcard.c|h, config.h.
|
||||||
|
|
||||||
|
FAT file system access based on code by ChaN, Jim Brain, Ingo Korb,
|
||||||
|
see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
snes.h: SNES hardware control and monitoring
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SNES_H
|
||||||
|
#define SNES_H
|
||||||
|
uint8_t crc_valid;
|
||||||
|
|
||||||
|
void snes_init(void);
|
||||||
|
void snes_reset(int state);
|
||||||
|
uint8_t get_snes_reset(void);
|
||||||
|
void snes_main_loop(void);
|
||||||
|
uint8_t menu_main_loop(void);
|
||||||
|
void get_selected_name(uint8_t* lfn);
|
||||||
|
#endif
|
||||||
136
mk1-src/spi.c
Normal file
136
mk1-src/spi.c
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
/* sd2snes - SD card based universal cartridge for the SNES
|
||||||
|
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
|
||||||
|
This file was adapted from sd2iec, written by Ingo Korb.
|
||||||
|
Original copyright header follows:
|
||||||
|
*/
|
||||||
|
/* sd2iec - SD/MMC to Commodore serial bus interface/controller
|
||||||
|
Copyright (C) 2007-2009 Ingo Korb <ingo@akana.de>
|
||||||
|
|
||||||
|
Inspiration and low-level SD/MMC access based on code from MMC2IEC
|
||||||
|
by Lars Pontoppidan et al., see sdcard.c|h and config.h.
|
||||||
|
|
||||||
|
FAT filesystem access based on code from ChaN and Jim Brain, see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
|
spi.c: Low level SPI access
|
||||||
|
|
||||||
|
Extended, optimized and cleaned version of code from MMC2IEC,
|
||||||
|
original copyright header follows:
|
||||||
|
|
||||||
|
//
|
||||||
|
// Title : SPI module
|
||||||
|
// Author : Lars Pontoppidan
|
||||||
|
// Date : January, 2007
|
||||||
|
// Version : 1.03
|
||||||
|
// Target MCU : Atmel AVR Series
|
||||||
|
//
|
||||||
|
// DESCRIPTION:
|
||||||
|
// This module implements initialization, sending and receiving bytes using
|
||||||
|
// hardware SPI on an AVR.
|
||||||
|
//
|
||||||
|
// DISCLAIMER:
|
||||||
|
// The author is in no way responsible for any problems or damage caused by
|
||||||
|
// using this code. Use at your own risk.
|
||||||
|
//
|
||||||
|
// LICENSE:
|
||||||
|
// This code is distributed under the GNU Public License
|
||||||
|
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
||||||
|
//
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// FIXME: Integrate into sdcard.c
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include "avrcompat.h"
|
||||||
|
#include "spi.h"
|
||||||
|
|
||||||
|
// access routines
|
||||||
|
void spiInit(void)
|
||||||
|
{
|
||||||
|
volatile uint8_t dummy;
|
||||||
|
|
||||||
|
// setup SPI I/O pins
|
||||||
|
SPI_PORT = (SPI_PORT & ~SPI_MASK) | SPI_SCK | SPI_SS | SPI_MISO;
|
||||||
|
SPI_DDR = (SPI_DDR & ~SPI_MASK) | SPI_SCK | SPI_SS | SPI_MOSI;
|
||||||
|
|
||||||
|
// setup SPI interface:
|
||||||
|
// interrupts disabled, SPI enabled, MSB first, master mode,
|
||||||
|
// leading edge rising, sample on leading edge, clock = f/4
|
||||||
|
SPCR = 0b01010000;
|
||||||
|
|
||||||
|
// Enable SPI double speed mode -> clock = f/2
|
||||||
|
SPSR = _BV(SPI2X);
|
||||||
|
|
||||||
|
// clear status
|
||||||
|
dummy = SPSR;
|
||||||
|
|
||||||
|
// clear receive buffer
|
||||||
|
dummy = SPDR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline uint8_t spiTransferByte(uint8_t data)
|
||||||
|
{
|
||||||
|
// send the given data
|
||||||
|
SPDR = data;
|
||||||
|
|
||||||
|
// wait for transfer to complete
|
||||||
|
loop_until_bit_is_set(SPSR, SPIF);
|
||||||
|
// *** reading of the SPSR and SPDR are crucial
|
||||||
|
// *** to the clearing of the SPIF flag
|
||||||
|
// *** in non-interrupt mode
|
||||||
|
|
||||||
|
// return the received data
|
||||||
|
return SPDR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline uint32_t spiTransferLong(const uint32_t data)
|
||||||
|
{
|
||||||
|
// It seems to be necessary to use the union in order to get efficient
|
||||||
|
// assembler code.
|
||||||
|
// Beware, endian unsafe union
|
||||||
|
union {
|
||||||
|
uint32_t l;
|
||||||
|
uint8_t c[4];
|
||||||
|
} long2char;
|
||||||
|
|
||||||
|
long2char.l = data;
|
||||||
|
|
||||||
|
// send the given data
|
||||||
|
SPDR = long2char.c[3];
|
||||||
|
// wait for transfer to complete
|
||||||
|
loop_until_bit_is_set(SPSR, SPIF);
|
||||||
|
long2char.c[3] = SPDR;
|
||||||
|
|
||||||
|
SPDR = long2char.c[2];
|
||||||
|
// wait for transfer to complete
|
||||||
|
loop_until_bit_is_set(SPSR, SPIF);
|
||||||
|
long2char.c[2] = SPDR;
|
||||||
|
|
||||||
|
SPDR = long2char.c[1];
|
||||||
|
// wait for transfer to complete
|
||||||
|
loop_until_bit_is_set(SPSR, SPIF);
|
||||||
|
long2char.c[1] = SPDR;
|
||||||
|
|
||||||
|
SPDR = long2char.c[0];
|
||||||
|
// wait for transfer to complete
|
||||||
|
loop_until_bit_is_set(SPSR, SPIF);
|
||||||
|
long2char.c[0] = SPDR;
|
||||||
|
|
||||||
|
return long2char.l;
|
||||||
|
}
|
||||||
73
mk1-src/spi.h
Normal file
73
mk1-src/spi.h
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
/* sd2snes - SD card based universal cartridge for the SNES
|
||||||
|
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
|
||||||
|
This file was adapted from sd2iec, written by Ingo Korb.
|
||||||
|
Original copyright header follows:
|
||||||
|
*/
|
||||||
|
/* sd2iec - SD/MMC to Commodore serial bus interface/controller
|
||||||
|
Copyright (C) 2007-2009 Ingo Korb <ingo@akana.de>
|
||||||
|
|
||||||
|
Inspiration and low-level SD/MMC access based on code from MMC2IEC
|
||||||
|
by Lars Pontoppidan et al., see sdcard.c|h and config.h.
|
||||||
|
|
||||||
|
FAT filesystem access based on code from ChaN and Jim Brain, see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
|
spi.h: Definitions for the low-level SPI routines
|
||||||
|
|
||||||
|
Based on original code by Lars Pontoppidan et al., see spi.c
|
||||||
|
for full copyright details.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SPI_H
|
||||||
|
#define SPI_H
|
||||||
|
|
||||||
|
// function prototypes
|
||||||
|
|
||||||
|
// SPI interface initializer
|
||||||
|
void spiInit(void);
|
||||||
|
|
||||||
|
// spiTransferByte(u08 data) waits until the SPI interface is ready
|
||||||
|
// and then sends a single byte over the SPI port. The function also
|
||||||
|
// returns the byte that was received during transmission.
|
||||||
|
uint8_t spiTransferByte(uint8_t data);
|
||||||
|
|
||||||
|
// spiTransferLong(u08 data) waits until the SPI interface is ready
|
||||||
|
// and then sends the long with MSB first over the SPI port.
|
||||||
|
uint32_t spiTransferLong(uint32_t data);
|
||||||
|
|
||||||
|
// Macros for setting slave select:
|
||||||
|
#ifdef CONFIG_TWINSD
|
||||||
|
# define SPI_SS_HIGH(card) do { \
|
||||||
|
if (card == 0) { \
|
||||||
|
SPI_PORT |= SPI_SS; \
|
||||||
|
} else { \
|
||||||
|
SD2_PORT |= SD2_CS; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#define SPI_SS_LOW(card) do { \
|
||||||
|
if (card == 0) { \
|
||||||
|
SPI_PORT &= (uint8_t)~SPI_SS; \
|
||||||
|
} else { \
|
||||||
|
SD2_PORT &= (uint8_t)~SD2_CS; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#else
|
||||||
|
# define SPI_SS_HIGH(card) SPI_PORT |= SPI_SS
|
||||||
|
# define SPI_SS_LOW(card) SPI_PORT &= (uint8_t)~SPI_SS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
75
mk1-src/src2doxy.pl
Executable file
75
mk1-src/src2doxy.pl
Executable file
@@ -0,0 +1,75 @@
|
|||||||
|
#!/usr/bin/perl -w -i~
|
||||||
|
|
||||||
|
# src2doxy.pl - create doxygen-compatible comments from readable C source
|
||||||
|
# Copyright (C) 2008 Ingo Korb <ingo@akana.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; version 2 of the License only.
|
||||||
|
#
|
||||||
|
# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
#
|
||||||
|
# This script parses a subset of kernel-doc style comments and rewrites
|
||||||
|
# them as something doxygen will understand.
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
my $incomment = 0;
|
||||||
|
my $inspecialcomment = 0;
|
||||||
|
my @postcomment = ();
|
||||||
|
my @outputstack;
|
||||||
|
|
||||||
|
while (<>) {
|
||||||
|
my $filename;
|
||||||
|
($filename = $ARGV) =~ s!.*/!!;
|
||||||
|
|
||||||
|
chomp;
|
||||||
|
s/\r$//;
|
||||||
|
s/\s+$//;
|
||||||
|
|
||||||
|
# doxygen is too stupid to understand after-the-variable comments
|
||||||
|
# without external help. WARNING: Will substitute within strings!
|
||||||
|
s!([^ \t]\s+)/// !$1///< !;
|
||||||
|
|
||||||
|
$incomment = 1 if m!^/\*!;
|
||||||
|
if (m!^/\*\*$!) {
|
||||||
|
$inspecialcomment = 1;
|
||||||
|
# Kill output
|
||||||
|
$_ = "";
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($incomment) {
|
||||||
|
if (m!\*/$!) {
|
||||||
|
# End of comment
|
||||||
|
$incomment = 0;
|
||||||
|
$inspecialcomment = 0;
|
||||||
|
@outputstack = @postcomment;
|
||||||
|
@postcomment = ();
|
||||||
|
} elsif (/$filename:\s+(.*).?\s*$/) {
|
||||||
|
# Add file description
|
||||||
|
push @postcomment, "\n/*! \\file $ARGV\n * \\brief $1. */\n";
|
||||||
|
}
|
||||||
|
if ($inspecialcomment == 1) {
|
||||||
|
# First line of special comment: Brief description
|
||||||
|
$inspecialcomment = 2;
|
||||||
|
m/^\s*\*\s*((struct |union )?[^: \t]+):?\s+-?\s*(.*)\s*$/;
|
||||||
|
$_ = "/*! \\brief $3\n *";
|
||||||
|
} elsif ($inspecialcomment == 2) {
|
||||||
|
# Modify parameters
|
||||||
|
s/\@([^: \t]+)\s*:\s+(.*)\s*$/\\param $1 $2/;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} continue {
|
||||||
|
print "$_\n";
|
||||||
|
while (scalar(@outputstack)) {
|
||||||
|
print shift @outputstack,"\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
16
mk1-src/time.h
Normal file
16
mk1-src/time.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#ifndef TIME_H
|
||||||
|
#define TIME_H
|
||||||
|
|
||||||
|
typedef uint32_t time_t;
|
||||||
|
struct tm {
|
||||||
|
uint8_t tm_sec; // 0..59
|
||||||
|
uint8_t tm_min; // 0..59
|
||||||
|
uint8_t tm_hour; // 0..23
|
||||||
|
uint8_t tm_mday; // 1..[28..31]
|
||||||
|
uint8_t tm_mon; // 0..11
|
||||||
|
uint8_t tm_year; // since 1900, i.e. 2000 is 100
|
||||||
|
uint8_t tm_wday; // 0 to 6, sunday is 6
|
||||||
|
// A Unix struct tm has a few more fields we don't need in this application
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* TIME_H */
|
||||||
135
mk1-src/timer.c
Normal file
135
mk1-src/timer.c
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
/* sd2snes - SD card based universal cartridge for the SNES
|
||||||
|
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
|
||||||
|
This file was adapted from sd2iec, written by Ingo Korb.
|
||||||
|
Original copyright header follows:
|
||||||
|
*/
|
||||||
|
/* sd2iec - SD/MMC to Commodore serial bus interface/controller
|
||||||
|
Copyright (C) 2007-2009 Ingo Korb <ingo@akana.de>
|
||||||
|
|
||||||
|
Inspiration and low-level SD/MMC access based on code from MMC2IEC
|
||||||
|
by Lars Pontoppidan et al., see sdcard.c|h and config.h.
|
||||||
|
|
||||||
|
FAT filesystem access based on code from ChaN and Jim Brain, see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
|
timer.c: System timer (and button debouncer)
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include "avrcompat.h"
|
||||||
|
#include "led.h"
|
||||||
|
#include "timer.h"
|
||||||
|
|
||||||
|
volatile tick_t ticks;
|
||||||
|
// Logical buttons
|
||||||
|
volatile uint8_t active_keys;
|
||||||
|
|
||||||
|
// Physical buttons
|
||||||
|
uint8_t buttonstate;
|
||||||
|
tick_t lastbuttonchange;
|
||||||
|
|
||||||
|
/* Called by the timer interrupt when the button state has changed */
|
||||||
|
static void buttons_changed(void) {
|
||||||
|
/* Check if the previous state was stable for two ticks */
|
||||||
|
if (time_after(ticks, lastbuttonchange+2)) {
|
||||||
|
if (active_keys & IGNORE_KEYS) {
|
||||||
|
active_keys &= ~IGNORE_KEYS;
|
||||||
|
} else if (!(buttonstate & (BUTTON_PREV|BUTTON_NEXT))) {
|
||||||
|
/* Both buttons held down */
|
||||||
|
active_keys |= KEY_HOME;
|
||||||
|
} else if (!(buttonstate & BUTTON_NEXT) &&
|
||||||
|
(BUTTON_PIN & BUTTON_NEXT)) {
|
||||||
|
/* "Next" button released */
|
||||||
|
active_keys |= KEY_NEXT;
|
||||||
|
} else if (!(buttonstate & BUTTON_PREV) &&
|
||||||
|
(BUTTON_PIN & BUTTON_NEXT)) {
|
||||||
|
active_keys |= KEY_PREV;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lastbuttonchange = ticks;
|
||||||
|
buttonstate = BUTTON_PIN & BUTTON_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The main timer interrupt */
|
||||||
|
ISR(TIMER1_COMPA_vect) {
|
||||||
|
uint8_t tmp = BUTTON_PIN & BUTTON_MASK;
|
||||||
|
|
||||||
|
if (tmp != buttonstate) {
|
||||||
|
buttons_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
ticks++;
|
||||||
|
|
||||||
|
#ifdef SINGLE_LED
|
||||||
|
if (led_state & LED_ERROR) {
|
||||||
|
if ((ticks & 15) == 0)
|
||||||
|
DIRTY_LED_PORT ^= DIRTY_LED_BIT();
|
||||||
|
} else {
|
||||||
|
if ((led_state & LED_BUSY) || (led_state & LED_DIRTY)) {
|
||||||
|
DIRTY_LED_ON();
|
||||||
|
} else {
|
||||||
|
DIRTY_LED_OFF();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (led_state & LED_ERROR)
|
||||||
|
if ((ticks & 15) == 0)
|
||||||
|
DIRTY_LED_PORT ^= DIRTY_LED_BIT();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Sleep button triggers when held down for 2sec */
|
||||||
|
if (time_after(ticks, lastbuttonchange+2)) {
|
||||||
|
if (!(buttonstate & BUTTON_NEXT) &&
|
||||||
|
(buttonstate & BUTTON_PREV) &&
|
||||||
|
time_after(ticks, lastbuttonchange+2*HZ) &&
|
||||||
|
!key_pressed(KEY_SLEEP)) {
|
||||||
|
/* Set ignore flag so the release doesn't trigger KEY_NEXT */
|
||||||
|
active_keys |= KEY_SLEEP | IGNORE_KEYS;
|
||||||
|
/* Avoid triggering for the next two seconds */
|
||||||
|
lastbuttonchange = ticks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if CONFIG_RTC_VARIANT == 1
|
||||||
|
increment_rtc();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_REMOTE_DISPLAY
|
||||||
|
/* Check if the display wants to be queried */
|
||||||
|
if (!(SOFTI2C_PIN & _BV(SOFTI2C_BIT_INTRQ))) {
|
||||||
|
active_keys |= KEY_DISPLAY;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void timer_init(void) {
|
||||||
|
/* Count F_CPU/8 in timer 0 */
|
||||||
|
TCCR0B = _BV(CS01);
|
||||||
|
|
||||||
|
/* Set up a 100Hz interrupt using timer 1 */
|
||||||
|
OCR1A = 1249;
|
||||||
|
TCNT1 = 0;
|
||||||
|
TCCR1A = 0;
|
||||||
|
TCCR1B = _BV(WGM12) | _BV(CS10) | _BV(CS11);
|
||||||
|
TIMSK1 |= _BV(OCIE1A);
|
||||||
|
|
||||||
|
/* Buttons */
|
||||||
|
BUTTON_DDR &= (uint8_t)~BUTTON_MASK;
|
||||||
|
BUTTON_PORT |= BUTTON_MASK;
|
||||||
|
}
|
||||||
121
mk1-src/timer.h
Normal file
121
mk1-src/timer.h
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
/* sd2snes - SD card based universal cartridge for the SNES
|
||||||
|
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
|
||||||
|
This file was adapted from sd2iec, written by Ingo Korb.
|
||||||
|
Original copyright header follows:
|
||||||
|
*/
|
||||||
|
/* sd2iec - SD/MMC to Commodore serial bus interface/controller
|
||||||
|
Copyright (C) 2007-2009 Ingo Korb <ingo@akana.de>
|
||||||
|
|
||||||
|
Inspiration and low-level SD/MMC access based on code from MMC2IEC
|
||||||
|
by Lars Pontoppidan et al., see sdcard.c|h and config.h.
|
||||||
|
|
||||||
|
FAT filesystem access based on code from ChaN and Jim Brain, see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
|
timer.h: System timer (and button-debouncer)
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TIMER_H
|
||||||
|
#define TIMER_H
|
||||||
|
|
||||||
|
#include <util/atomic.h>
|
||||||
|
|
||||||
|
// Bit masks for the (simulated) keys
|
||||||
|
#define KEY_NEXT (1<<0)
|
||||||
|
#define KEY_PREV (1<<1)
|
||||||
|
#define KEY_HOME (1<<2)
|
||||||
|
#define KEY_SLEEP (1<<3)
|
||||||
|
/* Remote display service request */
|
||||||
|
#define KEY_DISPLAY (1<<4)
|
||||||
|
|
||||||
|
#define IGNORE_KEYS (1<<7)
|
||||||
|
|
||||||
|
/// Logical keys that were pressed - must be reset by the reader.
|
||||||
|
extern volatile uint8_t active_keys;
|
||||||
|
|
||||||
|
#define key_pressed(x) (active_keys & (x))
|
||||||
|
#define reset_key(x) active_keys &= (uint8_t)~(x)
|
||||||
|
#define ignore_keys() active_keys = IGNORE_KEYS;
|
||||||
|
|
||||||
|
typedef uint16_t tick_t;
|
||||||
|
|
||||||
|
/// Global timing variable, 100 ticks per second
|
||||||
|
/// Use atomic access or getticks() !
|
||||||
|
extern volatile tick_t ticks;
|
||||||
|
#define HZ 100
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getticks - return the current system tick count
|
||||||
|
*
|
||||||
|
* This inline function returns the current system tick count.
|
||||||
|
*/
|
||||||
|
static inline tick_t getticks(void) {
|
||||||
|
tick_t tmp;
|
||||||
|
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
|
||||||
|
tmp = ticks;
|
||||||
|
}
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MS_TO_TICKS(x) (x/10)
|
||||||
|
|
||||||
|
/* Adapted from Linux 2.6 include/linux/jiffies.h:
|
||||||
|
*
|
||||||
|
* These inlines deal with timer wrapping correctly. You are
|
||||||
|
* strongly encouraged to use them
|
||||||
|
* 1. Because people otherwise forget
|
||||||
|
* 2. Because if the timer wrap changes in future you won't have to
|
||||||
|
* alter your driver code.
|
||||||
|
*
|
||||||
|
* time_after(a,b) returns true if the time a is after time b.
|
||||||
|
*
|
||||||
|
* Do this with "<0" and ">=0" to only test the sign of the result. A
|
||||||
|
* good compiler would generate better code (and a really good compiler
|
||||||
|
* wouldn't care). Gcc is currently neither.
|
||||||
|
* (">=0" refers to the time_after_eq macro which wasn't copied)
|
||||||
|
*/
|
||||||
|
#define time_after(a,b) \
|
||||||
|
((int16_t)(b) - (int16_t)(a) < 0)
|
||||||
|
#define time_before(a,b) time_after(b,a)
|
||||||
|
|
||||||
|
|
||||||
|
/// Calculate timer start value for given timeout in microseconds
|
||||||
|
#define TIMEOUT_US(x) (256-((float)F_CPU/10000000.0)*x)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* start_timeout - start a timeout using timer0
|
||||||
|
* @startval: starting value for timer
|
||||||
|
*
|
||||||
|
* This function sets timer 0 to the specified value and clears its overflow
|
||||||
|
* flag. Use in conjunction with TIMEOUT_US to cause a timer overflow after
|
||||||
|
* a specified number of microseconds. DON'T use a variable as a parameter to
|
||||||
|
* the TIMEOUT_US macro because that would require run-time float calculations.
|
||||||
|
*/
|
||||||
|
#define start_timeout(startval) do { TCNT0 = startval; TIFR0 |= _BV(TOV0); } while (0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* has_timed_out - returns true if timeout was reached
|
||||||
|
*
|
||||||
|
* This function returns true if the overflow flag of timer 0 is set which
|
||||||
|
* (together with start_timeout and TIMEOUT_US) will happen when the
|
||||||
|
* specified time has elapsed.
|
||||||
|
*/
|
||||||
|
#define has_timed_out() (TIFR0 & _BV(TOV0))
|
||||||
|
|
||||||
|
void timer_init(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
187
mk1-src/uart.c
Normal file
187
mk1-src/uart.c
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
/* sd2snes - SD card based universal cartridge for the SNES
|
||||||
|
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
|
||||||
|
This file was adapted from sd2iec, written by Ingo Korb.
|
||||||
|
Original copyright header follows:
|
||||||
|
*/
|
||||||
|
/* sd2iec - SD/MMC to Commodore serial bus interface/controller
|
||||||
|
Copyright (C) 2007-2009 Ingo Korb <ingo@akana.de>
|
||||||
|
|
||||||
|
Inspiration and low-level SD/MMC access based on code from MMC2IEC
|
||||||
|
by Lars Pontoppidan et al., see sdcard.c|h and config.h.
|
||||||
|
|
||||||
|
FAT filesystem access based on code from ChaN and Jim Brain, see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
|
uart.c: UART access routines
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "config.h"
|
||||||
|
#include "avrcompat.h"
|
||||||
|
#include "uart.h"
|
||||||
|
|
||||||
|
static uint8_t txbuf[1 << CONFIG_UART_BUF_SHIFT];
|
||||||
|
static volatile uint16_t read_idx;
|
||||||
|
static volatile uint16_t write_idx;
|
||||||
|
|
||||||
|
ISR(USART_UDRE_vect) {
|
||||||
|
if (read_idx == write_idx) return;
|
||||||
|
UDR = txbuf[read_idx];
|
||||||
|
read_idx = (read_idx+1) & (sizeof(txbuf)-1);
|
||||||
|
if (read_idx == write_idx)
|
||||||
|
UCSRB &= ~ _BV(UDRIE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart_putc(char c) {
|
||||||
|
uint16_t t=(write_idx+1) & (sizeof(txbuf)-1);
|
||||||
|
#ifndef CONFIG_DEADLOCK_ME_HARDER // :-)
|
||||||
|
UCSRB &= ~ _BV(UDRIE); // turn off RS232 irq
|
||||||
|
#else
|
||||||
|
while (t == read_idx); // wait for free space
|
||||||
|
#endif
|
||||||
|
txbuf[write_idx] = c;
|
||||||
|
write_idx = t;
|
||||||
|
//if (read_idx == write_idx) PORTD |= _BV(PD7);
|
||||||
|
UCSRB |= _BV(UDRIE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart_puthex(uint8_t num) {
|
||||||
|
uint8_t tmp;
|
||||||
|
tmp = (num & 0xf0) >> 4;
|
||||||
|
if (tmp < 10)
|
||||||
|
uart_putc('0'+tmp);
|
||||||
|
else
|
||||||
|
uart_putc('a'+tmp-10);
|
||||||
|
|
||||||
|
tmp = num & 0x0f;
|
||||||
|
if (tmp < 10)
|
||||||
|
uart_putc('0'+tmp);
|
||||||
|
else
|
||||||
|
uart_putc('a'+tmp-10);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart_puthexlong(uint32_t num) {
|
||||||
|
uart_puthex((num>>24)&0xff);
|
||||||
|
uart_puthex((num>>16)&0xff);
|
||||||
|
uart_puthex((num>>8)&0xff);
|
||||||
|
uart_puthex(num&0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart_puthexshort(uint16_t num) {
|
||||||
|
uart_puthex((num>>8)&0xff);
|
||||||
|
uart_puthex(num&0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void uart_trace(void *ptr, uint16_t start, uint16_t len) {
|
||||||
|
uint16_t i;
|
||||||
|
uint8_t j;
|
||||||
|
uint8_t ch;
|
||||||
|
uint8_t *data = ptr;
|
||||||
|
|
||||||
|
data+=start;
|
||||||
|
for(i=0;i<len;i+=16) {
|
||||||
|
|
||||||
|
uart_puthex(start>>8);
|
||||||
|
uart_puthex(start&0xff);
|
||||||
|
uart_putc('|');
|
||||||
|
uart_putc(' ');
|
||||||
|
for(j=0;j<16;j++) {
|
||||||
|
if(i+j<len) {
|
||||||
|
ch=*(data + j);
|
||||||
|
uart_puthex(ch);
|
||||||
|
} else {
|
||||||
|
uart_putc(' ');
|
||||||
|
uart_putc(' ');
|
||||||
|
}
|
||||||
|
uart_putc(' ');
|
||||||
|
}
|
||||||
|
uart_putc('|');
|
||||||
|
for(j=0;j<16;j++) {
|
||||||
|
if(i+j<len) {
|
||||||
|
ch=*(data++);
|
||||||
|
if(ch<32 || ch>0x7e)
|
||||||
|
ch='.';
|
||||||
|
uart_putc(ch);
|
||||||
|
} else {
|
||||||
|
uart_putc(' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uart_putc('|');
|
||||||
|
uart_putcrlf();
|
||||||
|
start+=16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ioputc(char c, FILE *stream) {
|
||||||
|
if (c == '\n') uart_putc('\r');
|
||||||
|
uart_putc(c);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t uart_getc(void) {
|
||||||
|
loop_until_bit_is_set(UCSRA,RXC);
|
||||||
|
return UDR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart_flush(void) {
|
||||||
|
while (read_idx != write_idx) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart_puts_P(prog_char *text) {
|
||||||
|
uint8_t ch;
|
||||||
|
|
||||||
|
while ((ch = pgm_read_byte(text++))) {
|
||||||
|
uart_putc(ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart_putcrlf(void) {
|
||||||
|
uart_putc(13);
|
||||||
|
uart_putc(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
static FILE mystdout = FDEV_SETUP_STREAM(ioputc, NULL, _FDEV_SETUP_WRITE);
|
||||||
|
|
||||||
|
void uart_init(void) {
|
||||||
|
/* Seriellen Port konfigurieren */
|
||||||
|
|
||||||
|
/* UBRRH = (int)((double)F_CPU/(16.0*CONFIG_UART_BAUDRATE)-1) >> 8;
|
||||||
|
UBRRL = (int)((double)F_CPU/(16.0*CONFIG_UART_BAUDRATE)-1) & 0xff;*/
|
||||||
|
|
||||||
|
UBRRH = (int)((double)F_CPU/(8.0*CONFIG_UART_BAUDRATE)-1) >> 8;
|
||||||
|
UBRRL = (int)((double)F_CPU/(8.0*CONFIG_UART_BAUDRATE)-1) & 0xff;
|
||||||
|
|
||||||
|
UCSRA |= _BV(U2X0);
|
||||||
|
|
||||||
|
UCSRB = _BV(RXEN) | _BV(TXEN);
|
||||||
|
// I really don't like random #ifdefs in the code =(
|
||||||
|
#if defined __AVR_ATmega32__
|
||||||
|
UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0);
|
||||||
|
#else
|
||||||
|
UCSRC = _BV(UCSZ1) | _BV(UCSZ0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
stdout = &mystdout;
|
||||||
|
|
||||||
|
//UCSRB |= _BV(UDRIE);
|
||||||
|
read_idx = 0;
|
||||||
|
write_idx = 0;
|
||||||
|
}
|
||||||
66
mk1-src/uart.h
Normal file
66
mk1-src/uart.h
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
/* sd2snes - SD card based universal cartridge for the SNES
|
||||||
|
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
|
||||||
|
This file was adapted from sd2iec, written by Ingo Korb.
|
||||||
|
Original copyright header follows:
|
||||||
|
*/
|
||||||
|
/* sd2iec - SD/MMC to Commodore serial bus interface/controller
|
||||||
|
Copyright (C) 2007-2009 Ingo Korb <ingo@akana.de>
|
||||||
|
|
||||||
|
Inspiration and low-level SD/MMC access based on code from MMC2IEC
|
||||||
|
by Lars Pontoppidan et al., see sdcard.c|h and config.h.
|
||||||
|
|
||||||
|
FAT filesystem access based on code from ChaN and Jim Brain, see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
|
uart.h: Definitions for the UART access routines
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef UART_H
|
||||||
|
#define UART_H
|
||||||
|
|
||||||
|
#ifdef CONFIG_UART_DEBUG
|
||||||
|
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
|
||||||
|
void uart_init(void);
|
||||||
|
unsigned char uart_getc(void);
|
||||||
|
void uart_putc(char c);
|
||||||
|
void uart_puthex(uint8_t num);
|
||||||
|
void uart_puthexlong(uint32_t num);
|
||||||
|
void uart_puthexshort(uint16_t num);
|
||||||
|
void uart_trace(void *ptr, uint16_t start, uint16_t len);
|
||||||
|
void uart_flush(void);
|
||||||
|
void uart_puts_P(prog_char *text);
|
||||||
|
void uart_putcrlf(void);
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#define dprintf(str,...) printf_P(PSTR(str), ##__VA_ARGS__)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define uart_init() do {} while(0)
|
||||||
|
#define uart_getc() 0
|
||||||
|
#define uart_putc(x) do {} while(0)
|
||||||
|
#define uart_puthex(x) do {} while(0)
|
||||||
|
#define uart_flush() do {} while(0)
|
||||||
|
#define uart_puts_P(x) do {} while(0)
|
||||||
|
#define uart_putcrlf() do {} while(0)
|
||||||
|
#define uart_trace(a,b,c) do {} while(0)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
47
mk1-src/ustring.h
Normal file
47
mk1-src/ustring.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/* sd2snes - SD card based universal cartridge for the SNES
|
||||||
|
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
|
||||||
|
This file was adapted from sd2iec, written by Ingo Korb.
|
||||||
|
Original copyright header follows:
|
||||||
|
*/
|
||||||
|
/* sd2iec - SD/MMC to Commodore serial bus interface/controller
|
||||||
|
Copyright (C) 2007-2009 Ingo Korb <ingo@akana.de>
|
||||||
|
|
||||||
|
Inspiration and low-level SD/MMC access based on code from MMC2IEC
|
||||||
|
by Lars Pontoppidan et al., see sdcard.c|h and config.h.
|
||||||
|
|
||||||
|
FAT filesystem access based on code from ChaN and Jim Brain, see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
|
ustring.h: uint8_t wrappers for string.h-functions
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef USTRING_H
|
||||||
|
#define USTRING_H
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define ustrcasecmp_P(s1,s2) (strcasecmp_P((char *)(s1), (s2)))
|
||||||
|
#define ustrchr(s,c) ((uint8_t *)strchr((char *)(s), (c)))
|
||||||
|
#define ustrcmp(s1,s2) (strcmp((char *)(s1), (char *)(s2)))
|
||||||
|
#define ustrcmp_P(s1,s2) (strcmp_P((char *)(s1), (s2)))
|
||||||
|
#define ustrcpy(s1,s2) (strcpy((char *)(s1), (char *)(s2)))
|
||||||
|
#define ustrcpy_P(s1,s2) (strcpy_P((char *)(s1), (s2)))
|
||||||
|
#define ustrncpy(s1,s2,n) (strncpy((char *)(s1), (char *)(s2),(n)))
|
||||||
|
#define ustrlen(s) (strlen((char *)(s)))
|
||||||
|
#define ustrrchr(s,c) ((uint8_t *)strrchr((char *)(s), (c)))
|
||||||
|
|
||||||
|
#endif
|
||||||
82
mk1-src/utils.c
Normal file
82
mk1-src/utils.c
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
/* sd2snes - SD card based universal cartridge for the SNES
|
||||||
|
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
|
||||||
|
This file was adapted from sd2iec, written by Ingo Korb.
|
||||||
|
Original copyright header follows:
|
||||||
|
*/
|
||||||
|
/* sd2iec - SD/MMC to Commodore serial bus interface/controller
|
||||||
|
Copyright (C) 2007-2009 Ingo Korb <ingo@akana.de>
|
||||||
|
|
||||||
|
Inspiration and low-level SD/MMC access based on code from MMC2IEC
|
||||||
|
by Lars Pontoppidan et al., see sdcard.c|h and config.h.
|
||||||
|
|
||||||
|
FAT filesystem access based on code from ChaN and Jim Brain, see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
|
utils.c: Misc. utility functions that didn't fit elsewhere
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "ustring.h"
|
||||||
|
|
||||||
|
uint8_t *appendnumber(uint8_t *msg, uint8_t value) {
|
||||||
|
if (value >= 100) {
|
||||||
|
*msg++ = '0' + value/100;
|
||||||
|
value %= 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
*msg++ = '0' + value/10;
|
||||||
|
*msg++ = '0' + value%10;
|
||||||
|
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert a one-byte BCD value to a normal integer */
|
||||||
|
uint8_t bcd2int(uint8_t value) {
|
||||||
|
return (value & 0x0f) + 10*(value >> 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert a uint8_t into a BCD value */
|
||||||
|
uint8_t int2bcd(uint8_t value) {
|
||||||
|
return (value % 10) + 16*(value/10);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Similiar to strtok_r, but only a single delimiting character */
|
||||||
|
uint8_t *ustr1tok(uint8_t *str, const uint8_t delim, uint8_t **saveptr) {
|
||||||
|
uint8_t *tmp;
|
||||||
|
|
||||||
|
if (str == NULL)
|
||||||
|
str = *saveptr;
|
||||||
|
|
||||||
|
/* Skip leading delimiters */
|
||||||
|
while (*str == delim) str++;
|
||||||
|
|
||||||
|
/* If there is anything left... */
|
||||||
|
if (*str) {
|
||||||
|
/* Search for the next delimiter */
|
||||||
|
tmp = str;
|
||||||
|
while (*tmp && *tmp != delim) tmp++;
|
||||||
|
|
||||||
|
/* Terminate the string there */
|
||||||
|
if (*tmp != 0)
|
||||||
|
*tmp++ = 0;
|
||||||
|
|
||||||
|
*saveptr = tmp;
|
||||||
|
|
||||||
|
return str;
|
||||||
|
} else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
57
mk1-src/utils.h
Normal file
57
mk1-src/utils.h
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/* sd2snes - SD card based universal cartridge for the SNES
|
||||||
|
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
|
||||||
|
This file was adapted from sd2iec, written by Ingo Korb.
|
||||||
|
Original copyright header follows:
|
||||||
|
*/
|
||||||
|
/* sd2iec - SD/MMC to Commodore serial bus interface/controller
|
||||||
|
Copyright (C) 2007-2009 Ingo Korb <ingo@akana.de>
|
||||||
|
|
||||||
|
Inspiration and low-level SD/MMC access based on code from MMC2IEC
|
||||||
|
by Lars Pontoppidan et al., see sdcard.c|h and config.h.
|
||||||
|
|
||||||
|
FAT filesystem access based on code from ChaN and Jim Brain, see ff.c|h.
|
||||||
|
|
||||||
|
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; version 2 of the License only.
|
||||||
|
|
||||||
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
|
utils.c: Misc. utility functions that didn't fit elsewhere
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef UTILS_H
|
||||||
|
#define UTILS_H
|
||||||
|
|
||||||
|
/* Side-effect safe min/max */
|
||||||
|
#define max(a,b) \
|
||||||
|
({ typeof (a) _a = (a); \
|
||||||
|
typeof (b) _b = (b); \
|
||||||
|
_a > _b ? _a : _b; })
|
||||||
|
|
||||||
|
#define min(a,b) \
|
||||||
|
({ typeof (a) _a = (a); \
|
||||||
|
typeof (b) _b = (b); \
|
||||||
|
_a < _b ? _a : _b; })
|
||||||
|
|
||||||
|
|
||||||
|
/* Write a number to a string as ASCII */
|
||||||
|
uint8_t *appendnumber(uint8_t *msg, uint8_t value);
|
||||||
|
|
||||||
|
/* Convert between integer and BCD */
|
||||||
|
uint8_t bcd2int(uint8_t value);
|
||||||
|
uint8_t int2bcd(uint8_t value);
|
||||||
|
|
||||||
|
/* Tokenize a string like strtok_r, but with a single delimiter character only */
|
||||||
|
uint8_t *ustr1tok(uint8_t *str, const uint8_t delim, uint8_t **saveptr);
|
||||||
|
|
||||||
|
#endif
|
||||||
BIN
pcb/DIL-Labels.sch
Normal file
BIN
pcb/DIL-Labels.sch
Normal file
Binary file not shown.
BIN
pcb/breakout1.brd
Normal file
BIN
pcb/breakout1.brd
Normal file
Binary file not shown.
BIN
pcb/breakout2.brd
Normal file
BIN
pcb/breakout2.brd
Normal file
Binary file not shown.
BIN
pcb/breakout2.sch
Normal file
BIN
pcb/breakout2.sch
Normal file
Binary file not shown.
BIN
pcb/breakouts1-old.brd
Normal file
BIN
pcb/breakouts1-old.brd
Normal file
Binary file not shown.
BIN
pcb/cart/sd2snes1.brd
Normal file
BIN
pcb/cart/sd2snes1.brd
Normal file
Binary file not shown.
BIN
pcb/cart/sd2snes1.sch
Normal file
BIN
pcb/cart/sd2snes1.sch
Normal file
Binary file not shown.
BIN
pcb/cart/sd2snes17.brd
Normal file
BIN
pcb/cart/sd2snes17.brd
Normal file
Binary file not shown.
BIN
pcb/cart/sd2snes17.sch
Normal file
BIN
pcb/cart/sd2snes17.sch
Normal file
Binary file not shown.
BIN
pcb/cart/sd2snes18.brd
Normal file
BIN
pcb/cart/sd2snes18.brd
Normal file
Binary file not shown.
BIN
pcb/cart/sd2snes18.sch
Normal file
BIN
pcb/cart/sd2snes18.sch
Normal file
Binary file not shown.
BIN
pcb/cart/sd2snes19.brd
Normal file
BIN
pcb/cart/sd2snes19.brd
Normal file
Binary file not shown.
BIN
pcb/cart/sd2snes19.sch
Normal file
BIN
pcb/cart/sd2snes19.sch
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user