|
|
1.1 ! root 1: The Generator GNM log format is: ! 2: ! 3: header: ! 4: 0: 'G' ! 5: 1: 'N' ! 6: 2: 'M' ! 7: 3: fields per second (e.g. 50 or 60) ! 8: ! 9: interval = 0; ! 10: while (!EOF) { ! 11: data = readbyte()) // readbyte() reads the next byte from the file ! 12: if ((data & 0xF0) == 0) { ! 13: switch (data) { ! 14: case 0: /* start of field marker (1/50th or 1/60th second elapsed) */ ! 15: sampsperfield=(readbyte() << 8) + readbyte(); ! 16: case 1: /* FM port 0 */ ! 17: ymport=0; ymreg=readbyte(); ymdata=readbyte(); ! 18: case 2: /* FM port 1 */ ! 19: ymport=1; ymreg=readbyte(); ymdata=readbyte(); ! 20: case 3: /* PSG */ ! 21: write readbyte() to psg port; ! 22: case 4: /* escaped sample data and mark of interval */ ! 23: ymport=0; ymreg=0x2A; ymdata=readbyte(); interval=1; ! 24: case 5: /* no sample data this interval */ ! 25: interval=1; /* no change of register 0x2A */ ! 26: } ! 27: } else { ! 28: /* unescaped sameple data and mark of interval */ ! 29: ymport=0; ymreg=0x2A; ymdata=data; sample=1; ! 30: } ! 31: if (interval) { ! 32: interval = 0; ! 33: update sound; ! 34: } ! 35: } ! 36: ! 37: Rationale ! 38: ! 39: The GYM file format does not support samples. Where sample data has been ! 40: added to the GYM file format it is not possible to know where within the ! 41: time period of a field the sample(s) occured, so any players have to make ! 42: a guess. Samples within a GYM file are represented using an FM write which ! 43: consists of three bytes, this is a huge waste of space. ! 44: ! 45: Design ! 46: ! 47: The field is split into a distinct number of intervals in order to ! 48: increase accuracy. As an emulation format, the idea was to output X ! 49: intervals where X is the number of lines of display, as emulators work ! 50: in terms of video lines. The GNM format has been modified however to ! 51: cope with any number of intervals within a field. You could divide a ! 52: field into 4 events for example. This would mean 4 times the accuracy ! 53: in placing events (in time) than the GYM format. Of course, the higher ! 54: the number of intervals, the bigger the resulting file format. ! 55: ! 56: You can only accurately have one sample per interval because the interval ! 57: is the only thing that tells you where in time you are within a field. ! 58: Therefore, the GNM format uses the samples themselves as a marker for ! 59: each interval. If there is no sample, then a special marker is inserted ! 60: to represent no change. This makes the file format as concise as possible. ! 61: ! 62: Encoding ! 63: ! 64: Each field starts with a $0 byte marker followed by two bytes that indicate ! 65: the number of intervals for this field. ! 66: ! 67: Each interval is marked by a sample. The samples are placed directly in ! 68: the stream except for byte vales $0 to $f, in which case they are escaped ! 69: with a $4 byte. If there was no sample written in the interval period then ! 70: a $5 byte is inserted. ! 71: ! 72: Generator's implementation ! 73: ! 74: Generator works on a field at a time basis. Generator allocates a block ! 75: of memory, which expands if required, that contains what we would write ! 76: to disk assuming maximum samples are necessary (maximum in Generator's ! 77: case is the number of lines in the display, i.e. 262 for NTSC). Nominally ! 78: 8k is allocated for this purpose. ! 79: ! 80: YM/PSG writes are written into this block, however writes to FM address ! 81: $2a are held pending until the end of each line. At the end of the line ! 82: we write the (last) sample into the block (as-is or escaped with a $4 if ! 83: necessary, or $5 if no change to FM register $2a was made). ! 84: ! 85: At the end of a field we can then decide the number of intervals that we ! 86: wish to output into the file. If there were no samples in the entire ! 87: period then we remove all interval markers ($5 bytes) and set the number ! 88: of intervals to 0 for this field. We could leave a few intervals in to ! 89: make FM more accurate, but Generator doesn't do this (not sure if it's ! 90: necessary). ! 91: ! 92: Generator is of course open source so you are free to look at the ! 93: actual implementation.
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.