Hallo zusammen,
ich beschäftige mich gerade mit dem Quellcode eines sehr alten Spiels
von 1983?
Hintergrund ist, ich beabsichtige das in C(++) nachzuprogrammieren. Auf
aktueller Hardware. Ich habe vor ca. 15 Jahren zum letzten mal Assembler
programmiert. Kann also behaupten, meine Fähigkeiten sind mehr als
eingerostet.
Ich verstehe zwar grob den Ablauf des Programmes, aber wenn es an die
Feinheiten geht, hört es mitunter auf. Dabei sind es an verschiedenen
Stellen immer die gleichen Fragezeichen...
Die Hardware ist ein TMS1400. Wusste bis vor kurzem nicht einmal, dass
es sowas mal gab :-)
1
Instruction Func OPCODE Bits HEX Inst
2
---------------- ----------- --- ----
3
0011001111101000 00000000 00 MNEA - Memory not equal to Accumulator
4
0011010111010000 00000001 01 ALEM - Accumulator less than or equal to Memory
5
0010101111101001 00000010 02 YNEA - Y Register not equal to Accumulator
6
1011011111001100 00000011 03 XMA - Exchange Memory and Accumulator
7
0011001111011100 00000110 06 AMAAC - Add Memory to Accumulator -> Accumulator with Carry
PLAYBUF tya ; Transfer the Y register to the Accumulator
11
dan ; Subtract one from Accumulator to point to beginning of sound buffer at 4/Y
12
ldx 3
13
tcy 10
14
SC0F tam ; Save updated pointer into sound buffer into 3/10
15
tmy
16
ldx 4 ; Check 4/Y
17
mnez
18
br SC3A ; There's a non-zero value here, play it
19
20
ldx 5 ; Check 5/Y
21
mnez
22
br SC3A ; There's a non-zero value here, play it
23
ldp 1
24
br LC5F ; There's a zero here... play silence (a rest)
25
26
SC39 mnea
27
mnea
28
mnea
29
mnea
30
SC1D tam
31
32
SC3A tcy 10 ; Select the speaker R output
33
setr ; Toggle the speaker on
34
mnea
35
mnea
36
mnea
37
mnea
38
ldx 3
39
rstr ; Toggle the speaker off
40
tmy ; Restore the note we were playing
41
;
42
; Load delay from 6/Y and 7/Y into A and Y respectively and delay for that many loops
43
;
44
; This adjusts the time between toggles of the speaker
45
;
46
ldx 6
47
tma
48
ldx 7
49
tmy
50
SC1C dyn
51
br SC1C
52
dan
53
br SC1C
54
;
55
; Restore the note we're on into the Y register
56
;
57
ldx 3
58
tcy 10
59
tmy
60
;
61
; Loop based on 5/Y and 4/Y, playing the note repeatedly. This gives duration.
62
;
63
ldx 5
64
dman
65
br SC39
66
tam
67
ldx 4
68
dman
69
br SC1D
70
;
71
; Note has been played for requested duration, decrement 3/10 and loop
72
;
73
LC08 ldx 3
74
tcy 10
75
dman
76
br SC0F
77
retn
78
79
80
;
81
; More of the PLAYBUF routine. Code responsible for playing silence (a rest)
82
;
83
SC40 mnea
84
mnea
85
mnea
86
mnea
87
SC4F tam
88
89
90
91
;
92
; Play a "zero" note - silence
93
;
94
LC5F cla
95
dan
96
SC7E mnea
97
mnea
98
mnea
99
mnea
100
mnea
101
dan
102
br SC7E
103
ldx 7
104
dman
105
br SC40
106
tam
107
ldx 6
108
dman
109
br SC4F
110
ldp 0
111
br LC08 ; Go back and play the next note
So wie ich das verstehe ist es ja eine Art PWM. Was ich im Moment nicht
weiß, wie ich die Zahlenwerte beim füllen des Buffers betrachten soll.
Sind es millisekunden? In der Funktion für die Ausgabe leuchtet mir
nicht ganz ein, wie durch die aufgerufenen Schleifen die genauen
Verzögerungen erzeugt werden.
Der wiederholte Aufruf des Befehls "mnea" ist mir dabei auch
unverständlich.
Ich hoffe, einer der Assembler Profis kann mir etwas mehr Einblick in
die Funktionsweise geben. Die Nachprogrammierung der beiden Funktionen
artet schon in wildes Probieren aus, was bisher nicht zielführend war.
Gruß
Matze
Matthias H. schrieb:> ich beschäftige mich gerade mit dem Quellcode eines sehr alten Spiels> von 1983?> Hintergrund ist, ich beabsichtige das in C(++) nachzuprogrammieren. Auf> aktueller Hardware.
Tja, wenn man irgendwas portieren will, muss man
1)die Quellsprache und die Zielsprache beherrschen.
2)ggf. das ursprüngliche Target und neue kennen.
Da bleibt dir noch viel Arbeit bei der persönlichen Aufschlauung zu
leisten.
Wollen wir mal hoffen, dass dieses Spiel es wirklich wert ist...
Hallo Matze,
Nur so eine Idee:
Das sind evtl. keine Zeitangaben in ms.
Sondern Zeitangaben, die in Relation zu der Zeit ist, die die mnea
Befehle bzw Unterroutinen dauern?
Die Hardware läuft doch mit einer festen Frequenz. Und der mnea Befehl
dauert dementsprechend.
Also kannst Du ausrechnen, wielange zB die SC3A Funktion den
Lautsprecher anmacht.
Jens
@jens
Der Gedanke kam mir auch schon. Leider ist mir nicht Bekannt hoch der
Takt ist.
Der mnea Befehl wird ja tatsächlich ähnlich wie nop verwendet....
Werde nochmal meine Unterlagen durchschauen ob ich etwas finde.
@AtariST
Völlig richtig! :-)
Tatsächlich am Code Fetzen erkannt?
Das füllen des Buffers leuchtet mir auch noch nicht so ganz ein. Für
mich sieht das erstmal aus wie 2D Array. Würdet Ihr das auch so lesen?
Nachtrag:
Habe noch etwas gefunden:
1
26 OSC pin 27 and 56pF cap to batt+ and 43K resistor to batt-
2
27 OSC pin 26 and cap and resistor
3
28 Vss 9v battery positive
Muss mal schauen, wie ich mit den Angaben den Takt rausfinde...
Ich rechne wahrscheinlich wieder Unsinn.
f = 1 / (2 pi R * C)
Komme auf 66 KHz.
Ist jetzt eine gute Frage wie viele Zyklen er für 1 Befehl braucht.
Bei 1/66000 wären das etwa 15us.
Gute Frage...
Nachtrag:
Habe noch etwas gefunden. Im Anhang ein Screenshot...
Einfacher wäre, du extrahierst den Soundtrack aus einem der Youtube
Videos.
Wenn du mit aktueller Hardware eine Linux-Platine meinst, kannst du die
damalige Strategie eh nicht verwenden. Musst die Sound-Treiber nutzen.
Ich meinte tatsächlich einen AVR.
Ich habe die Sounds als WAV Dateien. Habe aus der WAV mit einem
Hilfstool ein Datenstream erzeugt. Der lässt sich auch mittels PWM auf
dem AVR abspielen.
Macht aber natürlich Aufgrund der Datenmenge keinen Sinn.
Ich habe jetzt mal die Ausgabeprozedur Schritt für Schritt
mitgeschrieben damit ich mal die Logik durchschaue. Dabei bin ich
schnell drauf gekommen, dass das kein 2D Array ist, sondern ein 4D.
Wenn ich mir die Prozedur so anschaue , frage ich mich, wer sich sowas
ausdenkt... Meine Schritt für Schritt Notizen werde ich morgen mal in
Code wandeln und auf einem Arduino ausprobieren. Bin gespannt, ob da was
gescheites bei rum kommt. Habe leise Zweifel.
Matthias H. schrieb:> Macht aber natürlich Aufgrund der Datenmenge keinen Sinn.
Für Audio Ausgabe eignen sich diese angeblich übertrieben schnellen 32
Bit Controller mit DMA und DAC viel besser. Computer aus 8/16 Bit Zeiten
hatten für die Audio Ausgabe eigene Chipsätze.
H. H. schrieb:> Matthias H. schrieb:>> f = 1 / (2 pi R * C)>> Nicht 2*Pi, sondern 2*ln(2).
Hallo,
ich kapier deine Formel nicht ganz...
Kannst du mir das kurz erläutern? Vielleicht mit einer Beispiel
Rechnung?
Ansonsten ging meine Vermutung, dass der mnea Befehl ähnlich wie nop
genutzt wird nicht auf. Die Verwendung bzw. die Logik der Verwendung
dieses Befehls bleibt ein Rätzel.
Genau wie der zeitliche Ablauf. Ich sehe zwar, wann und wie welcher Wert
runtergezählt wird, aber eine Tonfolge entsteht bei mir nicht dabei.
Um genau zu sein, ich müsste nur diese Zeilen verstehen, dann wäre alles
klar!
1
SC39 mnea
2
mnea
3
mnea
4
mnea
5
SC1D tam
Der Befehl bedeutet "memory not equal accumulator" Wenn die Bedingung
wahr wäre, wird das Status bit auf 1 gesetzt. Da aber innerhalb dieser 6
Zeilen keine Veränderung eintritt, und nachfolgend keine Auswertung des
Status bits erfolgt, z.B. durch bedingten Sprung, verstehe ich die
Bedeutung nicht.
Daher kam die Vermutung, dass damit nur Zeit geschunden wird. Ich habe
im Programm mal probehalber 35us pro Befehl angenommen. Kam damit nicht
weiter.
Irgendwo übersehe ich etwas.
Langsam glaube ich, diese Soundausgabe ist der schwierigste Teil im
Projekt...
Vielen Dank für die verlinkten Unterlagen!
Matthias H. schrieb:> H. H. schrieb:>> Matthias H. schrieb:>>> f = 1 / (2 pi R * C)>>>> Nicht 2*Pi, sondern 2*ln(2).>> Hallo,>> ich kapier deine Formel nicht ganz...> Kannst du mir das kurz erläutern? Vielleicht mit einer Beispiel> Rechnung?
Siehe Datenblatt des NE555 als AMV.
Dark Tower gabs auch für den C64:
https://www.myabandonware.com/game/dark-tower-4se
In einem C64-Emulator kann man das laufen lassen und analysieren.
Die Mnemonics für den 6502 dürften geläufiger sein.