GE-115 Emulator
An Emulator of the General Electrics GE-115 computer
sat_batches.c
Go to the documentation of this file.
1#include "sat_batches.h"
2
3#include <stdio.h>
4#include <stdlib.h>
5#include <string.h>
6
7#include "cap.h"
8#include "transcode.h"
9
15
16struct sat_source {
17 const char *file;
19};
20
23 const struct sat_source *sources;
25 uint16_t image_entry;
26};
27
29 uint16_t addr;
30 uint8_t value;
31};
32
33static const struct sat_source src_cpu_functional[] = {
34 { "funktionalcpu.cap", SAT_SRC_AS_IS },
35};
36
37static const struct sat_source src_reader_a[] = {
38 { "reading-test-chain-01a.cap", SAT_SRC_AS_IS },
39};
40
41static const struct sat_source src_printer_mech[] = {
42 { "printermechanicaltest.cap", SAT_SRC_AS_IS },
43};
44
45/* Printer Mechanic Test startup: the deck issues PER 0x00,0x0126, whose order
46 * block is {00,40,00,4F,06,70} — a 79-byte "read unchanged" into 0x0670.
47 * In the real SAT stack that record comes from the required center card. The
48 * current scatter-image path has no physical center card, so synthesize the
49 * default raw reader bytes the diagnostic expects:
50 * col1 integrated, col2 no 2nd transport, col4 normal drum, col5 normal
51 * ribbon, col6 WITH END OF TEST HLT. The remaining bytes are left zero.
52 *
53 * Confidence:
54 * - 0x0673 / 0x0674 are directly tested by the deck as 0x01 (normal drum /
55 * ribbon path).
56 * - 0x0675 follows the manual's center-card column 6. Under the raw-reader
57 * low-byte model, a 9-punch collapses to 0x00, so WITH END OF TEST HLT is
58 * represented here as 0x00.
59 * - columns not yet evidenced by the code remain zero until more manual
60 * evidence is recovered. */
62 { 0x0670, 0x01 }, /* column 1: integrated subsystem */
63 { 0x0671, 0x01 }, /* column 2: 2nd transport absent */
64 { 0x0673, 0x01 }, /* column 4: normal drum */
65 { 0x0674, 0x01 }, /* column 5: normal ribbon */
66 { 0x0675, 0x00 }, /* column 6: with END OF TEST HLT */
67};
68
69static const struct sat_source src_control_program[] = {
70 { "control-program-cr.cap", SAT_SRC_SERIAL_LOADER_PLUS_BODY },
71};
72
73static const struct sat_source src_ls600_controller[] = {
74 { "sat-ls600.cap", SAT_SRC_SERIAL_LOADER_PLUS_BODY },
75 { "ls600-controller-test.cap", SAT_SRC_TRIM_TITLE_SUMMARY },
76};
77
78static const struct sat_source src_ls600_transcoder[] = {
79 { "sat-ls600.cap", SAT_SRC_SERIAL_LOADER_PLUS_BODY },
80 { "ls600-transcoder-test.cap", SAT_SRC_TRIM_TITLE_SUMMARY },
81};
82
83static const struct sat_source src_ls600_doe[] = {
84 { "sat-ls600.cap", SAT_SRC_SERIAL_LOADER_PLUS_BODY },
85 { "ls600-doe.cap", SAT_SRC_TRIM_TITLE_SUMMARY },
86};
87
88static const struct sat_batch_def sat_batches[] = {
89 {
90 { "cpu-functional", "CPU Functional Test",
91 "SAT step 1: the functional CPU deck staged through the scatter-image path.",
93 src_cpu_functional, (int)(sizeof(src_cpu_functional) / sizeof(src_cpu_functional[0])),
94 0x0000
95 },
96 {
97 { "card-reader-a", "Reading Test Channel A",
98 "SAT step 2: the captured card-reader test deck.", SAT_BATCH_IMAGE },
99 src_reader_a, (int)(sizeof(src_reader_a) / sizeof(src_reader_a[0])),
100 0x0000
101 },
102 {
103 { "printer-mechanical", "Printer Mechanical Test",
104 "SAT step 3: the line-printer deck staged through the scatter-image path, "
105 "with the required center card synthesized into the startup input buffer.",
107 src_printer_mech, (int)(sizeof(src_printer_mech) / sizeof(src_printer_mech[0])),
108 0x0118
109 },
110 {
111 { "control-program-cr", "Control Program CR",
112 "Control-program utility deck with the serial Hollerith loader kept.",
115 0x0000
116 },
117 {
118 { "ls600-controller-sat", "LS600 Controller SAT Batch",
119 "Sequencer Program followed by LS600 Controller Test, prepared per the SAT notes.",
122 0x0000
123 },
124 {
125 { "ls600-transcoder-sat", "LS600 Transcoder SAT Batch",
126 "Sequencer Program followed by LS600 Transcoder Test, prepared per the SAT notes.",
129 0x0000
130 },
131 {
132 { "ls600-doe-sat", "LS600 D.O.E. SAT Batch",
133 "Sequencer Program followed by the LS600 D.O.E. deck, prepared per the SAT notes.",
135 src_ls600_doe, (int)(sizeof(src_ls600_doe) / sizeof(src_ls600_doe[0])),
136 0x0000
137 },
138};
139
140static int row8_loader_card(const struct cap_deck *deck)
141{
142 int ncards = cap_num_cards(deck);
143 int limit = ncards < 5 ? ncards : 5;
144
145 for (int i = 1; i < limit; i++) {
146 const uint16_t *cols = cap_card_columns(deck, i);
147 if (cap_card_ncols(deck, i) >= 3 && cols && cols[2] == 0x0100)
148 return i;
149 }
150 return (ncards > 1) ? 1 : 0;
151}
152
153static int append_card_range(struct cap_deck *out, const struct cap_deck *src,
154 int first, int last_inclusive)
155{
156 for (int i = first; i <= last_inclusive; i++) {
157 int ncols = cap_card_ncols(src, i);
158 const uint16_t *cols = cap_card_columns(src, i);
159 if (ncols <= 0 || !cols)
160 continue;
161 if (cap_append_card(out, cols, ncols) != 0)
162 return -1;
163 }
164 return 0;
165}
166
167static int append_source(struct cap_deck *out, const char *path, enum sat_source_op op)
168{
169 struct cap_deck *src = cap_load(path);
170 int ncards;
171 int rc = -1;
172
173 if (!src)
174 return -1;
175
176 ncards = cap_num_cards(src);
177 switch (op) {
178 case SAT_SRC_AS_IS:
179 rc = append_card_range(out, src, 0, ncards - 1);
180 break;
182 rc = (ncards >= 3) ? append_card_range(out, src, 1, ncards - 2) : -1;
183 break;
185 int loader = row8_loader_card(src);
186 if (ncards < 7)
187 rc = -1;
188 else if (cap_append_card(out, cap_card_columns(src, loader),
189 cap_card_ncols(src, loader)) != 0)
190 rc = -1;
191 else
192 rc = append_card_range(out, src, 5, ncards - 2);
193 break;
194 }
195 default:
196 rc = -1;
197 break;
198 }
199
200 cap_free(src);
201 return rc;
202}
203
204static const struct sat_batch_def *sat_batch_def_find(const char *id)
205{
206 if (!id)
207 return NULL;
208 for (size_t i = 0; i < sizeof(sat_batches) / sizeof(sat_batches[0]); i++) {
209 if (strcmp(sat_batches[i].info.id, id) == 0)
210 return &sat_batches[i];
211 }
212 return NULL;
213}
214
215static void sat_apply_image_patches(const struct sat_batch_def *def, unsigned char *image)
216{
217 const struct sat_image_patch *patches = NULL;
218 size_t npatches = 0;
219
220 if (strcmp(def->info.id, "printer-mechanical") == 0) {
221 patches = printer_mech_center_card;
222 npatches = sizeof(printer_mech_center_card) / sizeof(printer_mech_center_card[0]);
223 }
224
225 for (size_t i = 0; i < npatches; i++)
226 image[patches[i].addr] = patches[i].value;
227}
228
229static void sat_note(char *note, size_t note_sz, const struct sat_batch_def *def)
230{
231 if (!note || note_sz == 0)
232 return;
233 snprintf(note, note_sz, "%s", def->info.summary);
234}
235
237{
238 return (int)(sizeof(sat_batches) / sizeof(sat_batches[0]));
239}
240
241const struct sat_batch_info *sat_batch_info_at(int idx)
242{
243 if (idx < 0 || idx >= sat_batch_count())
244 return NULL;
245 return &sat_batches[idx].info;
246}
247
248const struct sat_batch_info *sat_batch_find(const char *id)
249{
250 const struct sat_batch_def *def = sat_batch_def_find(id);
251 return def ? &def->info : NULL;
252}
253
254int sat_batch_prepare_image(const char *root, const char *id,
255 unsigned char *image,
256 unsigned *lo, unsigned *hi, uint16_t *entry,
257 char *note, size_t note_sz)
258{
259 char path[1024];
260 const struct sat_batch_def *def = sat_batch_def_find(id);
261 int rc;
262
263 if (!def || def->info.launch != SAT_BATCH_IMAGE ||
264 !root || !image || !lo || !hi || !entry || def->nsources != 1)
265 return -1;
266
267 snprintf(path, sizeof(path), "%s/%s", root, def->sources[0].file);
268 memset(image, 0, MEM_SIZE);
269 rc = cap_load_scattered(path, TC_COLBIN, image, lo, hi);
270 if (rc < 0)
271 return -1;
272
273 sat_apply_image_patches(def, image);
274 *entry = def->image_entry ? def->image_entry : (uint16_t)*lo;
275 sat_note(note, note_sz, def);
276 return 0;
277}
278
279int sat_batch_prepare_deck(const char *root, const char *id,
280 const char *out_path,
281 char *note, size_t note_sz)
282{
283 char path[1024];
284 struct cap_deck *out;
285 const struct sat_batch_def *def = sat_batch_def_find(id);
286
287 if (!def || def->info.launch != SAT_BATCH_READER || !root || !out_path)
288 return -1;
289
290 out = cap_create();
291 if (!out)
292 return -1;
293
294 for (int i = 0; i < def->nsources; i++) {
295 snprintf(path, sizeof(path), "%s/%s", root, def->sources[i].file);
296 if (append_source(out, path, def->sources[i].op) != 0) {
297 cap_free(out);
298 return -1;
299 }
300 }
301
302 if (cap_save(out, out_path) != 0) {
303 cap_free(out);
304 return -1;
305 }
306
307 cap_free(out);
308 sat_note(note, note_sz, def);
309 return 0;
310}
const uint16_t * cap_card_columns(const struct cap_deck *d, int i)
Definition cap.c:214
int cap_append_card(struct cap_deck *d, const uint16_t *cols, int ncols)
Definition cap.c:221
int cap_card_ncols(const struct cap_deck *d, int i)
Definition cap.c:207
struct cap_deck * cap_create(void)
Definition cap.c:195
int cap_num_cards(const struct cap_deck *d)
Definition cap.c:200
void cap_free(struct cap_deck *d)
Definition cap.c:263
struct cap_deck * cap_load(const char *path)
Definition cap.c:124
int cap_load_scattered(const char *path, int mode, unsigned char *image, unsigned *lo, unsigned *hi)
Definition cap.c:442
int cap_save(const struct cap_deck *d, const char *path)
Definition cap.c:238
#define MEM_SIZE
Definition ge.h:12
static const struct sat_batch_def * sat_batch_def_find(const char *id)
const struct sat_batch_info * sat_batch_find(const char *id)
int sat_batch_prepare_image(const char *root, const char *id, unsigned char *image, unsigned *lo, unsigned *hi, uint16_t *entry, char *note, size_t note_sz)
static const struct sat_source src_printer_mech[]
Definition sat_batches.c:41
static const struct sat_batch_def sat_batches[]
Definition sat_batches.c:88
sat_source_op
Definition sat_batches.c:10
@ SAT_SRC_AS_IS
Definition sat_batches.c:11
@ SAT_SRC_TRIM_TITLE_SUMMARY
Definition sat_batches.c:12
@ SAT_SRC_SERIAL_LOADER_PLUS_BODY
Definition sat_batches.c:13
static const struct sat_image_patch printer_mech_center_card[]
Definition sat_batches.c:61
static const struct sat_source src_ls600_controller[]
Definition sat_batches.c:73
static const struct sat_source src_control_program[]
Definition sat_batches.c:69
int sat_batch_count(void)
static void sat_apply_image_patches(const struct sat_batch_def *def, unsigned char *image)
static const struct sat_source src_ls600_doe[]
Definition sat_batches.c:83
static void sat_note(char *note, size_t note_sz, const struct sat_batch_def *def)
const struct sat_batch_info * sat_batch_info_at(int idx)
static const struct sat_source src_cpu_functional[]
Definition sat_batches.c:33
static const struct sat_source src_ls600_transcoder[]
Definition sat_batches.c:78
static int row8_loader_card(const struct cap_deck *deck)
static int append_card_range(struct cap_deck *out, const struct cap_deck *src, int first, int last_inclusive)
int sat_batch_prepare_deck(const char *root, const char *id, const char *out_path, char *note, size_t note_sz)
static int append_source(struct cap_deck *out, const char *path, enum sat_source_op op)
static const struct sat_source src_reader_a[]
Definition sat_batches.c:37
@ SAT_BATCH_IMAGE
Definition sat_batches.h:10
@ SAT_BATCH_READER
Definition sat_batches.h:11
Definition cap.c:35
int ncards
Definition cap.c:37
struct sat_batch_info info
Definition sat_batches.c:22
const struct sat_source * sources
Definition sat_batches.c:23
uint16_t image_entry
Definition sat_batches.c:25
const char * summary
Definition sat_batches.h:17
enum sat_batch_launch launch
Definition sat_batches.h:18
const char * id
Definition sat_batches.h:15
enum sat_source_op op
Definition sat_batches.c:18
const char * file
Definition sat_batches.c:17
@ TC_COLBIN
Definition transcode.h:22