Compare commits
55 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
481237636c | ||
|
|
a79a538560 | ||
|
|
da2386e453 | ||
|
|
b8f4c9b584 | ||
|
|
d7ad740843 | ||
|
|
2d89eb8000 | ||
|
|
d139fdb40c | ||
|
|
059966f06a | ||
|
|
3243143c39 | ||
|
|
a50522b4e9 | ||
|
|
eefcc712ca | ||
|
|
5a3e935a3e | ||
|
|
5f87768a14 | ||
|
|
3436ccf46a | ||
|
|
03ee71a626 | ||
|
|
b272a6fc1c | ||
|
|
afc26397b1 | ||
|
|
3506cb0ba2 | ||
|
|
52d5fc9e92 | ||
|
|
cbe30cb388 | ||
|
|
a52638b4be | ||
|
|
22fe28c624 | ||
|
|
2c14c3f925 | ||
|
|
fec9004dc1 | ||
|
|
97aef4a2d3 | ||
|
|
6d28f3fb51 | ||
|
|
1585032c5a | ||
|
|
a7c1a29f10 | ||
|
|
90b91583a1 | ||
|
|
20c2cdb961 | ||
|
|
dc01edfe9a | ||
|
|
014cf46a69 | ||
|
|
0a6c7f125b | ||
|
|
72642321a2 | ||
|
|
37a9f09a78 | ||
|
|
d65d657ff7 | ||
|
|
39b78ae91c | ||
|
|
c97278c3d6 | ||
|
|
e880fac0ba | ||
|
|
4a9d40b841 | ||
|
|
a474ccf475 | ||
|
|
e5285f8196 | ||
|
|
9943eca294 | ||
|
|
d1919c5f14 | ||
|
|
aabed6e40c | ||
|
|
d94b435511 | ||
|
|
93a12f3ca1 | ||
|
|
bd1f5215db | ||
|
|
08cace5c12 | ||
|
|
68f255d75b | ||
|
|
3fda86125c | ||
|
|
60efa60bb4 | ||
|
|
65e26cb0c3 | ||
|
|
74d9e3fe46 | ||
|
|
71f8391a7c |
24
CHANGELOG
Normal file
24
CHANGELOG
Normal file
@@ -0,0 +1,24 @@
|
||||
v0.1.1
|
||||
======
|
||||
|
||||
* initial public release
|
||||
|
||||
|
||||
v0.1.1a (bugfix release)
|
||||
========================
|
||||
|
||||
* Fixes:
|
||||
- SuperCIC pair mode was erroneously enabled in firmware binary
|
||||
- SNES menu crashed on empty database
|
||||
|
||||
|
||||
v0.1.2
|
||||
======
|
||||
|
||||
* Auto region override (eliminate "This game pak is not designed..." messages)
|
||||
* Improved mapper detection (fixes Batman vs. Joker and many PD ROMs)
|
||||
* Improved data streaming performance
|
||||
(should reduce MSU1 errors with some cards)
|
||||
* A and B buttons swapped in menu to match common key mappings
|
||||
* Fixes:
|
||||
- MSU1: Stop audio playback on end of audio file
|
||||
2
README.txt
Normal file
2
README.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
The development branch was switched over from 'master' to 'develop'.
|
||||
The master stream will be used for releases.
|
||||
@@ -1,6 +0,0 @@
|
||||
key seed: b14f4b57fd61e98
|
||||
110101111101010
|
||||
|
||||
lck seed: _9a185f11e10dec
|
||||
_10101111010100
|
||||
|
||||
230
cic/d411.pseudo
230
cic/d411.pseudo
@@ -1,230 +0,0 @@
|
||||
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
101
cic/mangle.c
@@ -1,101 +0,0 @@
|
||||
#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;
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
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
|
||||
|
||||
@@ -1,697 +0,0 @@
|
||||
#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
|
||||
@@ -1,741 +0,0 @@
|
||||
#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
|
||||
; ------------------------------------------------------------------------
|
||||
@@ -1,71 +0,0 @@
|
||||
: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
|
||||
@@ -1,726 +0,0 @@
|
||||
#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
|
||||
; ------------------------------------------------------------------------
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 192 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 188 KiB |
Binary file not shown.
@@ -1,401 +0,0 @@
|
||||
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
|
||||
@@ -64,6 +64,7 @@ processor p12f629
|
||||
; 0x4d buffer for eeprom access
|
||||
; 0x4e loop variable for longwait
|
||||
; 0x4f loop variable for wait
|
||||
; 0x5c GPIO buffer variable for pair mode allow
|
||||
; 0x5d 0: SuperCIC pair mode available flag
|
||||
; 0x5e SuperCIC pair mode detect (phase 1)
|
||||
; 0x5f SuperCIC pair mode detect (phase 2)
|
||||
@@ -90,8 +91,8 @@ isr
|
||||
clrf 0x5f ; clear pair mode detect
|
||||
bsf 0x5f, 1 ;
|
||||
clrf 0x5d ; clear pair mode available
|
||||
nop
|
||||
nop
|
||||
clrf 0x5c ; clear pair mode allow buffer
|
||||
bsf 0x5c, 3 ; assume disallow
|
||||
bsf INTCON, 7 ; re-enable interrupts (ISR will continue as main)
|
||||
goto main
|
||||
init
|
||||
@@ -296,8 +297,8 @@ swapskip
|
||||
; indirect access, no post increment, etc.
|
||||
mangle
|
||||
call mangle_lock
|
||||
nop
|
||||
nop
|
||||
movf GPIO, w ; buffer GPIO state
|
||||
movwf 0x5c ; for pair mode "transaction"
|
||||
mangle_key
|
||||
movf 0x2f, w
|
||||
movwf 0x20
|
||||
@@ -459,7 +460,7 @@ mangle_key_withskip
|
||||
;-------pair mode code-------
|
||||
bcf GPIO, 0
|
||||
movf GPIO, w
|
||||
btfss GPIO, 3
|
||||
btfss 0x5c, 3
|
||||
bsf GPIO, 0
|
||||
movwf 0x5e
|
||||
movf GPIO, w
|
||||
@@ -642,7 +643,7 @@ mangle_lock_withskip
|
||||
goto scic_pair_skip1
|
||||
btfsc 0x5f, 1
|
||||
goto scic_pair_skip2
|
||||
btfsc GPIO, 3
|
||||
btfsc 0x5c, 3
|
||||
goto scic_pair_skip3
|
||||
goto supercic_pairmode
|
||||
scic_pair_skip1
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
Before Width: | Height: | Size: 237 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 16 KiB |
@@ -1,357 +0,0 @@
|
||||
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
BIN
gfx/logo.chi
Binary file not shown.
BIN
gfx/logo_v2.chi
BIN
gfx/logo_v2.chi
Binary file not shown.
Binary file not shown.
BIN
gfx/sd2snes.pal
BIN
gfx/sd2snes.pal
Binary file not shown.
BIN
gfx/sd2snes.psd
BIN
gfx/sd2snes.psd
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
lbr/cy62167.lbr
BIN
lbr/cy62167.lbr
Binary file not shown.
BIN
lbr/lm1117.lbr
BIN
lbr/lm1117.lbr
Binary file not shown.
BIN
lbr/misc-74.lbr
BIN
lbr/misc-74.lbr
Binary file not shown.
BIN
lbr/sdcard.lbr
BIN
lbr/sdcard.lbr
Binary file not shown.
BIN
lbr/snescart.lbr
BIN
lbr/snescart.lbr
Binary file not shown.
339
misc/igr/COPYING
339
misc/igr/COPYING
@@ -1,339 +0,0 @@
|
||||
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.
|
||||
@@ -1,328 +0,0 @@
|
||||
#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
|
||||
@@ -1,28 +0,0 @@
|
||||
: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
619
mk1-src/Makefile
@@ -1,619 +0,0 @@
|
||||
# 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
|
||||
|
||||
@@ -1,168 +0,0 @@
|
||||
/* 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 */
|
||||
@@ -1,47 +0,0 @@
|
||||
# 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
119
mk1-src/config.h
@@ -1,119 +0,0 @@
|
||||
/* 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
|
||||
@@ -1,51 +0,0 @@
|
||||
/**
|
||||
* \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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
/**
|
||||
* \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__ */
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
/**
|
||||
* \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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
/**
|
||||
* \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
107
mk1-src/crc7.c
@@ -1,107 +0,0 @@
|
||||
/* 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;
|
||||
}*/
|
||||
@@ -1,33 +0,0 @@
|
||||
/* 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
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
#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
202
mk1-src/diskio.c
@@ -1,202 +0,0 @@
|
||||
/* 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
132
mk1-src/diskio.h
@@ -1,132 +0,0 @@
|
||||
/* 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
175
mk1-src/eeprom.c
@@ -1,175 +0,0 @@
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
/* 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
3066
mk1-src/ff.c
File diff suppressed because it is too large
Load Diff
448
mk1-src/ff.h
448
mk1-src/ff.h
@@ -1,448 +0,0 @@
|
||||
/*--------------------------------------------------------------------------/
|
||||
/ 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 */
|
||||
@@ -1,80 +0,0 @@
|
||||
/* 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;
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
/* 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
|
||||
@@ -1,273 +0,0 @@
|
||||
/* 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;
|
||||
}
|
||||
181
mk1-src/fpga.c
181
mk1-src/fpga.c
@@ -1,181 +0,0 @@
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
/* 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
|
||||
@@ -1,99 +0,0 @@
|
||||
/* 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();
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/* 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);
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
#! /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";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/* 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
110
mk1-src/led.c
@@ -1,110 +0,0 @@
|
||||
/* 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;
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/* 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
400
mk1-src/main.c
@@ -1,400 +0,0 @@
|
||||
/* 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
335
mk1-src/memory.c
@@ -1,335 +0,0 @@
|
||||
/* 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;
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
/* 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
773
mk1-src/sdcard.c
@@ -1,773 +0,0 @@
|
||||
/* 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")));
|
||||
@@ -1,40 +0,0 @@
|
||||
/* 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
175
mk1-src/smc.c
@@ -1,175 +0,0 @@
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
/* 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
146
mk1-src/snes.c
@@ -1,146 +0,0 @@
|
||||
/* 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);
|
||||
}
|
||||
136
mk1-src/spi.c
136
mk1-src/spi.c
@@ -1,136 +0,0 @@
|
||||
/* 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;
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
/* 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
|
||||
@@ -1,75 +0,0 @@
|
||||
#!/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";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
#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
135
mk1-src/timer.c
@@ -1,135 +0,0 @@
|
||||
/* 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
121
mk1-src/timer.h
@@ -1,121 +0,0 @@
|
||||
/* 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
187
mk1-src/uart.c
@@ -1,187 +0,0 @@
|
||||
/* 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;
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/* 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
|
||||
@@ -1,47 +0,0 @@
|
||||
/* 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
|
||||
@@ -1,82 +0,0 @@
|
||||
/* 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;
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
/* 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
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
28645
pcb/kicad/$savepcb.brd
28645
pcb/kicad/$savepcb.brd
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user