mirror of
https://github.com/Michaelangel007/c2t.git
synced 2024-12-11 11:49:24 +00:00
c2t-96h minor updates, doc updates, article added/updated, windows 96h binary
This commit is contained in:
parent
dc09517573
commit
c96332b204
9
Makefile
9
Makefile
@ -1,13 +1,16 @@
|
||||
|
||||
|
||||
all: c2t
|
||||
all: c2t c2t-96h
|
||||
|
||||
clean:
|
||||
rm c2t.h c2t
|
||||
rm c2t.h c2t c2t-96h
|
||||
cd asm; make clean
|
||||
|
||||
c2t: c2t.c c2t.h
|
||||
gcc -Wall -O3 -o c2t c2t.c
|
||||
gcc -Wall -Wno-unused-value -Wno-unused-function -O3 -o c2t c2t.c
|
||||
|
||||
c2t-96h: c2t-96h.c c2t.h
|
||||
gcc -Wall -Wno-unused-value -Wno-unused-function -O3 -o c2t-96h c2t-96h.c
|
||||
|
||||
c2t.h: mon/dos33.boot1.mon mon/dos33.boot2.mon asm/autoload.s asm/diskload2.s asm/diskload3.s asm/diskload8000.s asm/diskload9600.s asm/fastload8000.s asm/fastload9600.s asm/fastloadcd.s asm/inflate.s
|
||||
./makeheader
|
||||
|
19
README.md
19
README.md
@ -28,7 +28,8 @@ You clearly do not understand the awesomeness of the Apple II, move along.
|
||||
|
||||
## Version
|
||||
|
||||
0.996 (Nov 29 2014)
|
||||
c2t 0.996 (Nov 29 2014)
|
||||
c2t-96h 0.997 (Dec 31 2015)
|
||||
|
||||
|
||||
## Installation
|
||||
@ -63,6 +64,22 @@ gcc -Wall -O3 -static -o c2t c2t.c
|
||||
```
|
||||
> Use the `miniz.h` in the `windows` directory.
|
||||
|
||||
To cross build for Windows from OS/X, first install <http://crossgcc.rts-software.org/doku.php?id=compiling_for_win32>, then type:
|
||||
```
|
||||
cd windows
|
||||
cp ../c2t.*
|
||||
cp ../fake6502.h
|
||||
/usr/local/gcc-4.8.0-qt-4.8.4-for-mingw32/win32-gcc/bin/i586-mingw32-gcc -Wall -Wno-unused-value -Wno-unused-function -O3 -static -o c2t.exe c2t.c
|
||||
```
|
||||
|
||||
|
||||
## c2t-96h Version
|
||||
|
||||
`c2t-96h` is a hacked up version of `c2t` that fixes a few bugs (e.g. `.po` files) and adds working 9600 BPS code.
|
||||
Both `-8` and `-f` activate this new 9600 BPS code.
|
||||
|
||||
`c2t-96h` will eventually replace `c2t`. IOW, use `c2t-96h` for now.
|
||||
|
||||
|
||||
## Tested Configurations:
|
||||
|
||||
|
BIN
article/article.docx
Normal file
BIN
article/article.docx
Normal file
Binary file not shown.
BIN
article/article.pdf
Normal file
BIN
article/article.pdf
Normal file
Binary file not shown.
BIN
article/article.pptx
Normal file
BIN
article/article.pptx
Normal file
Binary file not shown.
34
article/c12k.txt
Normal file
34
article/c12k.txt
Normal file
@ -0,0 +1,34 @@
|
||||
12000
|
||||
12000
|
||||
-2
|
||||
2 main: ldy #0
|
||||
4 psync: bit tapein
|
||||
2 bmi psync
|
||||
2 ploop: iny
|
||||
4 bit tapein
|
||||
3 bpl ploop
|
||||
2 ploop: iny
|
||||
4 bit tapein
|
||||
3 bpl ploop
|
||||
2 ploop: iny
|
||||
4 bit tapein
|
||||
3 bpl ploop
|
||||
2 ploop: iny
|
||||
4 bit tapein
|
||||
3 bpl ploop
|
||||
2 ploop: iny
|
||||
4 bit tapein
|
||||
2 bpl ploop
|
||||
2 cpy #$40
|
||||
2 bpl endcode
|
||||
2 cpy #$15
|
||||
2 bpl main
|
||||
2 cpy #$07
|
||||
7 store: rol nnnn,x
|
||||
2 asl
|
||||
2 bne main
|
||||
2 lda #1
|
||||
2 inx
|
||||
2 bne main
|
||||
6 inc store+2
|
||||
3 jmp main
|
49
article/c6k.txt
Normal file
49
article/c6k.txt
Normal file
@ -0,0 +1,49 @@
|
||||
6000
|
||||
6000
|
||||
-2
|
||||
2 main: ldy #0
|
||||
4 psync: bit tapein
|
||||
2 bmi psync
|
||||
2 ploop: iny
|
||||
4 bit tapein
|
||||
3 bpl ploop
|
||||
2 ploop: iny
|
||||
4 bit tapein
|
||||
3 bpl ploop
|
||||
2 ploop: iny
|
||||
4 bit tapein
|
||||
3 bpl ploop
|
||||
2 ploop: iny
|
||||
4 bit tapein
|
||||
3 bpl ploop
|
||||
2 ploop: iny
|
||||
4 bit tapein
|
||||
3 bpl ploop
|
||||
2 ploop: iny
|
||||
4 bit tapein
|
||||
3 bpl ploop
|
||||
2 ploop: iny
|
||||
4 bit tapein
|
||||
3 bpl ploop
|
||||
2 ploop: iny
|
||||
4 bit tapein
|
||||
3 bpl ploop
|
||||
2 ploop: iny
|
||||
4 bit tapein
|
||||
3 bpl ploop
|
||||
2 ploop: iny
|
||||
4 bit tapein
|
||||
2 bpl ploop
|
||||
2 cpy #$40
|
||||
2 bpl endcode
|
||||
2 cpy #$15
|
||||
2 bpl main
|
||||
2 cpy #$07
|
||||
7 store: rol nnnn,x
|
||||
2 asl
|
||||
3 bne main
|
||||
2 lda #1
|
||||
2 inx
|
||||
3 bne main
|
||||
6 inc store+2
|
||||
3 jmp main
|
BIN
article/helloworldbasicheader.png
Normal file
BIN
article/helloworldbasicheader.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 48 KiB |
89
article/plot.py
Executable file
89
article/plot.py
Executable file
@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys, math, os
|
||||
|
||||
try:
|
||||
cycles_file = sys.argv[1]
|
||||
except:
|
||||
print "usage: %s cycles.txt" % sys.argv[0]
|
||||
sys.exit(1)
|
||||
|
||||
f = open(cycles_file,'r')
|
||||
freq0 = f.readline().strip()
|
||||
freq1 = f.readline().strip()
|
||||
start = int(f.readline().strip())
|
||||
|
||||
a2freq = 1020484.4497 # src: openemulator, src: https://discussions.apple.com/thread/559102
|
||||
#rot = True
|
||||
rot = False
|
||||
|
||||
xr = a2freq / float(freq0)
|
||||
xcross = xr / float(2.0)
|
||||
xc2 = int(xcross * 100) / float(100)
|
||||
ycross = 0
|
||||
xdiv = xcross / float(math.pi)
|
||||
yb = -0.25
|
||||
|
||||
g = open('plot.gnuplot','w')
|
||||
if rot:
|
||||
g.write('set title " %d/%d KHz Cycle" offset 0,-2\n' % (int(freq0)/1000,int(freq1)/1000))
|
||||
else:
|
||||
g.write('set ylabel "%d/%d KHz Cycle"\n' % (int(freq0)/1000,int(freq1)/1000))
|
||||
g.write('set term postscript \n')
|
||||
g.write('set size ratio 0.5\n')
|
||||
g.write('set output "plot.ps"\n')
|
||||
g.write('set key off\n')
|
||||
g.write('set grid xtics lt 0 lw 1 lc rgb "#000000"\n')
|
||||
g.write('set grid ytics lt 0 lw 1 lc rgb "#000000"\n')
|
||||
g.write('set xrange [%d:%f]\n' % (start,xr))
|
||||
g.write('set yrange [%f:1]\n' % yb)
|
||||
g.write('set xtics 1 font "courier,10"\n')
|
||||
g.write('set x2tics 1 font "courier,10"\n')
|
||||
g.write('set ytics 1 font "courier,10"\n')
|
||||
g.write('set arrow from %d,0 to %f,0 nohead lw 1 lc rgb "black"\n' % (start,xr))
|
||||
g.write('set arrow from %f,%f to %f,1 nohead lw 1 lc rgb "black"\n' % (xcross,yb,xcross))
|
||||
if start < 0:
|
||||
g.write('set arrow from %f,%f to %f,1 nohead lw 1 lc rgb "black"\n' % (0,yb,0))
|
||||
g.write('set xtic rotate by 90 right \n')
|
||||
g.write('set x2tic rotate by 90 left \n')
|
||||
|
||||
x2tics = {}
|
||||
xtics = {}
|
||||
|
||||
base = start
|
||||
ll = 0
|
||||
for i in f.readlines():
|
||||
cycles = int(i.split(' ')[0])
|
||||
text = i.split(' ',1)[1].rstrip().upper()
|
||||
if len(text) > ll:
|
||||
ll = len(text)
|
||||
xtics[str(base)] = text
|
||||
x2tics[str(base)] = str(base)
|
||||
base += cycles
|
||||
|
||||
x2tics[str(xc2)] = ' ZC'
|
||||
if start < 0:
|
||||
x2tics['0'] = '0 ZC'
|
||||
|
||||
g.write('set x2tics (')
|
||||
for k, v in x2tics.iteritems():
|
||||
g.write('"%s" %f, ' % (v,float(k)))
|
||||
g.write(')\n')
|
||||
|
||||
g.write('set xtics (')
|
||||
for k, v in xtics.iteritems():
|
||||
g.write('"%s" %d, ' % (v + ' '*(ll-len(v)),int(k)))
|
||||
g.write(')\n')
|
||||
|
||||
f.close()
|
||||
|
||||
g.write('set ytics ("0" 0, "+" 1, "-" %f)\n' % yb)
|
||||
g.write('plot sin(x/%f)\n' % xdiv)
|
||||
g.write('quit\n')
|
||||
|
||||
g.close()
|
||||
os.system('gnuplot plot.gnuplot')
|
||||
os.system('pstopdf plot.ps -o plot.pdf')
|
||||
if rot:
|
||||
os.system('pdf90 plot.pdf')
|
||||
|
74
article/timeline.py
Executable file
74
article/timeline.py
Executable file
@ -0,0 +1,74 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys, math, os
|
||||
|
||||
try:
|
||||
timeline_file = sys.argv[1]
|
||||
except:
|
||||
print "usage: %s timeline.txt" % sys.argv[0]
|
||||
sys.exit(1)
|
||||
|
||||
f = open(timeline_file,'r')
|
||||
title = f.readline().strip() + " Audio Timeline"
|
||||
start = 0
|
||||
rot = True
|
||||
|
||||
g = open('timeline.gnuplot','w')
|
||||
if rot:
|
||||
g.write('set x2label "%s"\n' % title);
|
||||
#else:
|
||||
# g.write('set ylabel "%d/%d KHz Cycle"\n' % (int(freq0)/1000,int(freq1)/1000))
|
||||
g.write('set term postscript \n')
|
||||
#g.write('set size ratio 0.5\n')
|
||||
g.write('set output "timeline.ps"\n')
|
||||
g.write('set key off\n')
|
||||
g.write('set grid xtics lt 0 lw 1 lc rgb "#000000"\n')
|
||||
g.write('set grid ytics lt 0 lw 1 lc rgb "#000000"\n')
|
||||
g.write('set yrange [0:1]\n')
|
||||
g.write('set xtics 1 font "courier,9"\n')
|
||||
g.write('set x2tics 1 font "courier,9"\n')
|
||||
g.write('set xtic rotate by 90 right \n')
|
||||
g.write('set x2tic rotate by 90 left \n')
|
||||
g.write('unset ytics\n')
|
||||
g.write('unset y2tics\n')
|
||||
|
||||
x2tics = {}
|
||||
xtics = {}
|
||||
|
||||
ll = 0
|
||||
for i in f.readlines():
|
||||
if i[0] == '#':
|
||||
continue
|
||||
timestamp = float(i.split(',')[0])
|
||||
label = i.split(',')[1].rstrip()
|
||||
if len(label) > ll:
|
||||
ll = len(label)
|
||||
xtics[str(timestamp)] = label
|
||||
x2tics[str(timestamp)] = str(timestamp)
|
||||
g.write('set arrow from %f,0 to %f,1 nohead lw 1 lc rgb "black"\n' % (timestamp,timestamp))
|
||||
xr = timestamp
|
||||
|
||||
g.write('set x2tics (')
|
||||
for k, v in x2tics.iteritems():
|
||||
g.write('"%s" %f, ' % (v,float(k)))
|
||||
g.write(')\n')
|
||||
|
||||
g.write('set xtics (')
|
||||
for k, v in xtics.iteritems():
|
||||
#g.write('"%s" %f, ' % (v + ' '*(ll-len(v)),float(k)))
|
||||
g.write('"%s" %f, ' % (v,float(k)))
|
||||
g.write(')\n')
|
||||
|
||||
f.close()
|
||||
|
||||
#g.write('set ytics ("0" 0, "+" 1, "-" %f)\n' % yb)
|
||||
g.write('set xrange [%d:%f]\n' % (start,xr))
|
||||
g.write('plot 0\n')
|
||||
g.write('quit\n')
|
||||
|
||||
g.close()
|
||||
os.system('gnuplot timeline.gnuplot')
|
||||
os.system('pstopdf timeline.ps -o timeline.pdf')
|
||||
if rot:
|
||||
os.system('pdf90 timeline.pdf')
|
||||
|
78
research/The Apple II Cassette Interface (1 of 2).txt
Normal file
78
research/The Apple II Cassette Interface (1 of 2).txt
Normal file
@ -0,0 +1,78 @@
|
||||
From: http://support.apple.com/kb/TA40730
|
||||
|
||||
This note is about the cassette interface built into the Apple II and
|
||||
Apple II+, subroutines. An assumption made here is that the cassette
|
||||
recorder is in the proper mode, play or record, when the read and write
|
||||
routines are executed. Note also that the timing is approximate and may
|
||||
vary from one Apple to another.
|
||||
|
||||
A record is a block of binary data. This data may be a BASIC or APPLESOFT
|
||||
program, a machine language program, or just binary data. Records representing
|
||||
BASIC or APPLESOFT programs are really two records, the length of the program
|
||||
and the actual program. A record consists of a header, synchronous bit, the
|
||||
actual data, and a checksum byte for error detection.
|
||||
|
||||
Monitor record format
|
||||
|
||||
+--------+-+-----------------------+-+
|
||||
| HEADER |S| DATA |C|
|
||||
+--------+-+-----------------------+-+
|
||||
|
||||
BASIC program record format
|
||||
|
||||
+--------+-+----+-+--------+-+----------------+-+
|
||||
| HEADER |S| LB |C| HEADER |S| PROGRAM |C|
|
||||
+--------+-+----+-+--------+-+----------------+-+
|
||||
|
||||
Key: S = SYNC bit
|
||||
C = CHECKSUM byte
|
||||
LB = BASIC program length
|
||||
|
||||
The header consists of 10 seconds of 770 Hz tone, (1 cycle equals 1300
|
||||
microseconds). This gives enough time for the cassette motor to attain speed
|
||||
and the plastic tape leader to go by. A subroutine called HEADR generates a
|
||||
shortened header between the BASIC length bytes and the BASIC program itself.
|
||||
The length of the header tone is controlled by the value of the accumulator on
|
||||
entry to the subroutine. This can vary from 0.2 seconds to 40 seconds. On
|
||||
entry the X register should be 0 and the carry flag should be set. HEADR also
|
||||
generates a synchronous bit at the end of the tone. HEADR resides at
|
||||
hexadecimal address $FCC9, or decimal address -882.
|
||||
|
||||
The last cycle of header tone and SYNC bit
|
||||
|
||||
---+ +-------------+ +-----+
|
||||
| | | | |
|
||||
+-------------+ +----+ |
|
||||
|
||||
| 1300 microseconds | 200 | 250 | header tone | synchronous bit |
|
||||
|
||||
The synchronous bit, generated by HEADR, is one half cycle of 2500 Hz, (200
|
||||
microseconds) and one half cycle of 2000 Hz, (250 microseconds). It is used to
|
||||
signal the end of the header tone and the start of the data.
|
||||
|
||||
The data is recorded on the tape with a low starting address and a high ending
|
||||
address. Each byte of data is shifted out most significant bit first, least
|
||||
significant bit last. A zero bit is made up of one cycle of 2 kHz, (250
|
||||
microseconds per half cycle) and a one bit is one cycle of 1 kHz, (500
|
||||
microseconds per half cycle). This works out to 2000 baud for zeros only and
|
||||
1000 baud for ones, or an average of 1500 baud.
|
||||
|
||||
A zero bit and a one bit
|
||||
|
||||
+-----+ +----------+ +
|
||||
| | | | |
|
||||
+ +-----+ +----------+
|
||||
|
||||
| 500 usec | 1000 usec |
|
||||
|
||||
The checksum byte is written on the tape at the end of the data block. All
|
||||
during reading or writing each data byte is EXCLUSIVE OR-ed with the checksum
|
||||
byte. If the checksum computed during a read agrees with the checksum that was
|
||||
written out, then the data is probably good. This method will detect an odd
|
||||
number of errors for any of the eight bits of the byte.
|
||||
|
||||
In writing data, the cassette output uses quite simple circuitry, a flip-flop
|
||||
connected through a voltage divider to the jack on the back panel of the
|
||||
Apple. Any time the address $C020 is accessed this flip-flop changes state.
|
||||
Accessing the flip-flop once every 500 microseconds generates a 1000 Hz
|
||||
tone.
|
65
research/The Apple II Cassette Interface (2 of 2).txt
Normal file
65
research/The Apple II Cassette Interface (2 of 2).txt
Normal file
@ -0,0 +1,65 @@
|
||||
From: http://support.apple.com/kb/TA40737
|
||||
|
||||
For reading data, the cassette recorder uses a more complicated input circuit
|
||||
consisting of a 741 operational amplifier configured as a zero crossing
|
||||
detector. Zero crossing detection means that whenever the voltage at the input
|
||||
jack goes from positive to negative (or negative to positive) the output of
|
||||
the amplifier switches from a 1 to a 0 (or 0 to 1). The detector is accessed
|
||||
by any read to address $C060. The sign bit (most significant bit) of the byte
|
||||
read reflects the detector status. The read routines continually EXCLUSIVE
|
||||
ORs this bit with the value most recently read to detect a change in state.
|
||||
The amount of time required to change state indicates the incoming frequency
|
||||
which then is used to determine if a one or a zero has been received. After
|
||||
detecting the first zero crossing at the start of the header, the read routine
|
||||
uses HEADR to generate a 3.5 delay, and then the read routine waits for the
|
||||
sync bit. After HEADR generates the synchronous bit, the read routine reads
|
||||
the data and puts it in the specified memory range.
|
||||
|
||||
In using the cassette interface to either read or write, all you need do is
|
||||
specify an address range and execute the read or write subroutine. The
|
||||
address range is stored in four bytes, two for the first address to be saved
|
||||
and two for the last to be saved. In both cases the least significant byte is
|
||||
first.
|
||||
|
||||
Commanding the cassette interface:
|
||||
|
||||
1. from the monitor:
|
||||
If the start is $800 and the end is $9FF, then
|
||||
800.9FFW will write the data to the cassette and
|
||||
800.9FFR will retrieve it.
|
||||
|
||||
2. from machine language:
|
||||
Again, if the start is $800 and the end is $9FF then store the address
|
||||
range,
|
||||
|
||||
LDA #$00
|
||||
STA $3C starting address low
|
||||
LDA #$08
|
||||
STA $3D starting address high
|
||||
LDA #$FF
|
||||
STA $3E ending address low
|
||||
LDA #$09
|
||||
STA $3F ending address high
|
||||
JSR $FEDC write to block to tape
|
||||
|
||||
The JSR $FEDC will write to the cassette; JSR $FEFD will read from the
|
||||
cassette.
|
||||
|
||||
3. from BASIC:
|
||||
First set up the address range. If S = the start and E = the end then from
|
||||
integer BASIC,
|
||||
|
||||
POKE 60,S MOD 256
|
||||
POKE 61,S / 256
|
||||
POKE 62,E MOD 256
|
||||
POKE 63,E / 256
|
||||
|
||||
4. from APPLESOFT,
|
||||
|
||||
POKE 60,S - INT(S / 256) * 256
|
||||
POKE 61,S / 256
|
||||
POKE 62,E - INT(E / 256) * 256
|
||||
POKE 63,E / 256
|
||||
|
||||
Then, to write out to cassette, use CALL -307; to read in from the cassette,
|
||||
use CALL -259.
|
BIN
windows/c2t-96h.exe
Executable file
BIN
windows/c2t-96h.exe
Executable file
Binary file not shown.
Loading…
Reference in New Issue
Block a user