4
4
Encoding as per: https://github.com/oboroc/msx-books/blob/master/ru/msx2-fb-1993-ru.md#10
5
5
"""
6
6
7
- import sys , wave
7
+ import sys , os , wave
8
8
9
9
class wav_writer :
10
10
def __init__ (self , s_rate = 44100.0 , s_width = 1 ):
@@ -38,7 +38,6 @@ def write(self, f_name):
38
38
f .setsampwidth (self .sample_width )
39
39
f .setframerate (self .sample_rate )
40
40
f .writeframes (bytearray (self .pcm_data ))
41
- del ba
42
41
43
42
44
43
def add_value (self , value ):
@@ -130,12 +129,6 @@ def add_long_header(self, freq):
130
129
self .add_short_header (freq )
131
130
132
131
133
- def add_cas (self , freq , cas ):
134
- """
135
- take object cas and add pcm data based on it
136
- """
137
-
138
-
139
132
CAS_HEADER = [0x1f , 0xa6 , 0xde , 0xba , 0xcc , 0x13 , 0x7d , 0x74 ]
140
133
CAS_HEADER_LEN = len (CAS_HEADER )
141
134
BASIC = 0xd3
@@ -191,33 +184,22 @@ def dechex(n):
191
184
self .blocks = []
192
185
while idx < len (cas_data ):
193
186
if not is_cas_header (cas_data , idx ):
194
- print ('Error: no valid cas header at' , dechex (idx ))
195
- return
187
+ raise ValueError ('no valid cas header at ' + dechex (idx ))
196
188
idx = idx + CAS_HEADER_LEN
197
189
# is it a 10 byte block header?
198
190
if reps (cas_data , idx , BLOCK_HEADER_LEN ) >= BLOCK_HEADER_LEN :
199
191
block_type = cas_data [idx ]
200
192
idx = idx + BLOCK_HEADER_LEN
201
193
else :
202
194
block_type = CUSTOM
203
- if block_type == BASIC :
204
- s = 'BASIC'
205
- elif block_type == ASCII :
206
- s = 'ASCII'
207
- elif block_type == BINARY :
208
- s = 'BINARY'
209
- else :
210
- s = 'CUSTOM'
211
- #print(s, 'block start at', dechex(idx))
212
195
# 6 bytes file name and cas header
213
196
block_fname = ''
214
197
if block_type in [BASIC , ASCII , BINARY ]:
215
198
for i in range (FNAME_LEN ):
216
199
block_fname = block_fname + chr (cas_data [idx + i ])
217
200
idx = idx + FNAME_LEN
218
201
if not is_cas_header (cas_data , idx ):
219
- print ('Error: no cas header after cas file name at' , dechex (idx ))
220
- return
202
+ raise ValueError ('no cas header after cas file name at ' + dechex (idx ))
221
203
idx = idx + CAS_HEADER_LEN
222
204
block_data = []
223
205
start_address = end_address = run_address = - 1
@@ -230,15 +212,14 @@ def dechex(n):
230
212
break
231
213
block_data .append (cas_data [idx ])
232
214
idx = idx + 1
233
- #print('BASIC block end at', dechex(idx))
234
215
elif block_type == ASCII :
235
216
ASCII_SEQ_LEN = 256
236
217
EOF = 0x1a
237
218
while idx < len (cas_data ):
238
219
if len (cas_data ) - idx < ASCII_SEQ_LEN :
239
- print ( 'Error: expected' , ASCII_SEQ_LEN , ' bytes sequence in ASCII block' , block_fname ,
240
- '; there is only' , len (cas_data ) - idx , 'bytes of data left' )
241
- return
220
+ raise ValueError ( ' expected ' + str ( ASCII_SEQ_LEN ) + ' bytes sequence in ASCII block ' +
221
+ block_fname + '; there is only' + str ( len (cas_data ) - idx ) +
222
+ ' bytes of data left' )
242
223
found_eof = False
243
224
for i in range (ASCII_SEQ_LEN ):
244
225
block_data .append (cas_data [idx + i ])
@@ -248,54 +229,42 @@ def dechex(n):
248
229
if found_eof :
249
230
break
250
231
if not is_cas_header (cas_data , idx ):
251
- #print('Error: no cas header for next ASCII sequence at', dechex(idx))
252
- return
232
+ raise ValueError ('no cas header for next ASCII sequence at ' + dechex (idx ))
253
233
idx = idx + CAS_HEADER_LEN
254
- #print('ASCII block end at', dechex(idx))
255
234
if not found_eof :
256
- print ('Error: no eof found in ascii block at' , dechex (idx ))
257
- return
235
+ raise ValueError ('no eof found in ascii block at ' + dechex (idx ))
258
236
elif block_type == BINARY :
259
237
start_address = cas_data [idx ] + cas_data [idx + 1 ] * 256
260
- #print('start address:', dechex(start_address))
261
238
end_address = cas_data [idx + 2 ] + cas_data [idx + 3 ] * 256
262
- #print('end address: ', dechex(end_address))
263
239
run_address = cas_data [idx + 4 ] + cas_data [idx + 5 ] * 256
264
- #print('run address: ', dechex(run_address))
265
240
code_len = end_address - start_address + 1
266
- #print('code length: ', dechex(code_len))
267
241
idx = idx + 6
268
242
bin_start = idx
269
243
if idx + code_len > len (cas_data ):
270
- print ('Error: unexpected end in binary block data' )
271
- return
244
+ raise ValueError ('unexpected end in binary block data at ' + dechex (idx ))
272
245
while idx < len (cas_data ):
273
246
if is_cas_header (cas_data , idx ):
274
247
break
275
248
block_data .append (cas_data [idx ])
276
249
idx = idx + 1
277
- #print('block length:', dechex(idx - bin_start))
278
- #print('BINARY block end at', dechex(idx))
279
250
elif block_type == CUSTOM :
280
251
while idx < len (cas_data ):
281
252
if is_cas_header (cas_data , idx ):
282
253
break
283
254
block_data .append (cas_data [idx ])
284
255
idx = idx + 1
285
- #print('CUSTOM block end at', dechex(idx))
286
256
else :
287
- print ('Error: this is a bug, this code should never be reached' )
288
- return
257
+ raise ValueError ('this is a bug, this code should never be reached' )
289
258
self .blocks .append ([block_type , block_fname , block_data , start_address , end_address , run_address ])
259
+ del cas_data
290
260
291
261
292
- def write (self , cas_name ):
262
+ def write (self , fname , is_wav = False , s_rate = 44100.0 , s_width = 1 ):
293
263
"""
294
- create a cas file from cas_data
264
+ create a cas or wav (if is_wav == True) file from cas_data
295
265
"""
296
266
if self .blocks == []:
297
- print ('Error: no cas data, nothing to write to' , cas_name )
298
- return
267
+ raise ValueError ('no cas data, nothing to write to ' + fname )
299
268
cas_data = []
300
269
for block in self .blocks :
301
270
block_type = block [0 ]
@@ -304,36 +273,82 @@ def write(self, cas_name):
304
273
start_address = block [3 ]
305
274
end_address = block [4 ]
306
275
run_address = block [5 ]
307
- cas_data .extend (CAS_HEADER )
276
+ if is_wav :
277
+ ww = wav_writer (s_rate , s_width )
278
+ freq = 1200.0
279
+ ww .add_long_header (freq )
280
+ else :
281
+ cas_data .extend (CAS_HEADER )
308
282
if block_type in [BASIC , ASCII , BINARY ]:
309
283
for i in range (BLOCK_HEADER_LEN ):
310
- cas_data .append (block_type )
284
+ if is_wav :
285
+ ww .add_byte (freq , block_type )
286
+ else :
287
+ cas_data .append (block_type )
311
288
for i in range (FNAME_LEN ):
312
- cas_data .append (ord (block_fname [i ]))
289
+ if is_wav :
290
+ ww .add_byte (freq , ord (block_fname [i ]))
291
+ else :
292
+ cas_data .append (ord (block_fname [i ]))
313
293
if block_type == BASIC :
314
- cas_data .extend (CAS_HEADER )
315
- cas_data .extend (block_data )
294
+ if is_wav :
295
+ ww .add_short_header (freq )
296
+ for i in range (len (block_data )):
297
+ ww .add_byte (freq , block_data [i ])
298
+ else :
299
+ cas_data .extend (CAS_HEADER )
300
+ cas_data .extend (block_data )
316
301
elif block_type == ASCII :
317
302
for i in range (len (block_data )):
318
303
if i % 256 == 0 :
319
- cas_data .extend (CAS_HEADER )
320
- cas_data .append (block_data [i ])
304
+ if is_wav :
305
+ ww .add_short_header (freq )
306
+ else :
307
+ cas_data .extend (CAS_HEADER )
308
+ if is_wav :
309
+ ww .add_byte (freq , block_data [i ])
310
+ else :
311
+ cas_data .append (block_data [i ])
321
312
elif block_type == BINARY :
322
- cas_data .extend (CAS_HEADER )
323
- cas_data .append (start_address & 0xff )
324
- cas_data .append ((start_address & 0xff00 ) >> 8 )
325
- cas_data .append (end_address & 0xff )
326
- cas_data .append ((end_address & 0xff00 ) >> 8 )
327
- cas_data .append (run_address & 0xff )
328
- cas_data .append ((run_address & 0xff00 ) >> 8 )
329
- cas_data .extend (block_data )
313
+ start_lo = start_address & 0xff
314
+ start_hi = (start_address & 0xff00 ) >> 8
315
+ end_lo = end_address & 0xff
316
+ end_hi = (end_address & 0xff00 ) >> 8
317
+ run_lo = run_address & 0xff
318
+ run_hi = (run_address & 0xff00 ) >> 8
319
+ if is_wav :
320
+ ww .add_short_header (freq )
321
+ ww .add_byte (freq , start_lo )
322
+ ww .add_byte (freq , start_hi )
323
+ ww .add_byte (freq , end_lo )
324
+ ww .add_byte (freq , end_hi )
325
+ ww .add_byte (freq , run_lo )
326
+ ww .add_byte (freq , run_hi )
327
+ for i in range (len (block_data )):
328
+ ww .add_byte (freq , block_data [i ])
329
+ else :
330
+ cas_data .extend (CAS_HEADER )
331
+ cas_data .append (start_lo )
332
+ cas_data .append (start_hi )
333
+ cas_data .append (end_lo )
334
+ cas_data .append (end_hi )
335
+ cas_data .append (run_lo )
336
+ cas_data .append (run_hi )
337
+ cas_data .extend (block_data )
330
338
elif block_type == CUSTOM :
331
- cas_data .extend (block_data )
339
+ if is_wav :
340
+ for i in range (len (block_data )):
341
+ ww .add_byte (freq , block_data [i ])
342
+ else :
343
+ cas_data .extend (block_data )
332
344
else :
333
- print ('Error: invalid block type' , block_type )
334
- return
335
- with open (cas_name , 'wb' ) as f :
336
- f .write (bytearray (cas_data ))
345
+ raise ValueError ('invalid block type ' + hex (block_type ))
346
+ if is_wav :
347
+ ww .write (fname )
348
+ else :
349
+ with open (fname , 'wb' ) as f :
350
+ f .write (bytearray (cas_data ))
351
+ del cas_data
337
352
338
353
339
354
def main ():
@@ -343,12 +358,10 @@ def main():
343
358
for i in range (1 , len (sys .argv )):
344
359
c = cas ()
345
360
c .read (sys .argv [i ])
346
- c .write ('---' + sys .argv [i ])
347
- print ('---' )
348
- # t = wav_writer()
349
- # t.add_cas(1200, c)
350
- # t.write('test.wav')
351
- # del t
361
+ # c.write('~' + sys.argv[i])
362
+ bn = os .path .basename (sys .argv [i ])
363
+ fname = os .path .splitext (bn )[0 ] + '.wav'
364
+ c .write (fname , True )
352
365
del c
353
366
354
367
0 commit comments