tschak909 Posted May 12, 2015 Share Posted May 12, 2015 Hello everyone, I am now officially announcing the first version of 'eduencode', a C library that can encode WAV files that are compatible with the Atari Educational System Master Cartridge (CXL4001). It provides a complete API for virtually every feature of the Atari Educational System, including: * ASCII text output * highlighted ASCII text output * Color settings for border, background, and hilight colors * writing individual bytes for control codes if desired. * clearing the screen * introducing pauses * indicating the correct answer for a following query * query to ask for an answer. (1, 2, or 3) * etc. All of the functions are immediate, and cause the given data to be appended to the file automatically. The WAV file produced is stereo, with the data in the right channel, as needed, and can either be directly used, or fed into a program such as Audacity, Soundforge, or others, for voice over processing in the left channel. It is intended that this library be used, to create a user friendly authoring tool, so that others can make educational system tapes, or for it to be used as an archaeological tool, as part of a curation to document how the Atari Educational System works. I am attaching a ZIP file containing the current revision of the code, and will post up to github, later this week. I am also pasting a copy of the library source in this thread, as well as the test harness, so everyone can have a look. eduencode.c - the implementation /* eduencode.c - Routines to create Atari Educational System tapes */ /* Author: Thomas Cherryhomes <thom.cherryhomes@gmail.com> */ #include <math.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <stdio.h> #include "eduencode.h" #define FALSE 0 #define TRUE 1 #define SAMPLE_RATE 44100 /* Output Sample Rate */ #define HZ_MARK 5327 /* Mark Frequency */ #define HZ_SPACE 3995 /* Space Frequency */ #define SECS_LEADER 4 /* Leader time in seconds */ #define NUM_CHANNELS 1 /* output channels - 1 */ #define BUFFER_SIZE 74 /* buffer size for a single 600 baud bit transition. */ #define AMPLITUDE 16384 /* amplitude for samples, right now at half volume. */ #define LEFT_CHANNEL 0 /* Lower 16 bits = Left Channel */ #define RIGHT_CHANNEL 16 /* Upper 16 bits = right channel */ #define BYTES_PER_SAMPLE 4 /* 16-bit samples, 2 channels */ #define BITS_PER_SAMPLE 16 /* Therefore 32 bits per total sample */ #define BYTE_RATE 176400 /* how many bytes per second, data rate */ #define HEADER_LENGTH 36 /* The RIFF WAVE file header is 36 bytes total */ int32_t edu_data_len = 0; int edu_write_leader(FILE* fp) { int i; float amplitude = AMPLITUDE; float freq_hz = HZ_MARK; float phase=0; int buffer_size = SAMPLE_RATE * NUM_CHANNELS * SECS_LEADER; float freq_radians_per_sample = freq_hz*2*M_PI/SAMPLE_RATE; int32_t buffer[buffer_size]; for (i=0;i<buffer_size;i++) { if (phase > M_PI) phase = (phase - (2*M_PI)); phase += freq_radians_per_sample; buffer[i] = (int32_t)(amplitude*sin(phase)) << RIGHT_CHANNEL; /* << 16 ensures right channel. */ } if (fwrite(&buffer,sizeof(int32_t),buffer_size,fp) != buffer_size) { return FALSE; } edu_data_len=edu_data_len+(sizeof(int32_t)*buffer_size); return TRUE; } int edu_write_wav_header(FILE* fp, int32_t len) { int32_t total_len = HEADER_LENGTH+len; int32_t subchunk_size = 16; int16_t format = 1; int16_t num_channels = 2; int32_t sample_rate = SAMPLE_RATE; int32_t byte_rate = BYTE_RATE; int16_t bytes_per_sample = BYTES_PER_SAMPLE; int16_t bits_per_sample = BITS_PER_SAMPLE; fwrite("RIFF",1,4,fp); fwrite(&total_len,sizeof(int32_t),1,fp); // Write total length fwrite("WAVE",1,4,fp); // Write WAVE subpart fwrite("fmt ",1,4,fp); // write fmt subpart fwrite(&subchunk_size,sizeof(int32_t),1,fp); // subchunk size is 16. fwrite(&format,sizeof(int16_t),1,fp); // PCM is format 1 fwrite(&num_channels,sizeof(int16_t),1,fp); // num channels = 2 fwrite(&sample_rate,sizeof(int32_t),1,fp); // 44100hz sample rate fwrite(&byte_rate,sizeof(int32_t),1,fp); // byte rate is 176400 fwrite(&bytes_per_sample,sizeof(int16_t),1,fp); // 2 bytes per sample fwrite(&bits_per_sample,sizeof(int16_t),1,fp); // 32 bits per sample. fwrite("data",1,4,fp); // data chunk fwrite(&len,sizeof(int32_t),1,fp); // data length return TRUE; // FIXME TODO: Come back here and do some fucking error handling. } FILE *edu_open_file(const char* filename) { FILE* fp; fp = fopen(filename,"wb"); edu_data_len=0; if (edu_write_wav_header(fp,0) == FALSE) return NULL; if (edu_write_leader(fp) == FALSE) return NULL; return fp; } int edu_close_file(FILE* fp) { fseek(fp,0,SEEK_SET); edu_write_wav_header(fp,edu_data_len); // Update header now that we have total length. fseek(fp,0,SEEK_END); fclose(fp); return TRUE; } int edu_write_baud(FILE* fp, float freq_hz) { int i; float amplitude = AMPLITUDE; float phase=0; int buffer_size = BUFFER_SIZE; float freq_radians_per_sample = freq_hz*2*M_PI/SAMPLE_RATE; int32_t buffer[buffer_size]; for (i=0;i<buffer_size;i++) { if (phase > M_PI) phase = (phase - (2*M_PI)); phase += freq_radians_per_sample; buffer[i] = (int32_t)(amplitude*sin(phase)) << RIGHT_CHANNEL; /* << 16 ensures right channel. */ } if (fwrite(&buffer,sizeof(int32_t),buffer_size,fp) != buffer_size) { return FALSE; } edu_data_len=edu_data_len+(sizeof(int32_t)*buffer_size); return TRUE; } int edu_write_mark(FILE* fp) { return edu_write_baud(fp,HZ_MARK); } int edu_write_space(FILE* fp) { return edu_write_baud(fp,HZ_SPACE); } int edu_write_start_bit(FILE* fp) { return edu_write_space(fp); } int edu_write_stop_bit(FILE* fp) { return edu_write_mark(fp); } int edu_write_byte(FILE* fp, unsigned char b) { int i=0; if (edu_write_start_bit(fp) == FALSE) return FALSE; b = b ^ 0xFF; // XOR the byte with $FF, invert all bits as specified. for (i=0; i<8; i++) { if (b & (1<<i)) { if (edu_write_mark(fp) == FALSE) return FALSE; } else { if (edu_write_space(fp) == FALSE) return FALSE; } } if (edu_write_stop_bit(fp) == FALSE) return FALSE; return TRUE; } int edu_write_string(FILE* fp, const char* text) { int buffer_size = strlen(text); int i=0; for (i=0; i<buffer_size; i++) { if (edu_write_byte(fp,text[i]) == FALSE) return FALSE; if (edu_write_byte(fp,0) == FALSE) return FALSE; } return TRUE; } int edu_write_hilight_string(FILE* fp, const char* text) { int buffer_size = strlen(text); int i=0; for (i=0; i<buffer_size; i++) { if (edu_write_byte(fp,(text[i] | 0x80)) == FALSE) return FALSE; if (edu_write_byte(fp,0) == FALSE) return FALSE; } return TRUE; } int edu_write_pause(FILE* fp, int ms) { int num_of_nulls = ms * .06; int i=0; for (i=0; i<num_of_nulls;i++) { if (edu_write_byte(fp,0) == FALSE) { return FALSE; } } return TRUE; } int edu_write_clear(FILE* fp) { return edu_write_byte(fp,0x03); } int edu_write_hilight_blink_off(FILE* fp) { return edu_write_byte(fp,0x02); } int edu_write_hilight_blink_on(FILE *fp) { return edu_write_byte(fp,0x05); } int edu_write_background_color(FILE *fp, BackgroundColor backgroundColor) { return edu_write_byte(fp,backgroundColor); } int edu_write_border_color(FILE *fp, BorderColor borderColor) { return edu_write_byte(fp,borderColor); } int edu_write_hilight_color(FILE *fp, HilightColor hilightColor) { return edu_write_byte(fp,hilightColor); } int edu_write_colors(FILE *fp, BackgroundColor backgroundColor, BorderColor borderColor, HilightColor hilightColor) { edu_write_background_color(fp,backgroundColor); edu_write_border_color(fp,borderColor); edu_write_hilight_color(fp,hilightColor); return TRUE; } int edu_write_correct_answer(FILE *fp, CorrectAnswer answer) { return edu_write_byte(fp,answer); } int edu_write_wait_for_answer(FILE *fp) { return edu_write_byte(fp,0x84); } eduencode.h - the public API /* eduencode.c - Routines to create Atari Educational System tapes */ /* Author: Thomas Cherryhomes <thom.cherryhomes@gmail.com> */ #include <stdio.h> enum BackgroundColorEnum { BACKGROUND_DARK_RED=0x19, BACKGROUND_MAGENTA=0x1A, BACKGROUND_RED=0x1b, BACKGROUND_BROWN=0x1c, BACKGROUND_GREEN=0x1d, BACKGROUND_BLUE=0x1e }; typedef enum BackgroundColorEnum BackgroundColor; enum BorderColorEnum { BORDER_DARK_RED=0x11, BORDER_MAGENTA=0x12, BORDER_RED=0x13, BORDER_BROWN=0x14, BORDER_GREEN=0x15, BORDER_BLUE=0x16 }; typedef enum BorderColorEnum BorderColor; enum HilightColorEnum { HILIGHT_DARK_RED=0x99, HILIGHT_MAGENTA=0x9A, HILIGHT_RED=0x9B, HILIGHT_BROWN=0x9C, HILIGHT_GREEN=0x9d, HILIGHT_BLUE=0x9E }; typedef enum HilightColorEnum HilightColor; enum CorrectAnswerEnum { ANSWER_1=0x08, ANSWER_2=0x09, ANSWER_3=0x0A }; typedef enum CorrectAnswerEnum CorrectAnswer; FILE *edu_open_file(const char* filename); int edu_close_file(FILE* fp); int edu_write_byte(FILE* fp, unsigned char b); int edu_write_string(FILE* fp, const char* text); int edu_write_hilight_string(FILE* fp, const char* text); int edu_write_pause(FILE* fp, int ms); int edu_write_clear(FILE* fp); int edu_write_hilight_blink_off(FILE* fp); int edu_write_hilight_blink_on(FILE *fp); int edu_write_background_color(FILE *fp, BackgroundColor backgroundColor); int edu_write_border_color(FILE *fp, BorderColor borderColor); int edu_write_hilight_color(FILE *fp, HilightColor hilightColor); int edu_write_colors(FILE *fp, BackgroundColor backgroundColor, BorderColor borderColor, HilightColor hilightColor); int edu_write_correct_answer(FILE *fp, CorrectAnswer answer); int edu_write_wait_for_answer(FILE *fp); and test_eduencode.c, the test harness, to show how it works: /* Test Harness */ #include "eduencode.h" #include <stdio.h> int main(int argc, char* argv[]) { FILE* fp = edu_open_file("test_eduencode.wav"); edu_write_string(fp,"------------------------------\r\r"); edu_write_string(fp,"This is an example tape being\r"); edu_write_string(fp,"Written by the "); edu_write_hilight_string(fp," eduencode \r"); edu_write_string(fp,"library; Released as free\r"); edu_write_string(fp,"software under the protections\r"); edu_write_string(fp,"of v3 of the"); edu_write_hilight_string(fp," GNU Public License "); edu_write_string(fp,"\r\r"); edu_write_hilight_color(fp,HILIGHT_DARK_RED); edu_write_pause(fp,600); edu_write_hilight_color(fp,HILIGHT_RED); edu_write_pause(fp,600); edu_write_hilight_color(fp,HILIGHT_BROWN); edu_write_pause(fp,600); edu_write_hilight_color(fp,HILIGHT_GREEN); edu_write_pause(fp,600); edu_write_pause(fp,6000); edu_write_colors(fp,BACKGROUND_GREEN,BORDER_GREEN,HILIGHT_RED); edu_write_clear(fp); edu_write_string(fp,"This code can be used to both\r"); edu_write_string(fp,"create new Atari Educational\r"); edu_write_string(fp,"System tapes,"); edu_write_pause(fp,400); edu_write_string(fp,"as well as\r"); edu_write_string(fp,"Provide a historical study of\r"); edu_write_string(fp,"The tape format, "); edu_write_pause(fp,350); edu_write_string(fp,"which, "); edu_write_pause(fp,150); edu_write_string(fp,"along\r"); edu_write_string(fp,"with the documentation of the\r"); edu_write_string(fp,"Master Cartridge, and its \r"); edu_write_string(fp,"disassembly,"); edu_write_pause(fp,450); edu_write_string(fp," serve as a \r"); edu_write_string(fp,"complete curated exhibit of\r"); edu_write_string(fp,"this form of computer based\r"); edu_write_string(fp,"education.\r"); edu_write_pause(fp,6000); edu_write_colors(fp,BACKGROUND_BROWN,BORDER_BROWN,HILIGHT_MAGENTA); edu_write_clear(fp); edu_write_hilight_string(fp," eduencode "); edu_write_string(fp," outputs a\r"); edu_write_string(fp,"standard WAV file, which can be\r"); edu_write_string(fp,"read by a variety of audio pro-\r"); edu_write_string(fp,"grams to be able to be written\r"); edu_write_string(fp,"to a cassette tape, and certain\r"); edu_write_string(fp,"emulators, such as Altirra, can\r"); edu_write_string(fp,"play these tapes, in emulation.\r"); edu_write_pause(fp,8000); edu_write_colors(fp,BACKGROUND_BROWN,BORDER_BROWN,HILIGHT_GREEN); edu_write_clear(fp); edu_write_string(fp,"This tape was written using the "); edu_write_hilight_string(fp," eduencode "); edu_write_string(fp," library\r"); edu_write_string(fp," functions, such as:\r\r"); edu_write_hilight_string(fp,"-------------------------------\r"); edu_write_hilight_string(fp,"| edu_write_string(fp,'Hi'); |\r"); edu_write_hilight_string(fp,"| edu_write_pause(fp,5000); |\r"); edu_write_hilight_string(fp,"| edu_write_correct_answer... |\r"); edu_write_hilight_string(fp,"| ... |\r"); edu_write_hilight_string(fp,"-------------------------------\r"); edu_write_pause(fp,7000); edu_write_colors(fp,BACKGROUND_BLUE,BORDER_GREEN,HILIGHT_RED); edu_write_clear(fp); edu_write_string(fp,"What license is "); edu_write_hilight_string(fp," eduencode "); edu_write_string(fp,"\rlicensed"); edu_write_string(fp," under?"); edu_write_correct_answer(fp,ANSWER_3); edu_write_string(fp,"\r\r"); edu_write_string(fp," GPL GPL GPL\r"); edu_write_string(fp," v.1 v.2 v.3\r"); edu_write_wait_for_answer(fp); edu_write_colors(fp,BACKGROUND_GREEN,BORDER_GREEN,HILIGHT_RED); edu_write_string(fp,"------------------------------\r\r"); edu_write_string(fp," Yes, that's correct."); edu_write_pause(fp,3000); edu_write_clear(fp); edu_write_string(fp,"Thank you for testing this. The\r"); edu_write_string(fp,"author also wishes to thank\r"); edu_write_string(fp,"AtariAge, and the Atari\r"); edu_write_string(fp,"Community for their\r"); edu_write_string(fp,"encouragement and support on\r"); edu_write_string(fp,"this project.\r\r\r"); edu_write_pause(fp,5000); edu_write_string(fp," end of tape."); edu_close_file(fp); return 0; } A video showing it all in action, is here: Still more to do... now, it's documenting everything... Any questions? Enjoy. -Thom eduencode.zip 12 Quote Link to comment Share on other sites More sharing options...
FULS Posted May 12, 2015 Share Posted May 12, 2015 Amazing!!! Thank you for the passion and time you have put into this project. Quote Link to comment Share on other sites More sharing options...
Xuel Posted May 13, 2015 Share Posted May 13, 2015 I seem to be getting some bit corruption: Any ideas what might be causing this? I'm using Altirra 2.60 same as you showed in the video. I do notice that my WAV file is slightly shorter than yours but all of the C source files are the same size. Perhaps there's some compiler-dependent thing going on? I'm using GCC under cygwin: ~/z/eduencode $ make cc -c -o eduencode.o eduencode.c ar ru libeduencode.a eduencode.o ar: creating libeduencode.a ranlib libeduencode.a cc -c -o test-eduencode.o test-eduencode.c cc -o test-eduencode test-eduencode.o -I. -L. -leduencode ~/z/eduencode $ ./test-eduencode.exe ~/z/eduencode $ ls -ln total 14965 -rw-r--r-- 1 1000 513 657 May 12 16:34 Makefile -rw-r--r-- 1 1000 513 6772 May 12 16:27 eduencode.c -rw-r--r-- 1 1000 513 1684 May 12 16:25 eduencode.h -rw-r--r-- 1 1000 513 5439 May 13 01:16 eduencode.o -rw-r--r-- 1 1000 513 6138 May 13 01:16 libeduencode.a -rw-r--r-- 1 1000 513 4275 May 12 17:28 test-eduencode.c -rwxr-xr-x 1 1000 513 71486 May 13 01:16 test-eduencode.exe -rw-r--r-- 1 1000 513 5731 May 13 01:16 test-eduencode.o -rw-r--r-- 1 1000 513 15200764 May 13 01:16 test_eduencode.wav ~/z/eduencode $ gcc --version gcc (GCC) 4.9.2 Copyright (C) 2014 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Quote Link to comment Share on other sites More sharing options...
phaeron Posted May 13, 2015 Share Posted May 13, 2015 Haven't compiled it locally to test, but it looks like the FSK encoder might be restarting at phase 0 at the beginning of each bit. This will introduce phase discontinuity glitches that can cause decoding errors. 1 Quote Link to comment Share on other sites More sharing options...
Xuel Posted May 13, 2015 Share Posted May 13, 2015 @phaeron As a quick test, I moved the phase variable out of edu_write_baud and made it global and now I don't have any corruption. So I think your diagnosis is correct. Thanks! @tschak909 I still don't understand why I'm getting a WAV file from test-eduencode.c that's exactly 41440 bytes smaller than yours (about 117ms?). Maybe you changed a delay amount between making the video and before creating the zip file? Though I've been watching and pausing the video and comparing it with the source code in your zip file and I can't see any obvious differences. 1 Quote Link to comment Share on other sites More sharing options...
tschak909 Posted May 13, 2015 Author Share Posted May 13, 2015 basically just moving phase out into global space? probably should rename it to __phase, then... Great catch, @phaeron. Now that I think about it, that should have been obvious...but that is the very first FSK modulator i've ever written, sorta just...guessed at it. @Xuel thanks for testing! Now I just need to find some time to write a real authoring tool. I want to make at least one complete set of tapes. -Thom 1 Quote Link to comment Share on other sites More sharing options...
tschak909 Posted May 16, 2015 Author Share Posted May 16, 2015 Hey guys, so... Roughly about 2am the other night, I had a crazy idea, to reimagine Strong Bad Email #45 - Techno, as an Edu System cassette Here's the result 9 Quote Link to comment Share on other sites More sharing options...
tschak909 Posted May 16, 2015 Author Share Posted May 16, 2015 Cassette image attached strongbad-techno.wav.zip Quote Link to comment Share on other sites More sharing options...
luckybuck Posted May 16, 2015 Share Posted May 16, 2015 So great Thom! Can't tell you. You are a miracle! What about publishing all that knowledge in the AtariWiki? Quote Link to comment Share on other sites More sharing options...
tschak909 Posted May 17, 2015 Author Share Posted May 17, 2015 would be great. IF I HAD AN ACCOUNT.. I signed up for one, many many years ago, and never ever got a reply. -Thom 1 Quote Link to comment Share on other sites More sharing options...
luckybuck Posted May 17, 2015 Share Posted May 17, 2015 What? Will return to you very(!) soon... Thanks. Quote Link to comment Share on other sites More sharing options...
tschak909 Posted May 21, 2015 Author Share Posted May 21, 2015 An Update from my side: Now that the archaeology of the master cartridge disassembly and forensic analysis of the tape format is completed, and the encoder functions, I am currently writing up a book detailing the entire "dig", and will be releasing it to the public once complete. It will consist of three major parts: * Introduction * Disassembling the Cartridge * Forensic Analysis of the Cassette Format The focus on this particular book is very much a "post mortem" of the Atari Educational System, with the intent of the book being viewed as a proper historical text deconstructing one of the earliest examples of both multimedia and computer based training.(and yes, the eduencode encoder will be printed in the book, in its entirety, along with a complete explanation of the code) I will then take the content of the book, and at the very least, take the reference bits and place onto AtariWiki, as this is the most logical place for it.-Thom 4 Quote Link to comment Share on other sites More sharing options...
+JAC! Posted May 21, 2015 Share Posted May 21, 2015 Hey guys, so... Roughly about 2am the other night, I had a crazy idea, to reimagine Strong Bad Email #45 - Techno, as an Edu System cassette Here's the result Awesome idea to show the possibilties. Laughed my a.. off. 1 Quote Link to comment Share on other sites More sharing options...
Kr0tki Posted May 28, 2015 Share Posted May 28, 2015 Thom, That's some nice piece of software! Thank you for your hard work on analysing the data format. I took the liberty of rewriting your library to use liba8cas, as it's an ideal candidate for that. liba8cas is the core of my tape conversion software, and it contains the FSK ecoder/decoder and can output both WAV and CAS files - therefore eduencode can now output them, too! basically just moving phase out into global space? probably should rename it to __phase, then...Using global variables in a library is generally a bad idea - it makes the library non-reentrant and/or not thread-safe.eduencode-a8cas.zip 4 Quote Link to comment Share on other sites More sharing options...
tschak909 Posted May 28, 2015 Author Share Posted May 28, 2015 Kr0tki, Thank you for the port, and the compliments. Can .cas files also handle the left channel audio track of a dual track tape? I did it to WAV, because I am publishing the code alongside the book I am writing, and wanted the code to be completely self contained, without any dependencies, and I wanted to be able to take the resulting files into an editing suite to drop in voiceover tracks. -Thom Quote Link to comment Share on other sites More sharing options...
Kr0tki Posted May 28, 2015 Share Posted May 28, 2015 Can .cas files also handle the left channel audio track of a dual track tape?No, not yet. The CAS format doesn't support audio tracks as of now. Quote Link to comment Share on other sites More sharing options...
tschak909 Posted May 28, 2015 Author Share Posted May 28, 2015 This is why I output WAV. The Edu format depends on it, as it is a lecturing and question/answer format. -Thom Quote Link to comment Share on other sites More sharing options...
tschak909 Posted May 30, 2015 Author Share Posted May 30, 2015 Has _anyone_ recorded output to tape and tried this with a real setup? I _really_ want to know if I need to handle timing marks more aggressively. -Thom Quote Link to comment Share on other sites More sharing options...
+Stephen Posted May 30, 2015 Share Posted May 30, 2015 I would love to test this, but my 410 needs a belt kit, and I am in the middle of moving houses. Sorry, but it will be at least 4 to 6 weeks before I can test this on real hardware. Quote Link to comment Share on other sites More sharing options...
+Allan Posted May 30, 2015 Share Posted May 30, 2015 Has _anyone_ recorded output to tape and tried this with a real setup? I _really_ want to know if I need to handle timing marks more aggressively. -Thom I'm recording it now to see if it works. Let you know what my results are soon. Allan 1 Quote Link to comment Share on other sites More sharing options...
tschak909 Posted May 31, 2015 Author Share Posted May 31, 2015 Thanks a ton, Allan. hopefully it will just work, and there won't be a need to go back and forth a few thousand times. -Thom Quote Link to comment Share on other sites More sharing options...
+Allan Posted May 31, 2015 Share Posted May 31, 2015 I tried it tonight a few times with no luck. I got the recording on the tape and I hear the voices/recording but I just get garbage characters and random color changes (I think). I'm not sure if I am making the recording right or not. I am going to put one of the Atari releases on a blank cassette and see if that works. Than I will know if it's my recording that is the problem. Allan Quote Link to comment Share on other sites More sharing options...
tschak909 Posted May 31, 2015 Author Share Posted May 31, 2015 strongbad-techno-normalized.zipDamn! What about this one? I normalized the data track to -1dB ... Quote Link to comment Share on other sites More sharing options...
+Allan Posted May 31, 2015 Share Posted May 31, 2015 I tried making a tape of a known working Atari tape and I see I need to play with the inputs a bit. Will try again tomorrow to get an original tape working, then I will know what to record at and go from there. Allan Quote Link to comment Share on other sites More sharing options...
luckybuck Posted June 4, 2015 Share Posted June 4, 2015 Hi together, was away for some days. Well, didn't we have an audio engineer here on AA, did we? If Altirra can read the files, then a lossless copy to a tape must also be possible. At least in theory... Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.