eduet: fix up some of the music

This commit is contained in:
Vince Weaver 2023-05-01 02:09:16 -04:00
parent deb0af4914
commit 6a74f2e9a8
13 changed files with 3127 additions and 25 deletions

View File

@ -11,7 +11,7 @@ $(DOS33):
cd ../../utils/dos33fs-utils && make cd ../../utils/dos33fs-utils && make
eduet.dsk: $(DOS33) HELLO ED HIGHWIND.ED FIGHTING.ED SA.ED \ eduet.dsk: $(DOS33) HELLO ED HIGHWIND.ED FIGHTING.ED SA.ED \
KERBAL.ED KORO.ED PEASANT.ED KERBAL.ED KORO.ED PEASANT.ED FORTNIGHT.ED
cp $(EMPTY_DISK) eduet.dsk cp $(EMPTY_DISK) eduet.dsk
$(DOS33) -y eduet.dsk SAVE A HELLO $(DOS33) -y eduet.dsk SAVE A HELLO
$(DOS33) -y eduet.dsk BSAVE -a 0x0C00 ED $(DOS33) -y eduet.dsk BSAVE -a 0x0C00 ED
@ -21,6 +21,7 @@ eduet.dsk: $(DOS33) HELLO ED HIGHWIND.ED FIGHTING.ED SA.ED \
$(DOS33) -y eduet.dsk BSAVE -a 0x2000 KERBAL.ED $(DOS33) -y eduet.dsk BSAVE -a 0x2000 KERBAL.ED
$(DOS33) -y eduet.dsk BSAVE -a 0x2000 KORO.ED $(DOS33) -y eduet.dsk BSAVE -a 0x2000 KORO.ED
$(DOS33) -y eduet.dsk BSAVE -a 0x2000 PEASANT.ED $(DOS33) -y eduet.dsk BSAVE -a 0x2000 PEASANT.ED
$(DOS33) -y eduet.dsk BSAVE -a 0x2000 FORTNIGHT.ED
### ###
@ -42,20 +43,34 @@ duet.o: duet.s
PEASANT.ED: peasant.ed PEASANT.ED: peasant.ed
cp peasant.ed PEASANT.ED cp peasant.ed PEASANT.ED
###
peasant.ed: $(TEXT_TO_ED) peasant.txt peasant.ed: $(TEXT_TO_ED) peasant.txt
$(TEXT_TO_ED) peasant.txt peasant $(TEXT_TO_ED) -o 1 peasant.txt peasant
### ###
HIGHWIND.ED: highwind.ed HIGHWIND.ED: highwind.ed
cp highwind.ed HIGHWIND.ED cp highwind.ed HIGHWIND.ED
highwind.ed: $(TEXT_TO_ED) highwind.txt
$(TEXT_TO_ED) -o 0 highwind.txt highwind
### ###
highwind.ed: $(TEXT_TO_ED) highwind.txt FIGHTING.ED: fighting.ed
$(TEXT_TO_ED) -o -2 highwind.txt highwind cp fighting.ed FIGHTING.ED
fighting.ed: $(TEXT_TO_ED) fighting.txt
$(TEXT_TO_ED) -o 0 fighting.txt fighting
###
FORTNIGHT.ED: fortnight.ed
cp fortnight.ed FORTNIGHT.ED
fortnight.ed: $(TEXT_TO_ED) fortnight.txt
$(TEXT_TO_ED) -o 1 fortnight.txt fortnight
### ###
@ -73,5 +88,3 @@ notes.o: notes.c notes.h
clean: clean:
rm -f *~ *.o *.lst ED text_to_ed rm -f *~ *.o *.lst ED text_to_ed

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,295 @@
'
' TITLE: Breakdancing Rat from SBEMAIL #152
' AUTHOR: (tracked by) Vince Weaver <vince@deater.net>
' COMMENTS: based on MIDI converted from recording of the video
'
' LOOP: 640
'
' BPM: 320
' TEMPO: 6
' FREQ: 1000000
' IRQ: 50
'
' LYRICS: 0
'
' ENDHEADER
-------
' 1
' G 3 8
' 2
0 ----- ----- -----
1 ----- ----- -----
2 ----- ----- -----
3 ----- ----- -----
4 ----- ----- -----
5 ----- ----- -----
6 ----- ----- -----
7 ----- ----- -----
8 ----- ----- -----
9 ----- ----- -----
A ----- ----- -----
B ----- ----- -----
C ----- ----- -----
D ----- ----- -----
E ----- ----- -----
F ----- ----- -----
10 C 3 8 C 2 8 -----
11 ----- ----- -----
12 ----- ----- -----
13 ----- ----- -----
14 C 3 8 C 2 8 -----
15 ----- ----- -----
16 ----- ----- -----
17 ----- ----- -----
' 3
0 ----- ----- -----
1 ----- ----- -----
2 ----- ----- -----
3 ----- ----- -----
4 ----- ----- -----
5 ----- ----- -----
6 ----- ----- -----
7 ----- ----- -----
8 ----- ----- -----
9 ----- ----- -----
A ----- ----- -----
B ----- ----- -----
C B 3 8 E 2 8 -----
D ----- ----- -----
E ----- ----- -----
F ----- ----- -----
10 D 4 8 G 2 8 -----
11 ----- ----- -----
12 ----- ----- -----
13 ----- ----- -----
14 B 3 8 E 2 8 -----
15 ----- ----- -----
16 ----- ----- -----
17 ----- ----- -----
' 4
0 F 4 8 A#3 8 -----
1 ----- ----- -----
2 ----- ----- -----
3 ----- ----- -----
4 F 4 8 A#3 8 -----
5 ----- ----- -----
6 ----- ----- -----
7 ----- ----- -----
8 F 4 8 A#3 8 -----
9 ----- ----- -----
A ----- ----- -----
B ----- ----- -----
C A#3 6 A#2 8 -----
D ----- ----- -----
E F 4 6 ----- -----
F ----- ----- -----
10 ----- ----- -----
11 ----- ----- -----
12 ----- ----- -----
13 ----- ----- -----
14 ----- ----- -----
15 ----- ----- -----
16 ----- ----- -----
17 ----- ----- -----
' 5
0 ----- ----- -----
1 ----- ----- -----
2 ----- ----- -----
3 ----- ----- -----
4 ----- ----- -----
5 ----- ----- -----
6 ----- ----- -----
7 ----- ----- -----
8 C 3 8 C 2 8 -----
9 ----- ----- -----
A ----- ----- -----
B ----- ----- -----
C C 3 8 C 2 8 -----
D ----- ----- -----
E ----- ----- -----
F ----- ----- -----
10 ----- ----- -----
11 ----- ----- -----
12 ----- ----- -----
13 ----- ----- -----
14 ----- ----- -----
15 ----- ----- -----
16 ----- ----- -----
17 ----- ----- -----
' 6
0 ----- ----- -----
1 ----- ----- -----
2 ----- ----- -----
3 ----- ----- -----
4 ----- ----- -----
5 ----- ----- -----
6 ----- ----- -----
7 ----- ----- -----
8 F 4 4 A#3 4 -----
9 ----- ----- -----
A ----- ----- -----
B ----- ----- -----
C ----- ----- -----
D ----- ----- -----
E ----- ----- -----
F ----- ----- -----
10 B 3 8 E 2 8 -----
11 ----- ----- -----
12 ----- ----- -----
13 ----- ----- -----
14 B 3 8 E 2 8 -----
15 ----- ----- -----
16 ----- ----- -----
17 ----- ----- -----
' 7
0 B 3 8 E 2 8 -----
1 ----- ----- -----
2 ----- ----- -----
3 ----- ----- -----
4 B 3 8 E 2 8 -----
5 ----- ----- -----
6 ----- ----- -----
7 ----- ----- -----
8 ----- ----- -----
9 ----- ----- -----
A ----- ----- -----
B ----- ----- -----
C ----- ----- -----
D ----- ----- -----
E ----- ----- -----
F ----- ----- -----
10 ----- ----- -----
11 ----- ----- -----
12 ----- ----- -----
13 ----- ----- -----
14 ----- ----- -----
15 ----- ----- -----
16 ----- ----- -----
17 ----- ----- -----
' 8
0 ----- ----- -----
1 ----- ----- -----
2 ----- ----- -----
3 ----- C 2 > -----
4 C 3 6 C 2 6 -----
5 ----- ----- -----
6 C 3 6 C 2 6 -----
7 ----- ----- -----
8 C 3 4 C 2 4 -----
9 ----- ----- -----
A ----- ----- -----
B ----- ----- -----
C ----- ----- -----
D ----- ----- -----
E ----- ----- -----
F ----- ----- -----
10 ----- ----- -----
11 ----- ----- -----
12 ----- ----- -----
13 ----- ----- -----
14 ----- ----- -----
15 ----- ----- -----
16 ----- ----- -----
17 ----- ----- -----
' 9
0 B 3 8 E 2 8 -----
1 ----- ----- -----
2 ----- ----- -----
3 ----- ----- -----
4 D 4 8 G 2 8 -----
5 ----- ----- -----
6 ----- ----- -----
7 ----- ----- -----
8 B 3 8 E 2 8 -----
9 ----- ----- -----
A ----- ----- -----
B ----- ----- -----
C F 4 8 A#2 8 -----
D ----- ----- -----
E ----- ----- -----
F ----- ----- -----
' A#3 4
10 ----- A#3 8 -----
11 F 4 ? ----- -----
12 ----- ----- -----
13 ----- ----- -----
14 F 4 8 A#3 8 -----
15 ----- ----- -----
16 ----- ----- -----
17 ----- ----- -----
' 10
0 F 4 4 A#3 4 -----
1 ----- ----- -----
2 ----- ----- -----
3 ----- ----- -----
4 ----- ----- -----
5 ----- ----- -----
6 ----- ----- -----
7 ----- ----- -----
8 ----- ----- -----
9 ----- ----- -----
A ----- ----- -----
B ----- ----- -----
C ----- ----- -----
D ----- ----- -----
E ----- ----- -----
F ----- ----- -----
10 ----- ----- -----
11 ----- ----- -----
12 ----- ----- -----
13 ----- ----- -----
14 C 3 8 C 2 8 -----
15 ----- ----- -----
16 ----- ----- -----
17 ----- ----- -----
' 11
0 C 3 4 C 2 4 -----
1 ----- ----- -----
2 ----- ----- -----
3 ----- ----- -----
4 ----- ----- -----
5 ----- ----- -----
6 ----- ----- -----
7 ----- ----- -----
8 ----- ----- -----
9 ----- ----- -----
A ----- ----- -----
B ----- ----- -----
C ----- ----- -----
D ----- ----- -----
E ----- ----- -----
F ----- ----- -----
10 ----- ----- -----
11 ----- ----- -----
12 ----- ----- -----
13 ----- ----- -----
14 F 4 8 A#3 8 -----
15 ----- ----- -----
16 ----- ----- -----
17 ----- ----- -----
' 12
0 ----- ----- -----
1 ----- ----- -----
2 ----- ----- -----
3 ----- ----- -----
4 B 3 8 E 2 8 -----
5 ----- ----- -----
6 ----- ----- -----
7 ----- ----- -----
8 B 3 8 E 2 8 -----
9 ----- ----- -----
A ----- ----- -----
B ----- ----- -----
C B 3 8 E 2 8 -----
D ----- ----- -----
E ----- ----- -----
F ----- ----- -----
10 B 3 4 E 2 4 -----
11 ----- ----- -----
12 ----- ----- -----
13 ----- ----- -----
14 ----- ----- -----
15 ----- ----- -----
16 ----- ----- -----
17 ----- ----- -----
' LOOP TO FRAME ?

View File

@ -8,10 +8,11 @@
45 PRINT "4. KERBAL THEME" 45 PRINT "4. KERBAL THEME"
50 PRINT "5. KOROBEINIKI (TETRIS THEME)" 50 PRINT "5. KOROBEINIKI (TETRIS THEME)"
55 PRINT "6. PEASANT'S QUEST" 55 PRINT "6. PEASANT'S QUEST"
60 PRINT "7. FORTNIGHT (BREAKDANCE RAT)"
100 PRINT CHR$ (4)"BLOAD ED" 100 PRINT CHR$ (4)"BLOAD ED"
120 PRINT "-----> ";: INPUT A 120 PRINT "-----> ";: INPUT A
130 IF A < 0 OR A > 6 THEN GOTO 120 130 IF A < 0 OR A > 7 THEN GOTO 120
140 ON A GOTO 200,210,220,230,240,250 140 ON A GOTO 200,210,220,230,240,250,260
200 PRINT CHR$ (4)"BLOAD SA.ED,A$2000" 200 PRINT CHR$ (4)"BLOAD SA.ED,A$2000"
205 GOTO 1000 205 GOTO 1000
210 PRINT CHR$ (4)"BLOAD FIGHTING.ED,A$2000" 210 PRINT CHR$ (4)"BLOAD FIGHTING.ED,A$2000"
@ -24,6 +25,8 @@
245 GOTO 1000 245 GOTO 1000
250 PRINT CHR$ (4)"BLOAD PEASANT.ED,A$2000" 250 PRINT CHR$ (4)"BLOAD PEASANT.ED,A$2000"
255 GOTO 1000 255 GOTO 1000
260 PRINT CHR$ (4)"BLOAD FORTNIGHT.ED,A$2000"
265 GOTO 1000
1000 POKE 30,0: POKE 31,32 1000 POKE 30,0: POKE 31,32
1010 CALL 256*12 1010 CALL 256*12
1020 GOTO 2 1020 GOTO 2

View File

@ -85,14 +85,24 @@ double note_to_freq(char note, int flat, int sharp, int octave, double sub) {
*/ */
//static unsigned char ed_freqs[]={
///* A A# B C C# D D# E F F# G G# */
// 255,240,228,216,204,192,180,172,160,152,144,136,
// 128,120,114,108,102,96, 90, 86, 80, 76, 72, 68,
// 64, 60, 57, 54, 51, 48, 45, 43, 40, 38, 36, 34,
// 32, 30, 28, 27, 25, 24, 22, 21, 20, 19, 18, 17,
// 16, 15, 14, 13, 12, 12, 11, 10, 10, 9, 9, 8,
// 8, 8, 7};
static unsigned char ed_freqs[]={ static unsigned char ed_freqs[]={
/* A A# B C C# D D# E F F# G G# */ /* C C# D D# E F F# G G# A A# B*/
255,240,228,216,204,192,180,172,160,152,144,136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255,240,228, /* 1 */
128,120,114,108,102,96, 90, 86, 80, 76, 72, 68, 216,204,192,180,172,160,152,144,136,128,120,114, /* 2 */
64, 60, 57, 54, 51, 48, 45, 43, 40, 38, 36, 34, 108,102,96, 90, 86, 80, 76, 72, 68, 64, 60, 57, /* 3 */
32, 30, 28, 27, 25, 24, 22, 21, 20, 19, 18, 17, 54, 51, 48, 45, 43, 40, 38, 36, 34, 32, 30, 28, /* 4 */
16, 15, 14, 13, 12, 12, 11, 10, 10, 9, 9, 8, 27, 25, 24, 22, 21, 20, 19, 18, 17, 16, 15, 14, /* 5 */
8, 8, 7}; 13, 12, 12, 11, 10, 10, 9, 9, 8, 8, 8, 7}; /* 6 */
/* c1 c1 /* c1 c1
d1 d1 d1 d1
@ -109,13 +119,14 @@ int note_to_ed(char note, int flat, int sharp, int octave) {
int offset; int offset;
switch(note) { switch(note) {
case 'A': offset=12; break; case 'C': offset=0; break;
case 'B': offset=14; break; case 'D': offset=2; break;
case 'C': offset=3; break; case 'E': offset=4; break;
case 'D': offset=5; break; case 'F': offset=5; break;
case 'E': offset=7; break; case 'G': offset=7; break;
case 'F': offset=8; break; case 'A': offset=9; break;
case 'G': offset=10; break; case 'B': offset=11; break;
default: default:
fprintf(stderr,"Unknown note %c\n",note); fprintf(stderr,"Unknown note %c\n",note);
return -1; return -1;
@ -126,7 +137,7 @@ int note_to_ed(char note, int flat, int sharp, int octave) {
offset+=((octave-1)*12); offset+=((octave-1)*12);
if (offset>63) { if (offset>72) {
fprintf(stderr,"Out of range offset %d\n",offset); fprintf(stderr,"Out of range offset %d\n",offset);
return 7; return 7;
} }

View File

@ -71,6 +71,8 @@ static int note_to_length(int length) {
case 11: len=(baselen*9)/8; break; // ; = 9/8 dotted half + dotted quarter case 11: len=(baselen*9)/8; break; // ; = 9/8 dotted half + dotted quarter
case 12: len=(baselen*3)/2; break; // < = 3/2 dotted whole case 12: len=(baselen*3)/2; break; // < = 3/2 dotted whole
case 13: len=(baselen*2); break; // = = 2 double whole case 13: len=(baselen*2); break; // = = 2 double whole
case 14: len=(baselen/32); break; // > = 1/32
case 15: len=(baselen/32)*3; break; // ? = 3/32 dotted sixteenth
default: default:
fprintf(stderr,"Unknown length %d, line %d\n", fprintf(stderr,"Unknown length %d, line %d\n",
length,line); length,line);
@ -362,6 +364,9 @@ int main(int argc, char **argv) {
// baselen=60; // baselen=60;
baselen=64; // multiple of 16? baselen=64; // multiple of 16?
} }
else if (bpm==180) {// 3.33Hz, 333ms,
baselen=64; // multiple of 16?
}
else if (bpm==250) { else if (bpm==250) {
baselen=48; // eyeballed baselen=48; // eyeballed
} }

View File

@ -0,0 +1,32 @@
include ../../Makefile.inc
DOS33 = ../../utils/dos33fs-utils/dos33
TOKENIZE = ../../utils/asoft_basic-utils/tokenize_asoft
LINKERSCRIPTS = ../../linker_scripts
EMPTYDISK = ../../empty_disk/empty.dsk
all: double.dsk
double.dsk: HELLO DOUBLE
cp $(EMPTYDISK) double.dsk
$(DOS33) -y double.dsk SAVE A HELLO
$(DOS33) -y double.dsk BSAVE -a 0x1000 DOUBLE
###
HELLO: hello.bas
$(TOKENIZE) < hello.bas > HELLO
###
DOUBLE: double.o
ld65 -o DOUBLE double.o -C $(LINKERSCRIPTS)/apple2_1000.inc
double.o: double.s \
zp.inc
ca65 -o double.o double.s -l double.lst
###
clean:
rm -f *~ *.o *.lst HELLO DOUBLE

View File

@ -0,0 +1,279 @@
; Double Hi-res / Double lo-res mode switch fun
; by Vince `deater` Weaver
.include "zp.inc"
.include "hardware.inc"
;================================
; Clear screen and setup graphics
;================================
double:
jsr SETGR ; set lo-res 40x40 mode
; set 80-store mode
sta EIGHTYSTORE ; PAGE2 selects AUX memory
bit PAGE1
;===================
; draw lo-res lines
ldx #39
draw_lores_lines:
txa
tay
jsr SETCOL
lda #47
sta V2
lda #0
jsr VLINE ; VLINE A,$2D at Y
dex
bpl draw_lores_lines
; copy to 800 temporarily
; yes this is a bit of a hack
ldy #0
cp_loop:
lda $400,Y
sta $800,Y
lda $500,Y
sta $900,Y
lda $600,Y
sta $A00,Y
lda $700,Y
sta $B00,Y
iny
bne cp_loop
bit PAGE1
; copy to $400 in AUX
bit PAGE2 ; $400 now maps to AUX:$400
ldy #0
cp2_loop:
lda $800,Y
eor #$FF
sta $400,Y
lda $900,Y
eor #$FF
sta $500,Y
lda $A00,Y
eor #$FF
sta $600,Y
lda $B00,Y
eor #$FF
sta $700,Y
iny
bne cp2_loop
bit PAGE1
;===================
; draw hi-res lines
jsr HGR
bit FULLGR ; make it 40x48
lda #$FF
sta $E4 ; HCOLOR
ldx #0
ldy #0
lda #96
jsr HPLOT0 ; plot at (Y,X), (A)
ldx #0
lda #140
ldy #191
jsr HGLIN ; line to (X,A),(Y)
ldx #1
lda #23
ldy #96
jsr HGLIN ; line to (X,A),(Y)
; draw double-hires lines
lda #$20 ; draw to page0 (MAIN?)
sta HGRPAGE
lda #150 ; start at 150
sta YPOS
color_loop:
lda YPOS
and #$f
sta TCOLOR
asl
asl
asl
asl
ora TCOLOR
sta TCOLOR ; update color
lda YPOS
jsr draw_line_color
inc YPOS
lda YPOS
cmp #192
bne color_loop
; wait for vblank on IIe
; positive? during vblank
wait_vblank_iie:
lda VBLANK
bmi wait_vblank_iie ; wait for positive (in vblank)
wait_vblank_done_iie:
lda VBLANK ; wait for negative (vlank done)
bpl wait_vblank_done_iie
;
double_loop:
;===========================
; text mode first 6*4 (24) lines
; each line 65 cycles (25 hblank+40 bytes)
; 3 LINES 80-COL AN3
sta SET80COL ; 4
bit SET_TEXT ; 4
; wait 6*4=24 lines
; (24*65)-8 = 1560-8 = 1552
jsr delay_1552
; 3 LINES 40-COL AN3
sta CLR80COL ; 4
bit SET_TEXT ; 4
jsr delay_1552
; 3 LINES 40-col LORES AN3
lda LORES ; 4
bit SET_GR ; 4
jsr delay_1552
; 3 LINES 80-col DLORES AN3
sta SET80COL ; 4
sta CLRAN3 ; 4
jsr delay_1552
; 3 lines 40-col LORES
sta CLR80COL ; 4
sta SETAN3 ; 4 ; doublehiresoff
jsr delay_1552
; 3 lines HIRES
sta HIRES ; 4
sta CLRAN3 ; 4
jsr delay_1552
; 3 lines HIRES
sta HIRES ; 4
sta SETAN3 ; 4
jsr delay_1552
; 3 line Double-HIRES
sta SET80COL ; 4
sta CLRAN3 ; 4
jsr delay_1552
;==================================
; vblank = 4550 cycles
; Try X=226 Y=4 cycles=4545
skip_vblank:
nop
ldy #4 ; 2
loop3: ldx #226 ; 2
loop4: dex ; 2
bne loop4 ; 2nt/3
dey ; 2
bne loop3 ; 2nt/3
jmp double_loop ; 3
;=======================================================
; need to align because if we straddle a page boundary
; the time counts end up off
.align $100
; actually want 1552-12 (6 each for jsr/rts)
; 1540
; Try X=15 Y=19 cycles=1540
delay_1552:
ldy #19 ; 2
loop5: ldx #15 ; 2
loop6: dex ; 2
bne loop6 ; 2nt/3
dey ; 2
bne loop5 ; 2nt/3
rts
;==========================
; draw horizontal DHGR line
;==========================
; color is in TCOLOR
; Y position is in A
;=========================
draw_line_color:
ldx #0
ldy #0
jsr HPOSN ; setup GBASL/GBASH with Y position
ldy #0
line_loop_it:
; set page2
sta PAGE2
lda TCOLOR
sta (GBASL),Y
cmp #$80
rol TCOLOR
; set page1
sta PAGE1
lda TCOLOR
sta (GBASL),Y
cmp #$80
rol TCOLOR
iny
cpy #40
bne line_loop_it
rts

View File

@ -0,0 +1,28 @@
; soft-switches
; yes, I know these aren't necessary the "official" names
EIGHTYSTORE = $C001
CLR80COL = $C00C
SET80COL = $C00D
SET_GR = $C050
SET_TEXT= $C051
FULLGR = $C052
TEXTGR = $C053
PAGE1 = $C054
PAGE2 = $C055
LORES = $C056
HIRES = $C057
CLRAN3 = $C05E
SETAN3 = $C05F
VBLANK = $C019 ; *not* RDVBL (VBL signal low)
; ROM routines
SETCOL = $F864 ; COLOR=A*17
SETGR = $FB40
VLINE = $F828 ; VLINE A,$2D at Y
HGR = $F3E2
HPOSN = $F411
HPLOT0 = $F457 ; plot at (Y,X), (A)
HGLIN = $F53A ; line to (X,A),(Y)

View File

@ -0,0 +1,2 @@
5 HOME
10 PRINT CHR$(4);"CATALOG"

View File

@ -0,0 +1,222 @@
;===================================================================
; code to detect mockingboard
;===================================================================
; this isn't always easy
; my inclination is to just assume slot #4 but that isn't always realistic
; code below based on "hw.mockingboard.a" from "Total Replay"
;license:MIT
; By Andrew Roughan
; in the style of 4am for Total Replay
;
; Mockingboard support functions
;
;------------------------------------------------------------------------------
; HasMockingboard
; detect Mockingboard card by searching for 6522 timers across all slots
; access 6522 timers with deterministic cycle counts
;
; based on prior art in Mockingboard Developers Toolkit
; with optimisation from deater/french touch
; also takes into account FastChip //e clock difference
;
; in: none
; accelerators should be off
; out: C set if Mockingboard found in any slot
; if card was found, X = #$Cn where n is the slot number of the card
; C clear if no Mockingboard found
; other flags clobbered
; A/Y clobbered
;------------------------------------------------------------------------------
mockingboard_detect:
; activate Mockingboard IIc
; + the Mockingboard has to take over Slot#4 (IIc has no slots)
; in theory any write to the firmware area in $C400 will
; activate it, but that might not be fast enough when detecting
; so writing $FF to $C403/$C404 is official way to enable
; + Note this disables permanently the mouse firmware in $C400
; so "normal" interrupts are broken :( The hack to fix things
; is to switch in RAM for $F000 and just replace the IRQ
; vectors at $FFFE/$FFFF instead of $3FE/$3FF but that makes
; it difficult if you actually wanted to use any
; Applesoft/Monitor ROM routines
;.ifdef PT3_ENABLE_APPLE_IIC
lda APPLEII_MODEL
cmp #'C'
bne not_iic
lda #$ff
; don't bother patching these, IIc mockingboard always slot 4
sta MOCK_6522_DDRA1 ; $C403
sta MOCK_6522_T1CL ; $C404
;.endif
not_iic:
lda #$00
sta MB_ADDR_L
ldx #$C7 ; start at slot #7
mb_slot_loop:
stx MB_ADDR_H
ldy #$04 ; 6522 #1 $Cx04
jsr mb_timer_check
bne mb_next_slot
ldy #$84 ; 6522 #2 $Cx84
jsr mb_timer_check
bne mb_next_slot
mb_found:
sec ; found
rts
mb_next_slot:
dex
cpx #$C0
bne mb_slot_loop
clc ; not found
rts
mb_timer_check:
lda (MB_ADDR_L),Y ; read 6522 timer low byte
sta MB_VALUE
lda (MB_ADDR_L),Y ; second time
sec
sbc MB_VALUE
cmp #$F8 ; looking for (-)8 cycles between reads
beq mb_timer_check_done
cmp #$F7 ; FastChip //e clock is different
mb_timer_check_done:
rts
.if 0
;=======================================
; Detect a Mockingboard card
;=======================================
; Based on code from the French Touch "Pure Noise" Demo
; Attempts to time an instruction sequence with a 6522
;
; If found, puts in bMB
; MB_ADDRL:MB_ADDRH has address of Mockingboard
; returns X=0 if not found, X=1 if found
mockingboard_detect:
lda #0
sta MB_ADDRL
mb_detect_loop: ; self-modifying
lda #$07 ; we start in slot 7 ($C7) and go down to 0 ($C0)
ora #$C0 ; make it start with C
sta MB_ADDRH
ldy #04 ; $CX04
ldx #02 ; 2 tries?
mb_check_cycle_loop:
lda (MB_ADDRL),Y ; timer 6522 (Low Order Counter)
; count down
sta PT3_TEMP ; 3 cycles
lda (MB_ADDRL),Y ; + 5 cycles = 8 cycles
; between the two accesses to the timer
sec
sbc PT3_TEMP ; subtract to see if we had 8 cycles
cmp #$f8 ; -8
bne mb_not_in_this_slot
dex ; decrement, try one more time
bne mb_check_cycle_loop ; loop detection
inx ; Mockingboard found (X=1)
done_mb_detect:
;stx bMB ; store result to bMB
rts ; return
mb_not_in_this_slot:
dec mb_detect_loop+1 ; decrement the "slot" (self_modify)
bne mb_detect_loop ; loop down to one
ldx #00
beq done_mb_detect
;alternative MB detection from Nox Archaist
; lda #$04
; sta MB_ADDRL
; ldx #$c7
;
;find_mb:
; stx MB_ADDRH
;
; ;detect sound I
;
; sec
; ldy #$00
; lda (MB_ADDRL), y
; sbc (MB_ADDRL), y
; cmp #$05
; beq found_mb
; dex
; cpx #$c0
; bne find_mb
; ldx #$00 ;no mockingboard found
; rts
;
;found_mb:
; ldx #$01 ;mockingboard found
; rts
;
; ;optionally detect sound II
;
; sec
; ldy #$80
; lda (MB_ADDRL), y
; sbc (MB_ADDRL), y
; cmp #$05
; beq found_mb
;=======================================
; Detect a Mockingboard card in Slot4
;=======================================
; Based on code from the French Touch "Pure Noise" Demo
; Attempts to time an instruction sequence with a 6522
;
; MB_ADDRL:MB_ADDRH has address of Mockingboard
; returns X=0 if not found, X=1 if found
mockingboard_detect_slot4:
lda #0
sta MB_ADDRL
mb4_detect_loop: ; self-modifying
lda #$04 ; we're only looking in Slot 4
ora #$C0 ; make it start with C
sta MB_ADDRH
ldy #04 ; $CX04
ldx #02 ; 2 tries?
mb4_check_cycle_loop:
lda (MB_ADDRL),Y ; timer 6522 (Low Order Counter)
; count down
sta PT3_TEMP ; 3 cycles
lda (MB_ADDRL),Y ; + 5 cycles = 8 cycles
; between the two accesses to the timer
sec
sbc PT3_TEMP ; subtract to see if we had 8 cycles
cmp #$f8 ; -8
bne mb4_not_in_this_slot
dex ; decrement, try one more time
bne mb4_check_cycle_loop ; loop detection
inx ; Mockingboard found (X=1)
done_mb4_detect:
rts ; return
mb4_not_in_this_slot:
ldx #00
beq done_mb4_detect
.endif

View File

@ -0,0 +1,261 @@
; Mockingboad programming:
; + Has two 6522 I/O chips connected to two AY-3-8910 chips
; + Optionally has some speech chips controlled via the outport on the AY
; + Often in slot 4
; TODO: how to auto-detect?
; References used:
; http://macgui.com/usenet/?group=2&id=8366
; 6522 Data Sheet
; AY-3-8910 Data Sheet
;========================
; Mockingboard card
; Essentially two 6522s hooked to the Apple II bus
; Connected to AY-3-8910 chips
; PA0-PA7 on 6522 connected to DA0-DA7 on AY
; PB0 on 6522 connected to BC1
; PB1 on 6522 connected to BDIR
; PB2 on 6522 connected to RESET
; left speaker
MOCK_6522_ORB1 = $C400 ; 6522 #1 port b data
MOCK_6522_ORA1 = $C401 ; 6522 #1 port a data
MOCK_6522_DDRB1 = $C402 ; 6522 #1 data direction port B
MOCK_6522_DDRA1 = $C403 ; 6522 #1 data direction port A
MOCK_6522_T1CL = $C404 ; 6522 #1 t1 low order latches
MOCK_6522_T1CH = $C405 ; 6522 #1 t1 high order counter
MOCK_6522_T1LL = $C406 ; 6522 #1 t1 low order latches
MOCK_6522_T1LH = $C407 ; 6522 #1 t1 high order latches
MOCK_6522_T2CL = $C408 ; 6522 #1 t2 low order latches
MOCK_6522_T2CH = $C409 ; 6522 #1 t2 high order counters
MOCK_6522_SR = $C40A ; 6522 #1 shift register
MOCK_6522_ACR = $C40B ; 6522 #1 auxilliary control register
MOCK_6522_PCR = $C40C ; 6522 #1 peripheral control register
MOCK_6522_IFR = $C40D ; 6522 #1 interrupt flag register
MOCK_6522_IER = $C40E ; 6522 #1 interrupt enable register
MOCK_6522_ORANH = $C40F ; 6522 #1 port a data no handshake
; right speaker
MOCK_6522_ORB2 = $C480 ; 6522 #2 port b data
MOCK_6522_ORA2 = $C481 ; 6522 #2 port a data
MOCK_6522_DDRB2 = $C482 ; 6522 #2 data direction port B
MOCK_6522_DDRA2 = $C483 ; 6522 #2 data direction port A
; AY-3-8910 commands on port B
; RESET BDIR BC1
MOCK_AY_RESET = $0 ; 0 0 0
MOCK_AY_INACTIVE = $4 ; 1 0 0
MOCK_AY_READ = $5 ; 1 0 1
MOCK_AY_WRITE = $6 ; 1 1 0
MOCK_AY_LATCH_ADDR = $7 ; 1 1 1
;========================
; Mockingboard Init
;========================
; Initialize the 6522s
; set the data direction for all pins of PortA/PortB to be output
mockingboard_init:
lda #$ff ; all output (1)
mock_init_smc1:
sta MOCK_6522_DDRB1
sta MOCK_6522_DDRA1
mock_init_smc2:
sta MOCK_6522_DDRB2
sta MOCK_6522_DDRA2
rts
;===================================
;===================================
; Reset Both AY-3-8910s
;===================================
;===================================
;======================
; Reset Left AY-3-8910
;======================
reset_ay_both:
lda #MOCK_AY_RESET
reset_ay_smc1:
sta MOCK_6522_ORB1
lda #MOCK_AY_INACTIVE
reset_ay_smc2:
sta MOCK_6522_ORB1
;======================
; Reset Right AY-3-8910
;======================
;reset_ay_right:
;could be merged with both
lda #MOCK_AY_RESET
reset_ay_smc3:
sta MOCK_6522_ORB2
lda #MOCK_AY_INACTIVE
reset_ay_smc4:
sta MOCK_6522_ORB2
rts
; Write sequence
; Inactive -> Latch Address -> Inactive -> Write Data -> Inactive
;=========================================
; Write Right/Left to save value AY-3-8910
;=========================================
; register in X
; value in MB_VALUE
write_ay_both:
; address
write_ay_smc1:
stx MOCK_6522_ORA1 ; put address on PA1 ; 4
stx MOCK_6522_ORA2 ; put address on PA2 ; 4
lda #MOCK_AY_LATCH_ADDR ; latch_address on PB1 ; 2
write_ay_smc2:
sta MOCK_6522_ORB1 ; latch_address on PB1 ; 4
sta MOCK_6522_ORB2 ; latch_address on PB2 ; 4
ldy #MOCK_AY_INACTIVE ; go inactive ; 2
write_ay_smc3:
sty MOCK_6522_ORB1 ; 4
sty MOCK_6522_ORB2 ; 4
;===========
; 28
; value
lda MB_VALUE ; 3
write_ay_smc4:
sta MOCK_6522_ORA1 ; put value on PA1 ; 4
sta MOCK_6522_ORA2 ; put value on PA2 ; 4
lda #MOCK_AY_WRITE ; ; 2
write_ay_smc5:
sta MOCK_6522_ORB1 ; write on PB1 ; 4
sta MOCK_6522_ORB2 ; write on PB2 ; 4
write_ay_smc6:
sty MOCK_6522_ORB1 ; 4
sty MOCK_6522_ORB2 ; 4
;===========
; 29
rts ; 6
;===========
; 63
write_ay_both_end:
;.assert >write_ay_both = >write_ay_both_end, error, "write_ay_both crosses page"
;=======================================
; clear ay -- clear all 14 AY registers
; should silence the card
;=======================================
; 7+(74*14)+5=1048
clear_ay_both:
ldx #13 ; 2
lda #0 ; 2
sta MB_VALUE ; 3
clear_ay_left_loop:
jsr write_ay_both ; 6+63
dex ; 2
bpl clear_ay_left_loop ; 3
; -1
rts ; 6
clear_ay_end:
;.assert >clear_ay_both = >clear_ay_end, error, "clear_ay_both crosses page"
;=============================
; Setup
;=============================
mockingboard_setup_interrupt:
; for this game with things in language card including
; irq handler, always force IIc mode (where RAM swapped in
; and we put the irq handler address directly up at $FFFE)
lda #<interrupt_handler
sta $fffe
lda #>interrupt_handler
sta $ffff
; nop out the "lda $45" since we are bypassing the ROM irq handler
; that puts A in $45
lda #$EA
sta interrupt_smc
sta interrupt_smc+1
;=========================
; Setup Interrupt Handler
;=========================
; Vector address goes to 0x3fe/0x3ff
; FIXME: should chain any existing handler
; lda #<interrupt_handler
; sta $03fe
; lda #>interrupt_handler
; sta $03ff
;============================
; Enable 50Hz clock on 6522
;============================
; Note, on Apple II the clock isn't 1MHz but is actually closer to
; roughly 1.023MHz, and every 65th clock is stretched (it's complicated)
; 4fe7 / 1.023e6 = .020s, 50Hz
; 9c40 / 1.023e6 = .040s, 25Hz
; 411a / 1.023e6 = .016s, 60Hz
; French Touch uses
; 4e20 / 1.000e6 = .020s, 50Hz, which assumes 1MHz clock freq
sei ; disable interrupts just in case
lda #$40 ; Continuous interrupts, don't touch PB7
setup_irq_smc1:
sta MOCK_6522_ACR ; ACR register
lda #$7F ; clear all interrupt flags
setup_irq_smc2:
sta MOCK_6522_IER ; IER register (interrupt enable)
lda #$C0
setup_irq_smc3:
sta MOCK_6522_IFR ; IFR: 1100, enable interrupt on timer one oflow
setup_irq_smc4:
sta MOCK_6522_IER ; IER: 1100, enable timer one interrupt
lda #$E7
; lda #$20
setup_irq_smc5:
sta MOCK_6522_T1CL ; write into low-order latch
lda #$4f
; lda #$4E
setup_irq_smc6:
sta MOCK_6522_T1CH ; write into high-order latch,
; load both values into counter
; clear interrupt and start counting
rts
;=============================
; Disable Interrupt
;=============================
mockingboard_disable_interrupt:
sei ; disable interrupts just in case
lda #$40 ; Continuous interrupts, don't touch PB7
disable_irq_smc1:
sta MOCK_6522_ACR ; ACR register
lda #$7F ; clear all interrupt flags
disable_irq_smc2:
sta MOCK_6522_IER ; IER register (interrupt enable)
rts

View File

@ -0,0 +1,10 @@
; zero page
GBASL = $26
GBASH = $27
V2 = $2D
HGRPAGE = $E6
YPOS = $FE
TCOLOR = $FF