Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
54 | pj | 1 | /* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */ |
2 | /* */ |
||
3 | /* This library is free software; you can redistribute it and/or */ |
||
4 | /* modify it without any restrictions. This library is distributed */ |
||
5 | /* in the hope that it will be useful, but without any warranty. */ |
||
6 | |||
7 | /* Multi-chipset support Copyright 1993 Harm Hanemaayer */ |
||
8 | /* partially copyrighted (C) 1993 by Hartmut Schirmer */ |
||
9 | |||
10 | /* 21 January 1995 - added vga_readscanline(), added support for */ |
||
11 | /* non 8-pixel aligned scanlines in 16 color mode. billr@rastergr.com */ |
||
12 | #include <stdio.h> |
||
13 | #include "vga.h" |
||
14 | #include "libvga.h" |
||
15 | #include "driver.h" |
||
16 | |||
17 | /* used to decompose color value into bits (for fast scanline drawing) */ |
||
18 | union bits { |
||
19 | struct { |
||
20 | unsigned char bit3; |
||
21 | unsigned char bit2; |
||
22 | unsigned char bit1; |
||
23 | unsigned char bit0; |
||
24 | } b; |
||
25 | unsigned int i; |
||
26 | }; |
||
27 | |||
28 | /* color decompositions */ |
||
29 | static union bits color16[16] = |
||
30 | { |
||
31 | { |
||
32 | {0, 0, 0, 0}}, |
||
33 | { |
||
34 | {0, 0, 0, 1}}, |
||
35 | { |
||
36 | {0, 0, 1, 0}}, |
||
37 | { |
||
38 | {0, 0, 1, 1}}, |
||
39 | { |
||
40 | {0, 1, 0, 0}}, |
||
41 | { |
||
42 | {0, 1, 0, 1}}, |
||
43 | { |
||
44 | {0, 1, 1, 0}}, |
||
45 | { |
||
46 | {0, 1, 1, 1}}, |
||
47 | { |
||
48 | {1, 0, 0, 0}}, |
||
49 | { |
||
50 | {1, 0, 0, 1}}, |
||
51 | { |
||
52 | {1, 0, 1, 0}}, |
||
53 | { |
||
54 | {1, 0, 1, 1}}, |
||
55 | { |
||
56 | {1, 1, 0, 0}}, |
||
57 | { |
||
58 | {1, 1, 0, 1}}, |
||
59 | { |
||
60 | {1, 1, 1, 0}}, |
||
61 | { |
||
62 | {1, 1, 1, 1}}}; |
||
63 | |||
64 | /* mask for end points in plane buffer mode */ |
||
65 | static unsigned char mask[8] = |
||
66 | { |
||
67 | 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01}; |
||
68 | /* display plane buffers (for fast scanline drawing) */ |
||
69 | /* 256 bytes -> max 2048 pixel per line (2/16 colors) */ |
||
70 | static unsigned char plane0[256]; |
||
71 | static unsigned char plane1[256]; |
||
72 | static unsigned char plane2[256]; |
||
73 | static unsigned char plane3[256]; |
||
74 | |||
75 | static inline void shifted_memcpy(void *dest_in, void *source_in, int len) |
||
76 | { |
||
77 | int *dest = dest_in; |
||
78 | int *source = source_in; |
||
79 | |||
80 | len >>= 2; |
||
81 | |||
82 | while (len--) |
||
83 | *dest++ = (*source++ << 8); |
||
84 | } |
||
85 | |||
86 | /* RGB_swapped_memcopy returns the amount of bytes unhandled */ |
||
87 | static inline int RGB_swapped_memcpy(char *dest, char *source, int len) |
||
88 | { |
||
89 | int rest, tmp; |
||
90 | |||
91 | tmp = len / 3; |
||
92 | rest = len - 3 * tmp; |
||
93 | len = tmp; |
||
94 | |||
95 | while (len--) { |
||
96 | *dest++ = source[2]; |
||
97 | *dest++ = source[1]; |
||
98 | *dest++ = source[0]; |
||
99 | source += 3; |
||
100 | } |
||
101 | |||
102 | return rest; |
||
103 | } |
||
104 | |||
105 | int vga_drawscanline(int line, unsigned char *colors) |
||
106 | { |
||
107 | if ((CI.colors == 2) || (CI.colors > 256)) |
||
108 | return vga_drawscansegment(colors, 0, line, CI.xbytes); |
||
109 | else |
||
110 | return vga_drawscansegment(colors, 0, line, CI.xdim); |
||
111 | } |
||
112 | |||
113 | #ifdef LIBC_MEMCPY |
||
114 | #define MEMCPY memcpy |
||
115 | #else |
||
116 | void MEMCPY(unsigned char *dst, unsigned char *src, size_t n) { |
||
117 | unsigned char *e; |
||
118 | e=src+n; |
||
119 | while(src<e) *(dst++)=*(src++); |
||
120 | } |
||
121 | #endif |
||
122 | |||
123 | int vga_drawscansegment(unsigned char *colors, int x, int y, int length) |
||
124 | { |
||
125 | /* both length and x must divide with 8 */ |
||
126 | /* no longer true (at least for 16 & 256 colors) */ |
||
127 | |||
128 | if (MODEX) |
||
129 | goto modeX; |
||
130 | switch (CI.colors) { |
||
131 | case 16: |
||
132 | { |
||
133 | int i, j, k, first, last, page, l1, l2; |
||
134 | int offset, eoffs, soffs, ioffs; |
||
135 | union bits bytes; |
||
136 | unsigned char *address; |
||
137 | |||
138 | k = 0; |
||
139 | soffs = ioffs = (x & 0x7); /* starting offset into first byte */ |
||
140 | eoffs = (x + length) & 0x7; /* ending offset into last byte */ |
||
141 | for (i = 0; i < length;) { |
||
142 | bytes.i = 0; |
||
143 | first = i; |
||
144 | last = i + 8 - ioffs; |
||
145 | if (last > length) |
||
146 | last = length; |
||
147 | for (j = first; j < last; j++, i++) |
||
148 | bytes.i = (bytes.i << 1) | color16[colors[j]].i; |
||
149 | plane0[k] = bytes.b.bit0; |
||
150 | plane1[k] = bytes.b.bit1; |
||
151 | plane2[k] = bytes.b.bit2; |
||
152 | plane3[k++] = bytes.b.bit3; |
||
153 | ioffs = 0; |
||
154 | } |
||
155 | if (eoffs) { |
||
156 | /* fixup last byte */ |
||
157 | k--; |
||
158 | bytes.i <<= (8 - eoffs); |
||
159 | plane0[k] = bytes.b.bit0; |
||
160 | plane1[k] = bytes.b.bit1; |
||
161 | plane2[k] = bytes.b.bit2; |
||
162 | plane3[k++] = bytes.b.bit3; |
||
163 | } |
||
164 | offset = (y * CI.xdim + x) / 8; |
||
165 | vga_setpage((page = offset >> 16)); |
||
166 | l1 = 0x10000 - (offset &= 0xffff); |
||
167 | /* k currently contains number of bytes to write */ |
||
168 | if (l1 > k) |
||
169 | l1 = k; |
||
170 | l2 = k - l1; |
||
171 | /* make k the index of the last byte to write */ |
||
172 | k--; |
||
173 | |||
174 | address = GM + offset; |
||
175 | |||
176 | /* disable Set/Reset Register */ |
||
177 | __svgalib_outgra(0x01,0x00); |
||
178 | |||
179 | /* write to all bits */ |
||
180 | __svgalib_outgra(0x08,0xff); |
||
181 | |||
182 | /* select write map mask register */ |
||
183 | __svgalib_outseq(0x02,0x01); |
||
184 | |||
185 | /* select read map mask register */ |
||
186 | __svgalib_outgra(0x04,0x00); |
||
187 | if (soffs) |
||
188 | plane0[0] |= *address & ~mask[soffs]; |
||
189 | if (eoffs && l2 == 0) |
||
190 | plane0[k] |= *(address + l1 - 1) & mask[eoffs]; |
||
191 | MEMCPY(address, plane0, l1); |
||
192 | |||
193 | /* write plane 1 */ |
||
194 | __svgalib_outseq(0x02,0x02); |
||
195 | /* read plane 1 */ |
||
196 | __svgalib_outgra(0x04,0x01); |
||
197 | if (soffs) |
||
198 | plane1[0] |= *address & ~mask[soffs]; |
||
199 | if (eoffs && l2 == 0) |
||
200 | plane1[k] |= *(address + l1 - 1) & mask[eoffs]; |
||
201 | MEMCPY(address, plane1, l1); |
||
202 | |||
203 | /* write plane 2 */ |
||
204 | __svgalib_outseq(0x02,0x04); |
||
205 | /* read plane 2 */ |
||
206 | __svgalib_outgra(0x04,0x02); |
||
207 | if (soffs) |
||
208 | plane2[0] |= *address & ~mask[soffs]; |
||
209 | if (eoffs && l2 == 0) |
||
210 | plane2[k] |= *(address + l1 - 1) & mask[eoffs]; |
||
211 | MEMCPY(address, plane2, l1); |
||
212 | |||
213 | /* write plane 3 */ |
||
214 | __svgalib_outseq(0x02,0x08); |
||
215 | /* read plane 3 */ |
||
216 | __svgalib_outgra(0x04,0x03); |
||
217 | if (soffs) |
||
218 | plane3[0] |= *address & ~mask[soffs]; |
||
219 | if (eoffs && l2 == 0) |
||
220 | plane3[k] |= *(address + l1 - 1) & mask[eoffs]; |
||
221 | MEMCPY(address, plane3, l1); |
||
222 | |||
223 | if (l2 > 0) { |
||
224 | vga_setpage(page + 1); |
||
225 | |||
226 | /* write plane 0 */ |
||
227 | __svgalib_outseq(0x02,0x01); |
||
228 | if (eoffs) { |
||
229 | /* read plane 0 */ |
||
230 | __svgalib_outgra(0x04,0x00); |
||
231 | plane0[k] |= *(GM + l2 - 1) & mask[eoffs]; |
||
232 | } |
||
233 | MEMCPY(GM, &plane0[l1], l2); |
||
234 | |||
235 | /* write plane 1 */ |
||
236 | __svgalib_outseq(0x02,0x02); |
||
237 | if (eoffs) { |
||
238 | /* read plane 1 */ |
||
239 | __svgalib_outgra(0x04,0x01); |
||
240 | plane1[k] |= *(GM + l2 - 1) & mask[eoffs]; |
||
241 | } |
||
242 | MEMCPY(GM, &plane1[l1], l2); |
||
243 | |||
244 | /* write plane 2 */ |
||
245 | __svgalib_outseq(0x02,0x04); |
||
246 | if (eoffs) { |
||
247 | /* read plane 2 */ |
||
248 | __svgalib_outgra(0x04,0x02); |
||
249 | plane2[k] |= *(GM + l2 - 1) & mask[eoffs]; |
||
250 | } |
||
251 | MEMCPY(GM, &plane2[l1], l2); |
||
252 | |||
253 | /* write plane 3 */ |
||
254 | __svgalib_outseq(0x02,0x08); |
||
255 | if (eoffs) { |
||
256 | /* read plane 3 */ |
||
257 | __svgalib_outgra(0x04,0x03); |
||
258 | plane3[k] |= *(GM + l2 - 1) & mask[eoffs]; |
||
259 | } |
||
260 | MEMCPY(GM, &plane3[l1], l2); |
||
261 | } |
||
262 | /* restore map mask register */ |
||
263 | __svgalib_outseq(0x02,0x0f); |
||
264 | |||
265 | /* enable Set/Reset Register */ |
||
266 | __svgalib_outgra(0x01,0x0f); |
||
267 | } |
||
268 | break; |
||
269 | case 2: |
||
270 | { |
||
271 | /* disable Set/Reset Register */ |
||
272 | __svgalib_outgra(0x01,0x00); |
||
273 | |||
274 | /* write to all bits */ |
||
275 | __svgalib_outgra(0x08,0xff); |
||
276 | |||
277 | /* write to all planes */ |
||
278 | __svgalib_outseq(0x02,0x0f); |
||
279 | |||
280 | MEMCPY(GM + (y * CI.xdim + x) / 8, colors, length); |
||
281 | |||
282 | /* restore map mask register */ |
||
283 | __svgalib_outseq(0x02,0x0f); |
||
284 | |||
285 | /* enable Set/Reset Register */ |
||
286 | __svgalib_outgra(0x01,0x0f); |
||
287 | } |
||
288 | break; |
||
289 | case 256: |
||
290 | { |
||
291 | switch (CM) { |
||
292 | case G320x200x256: /* linear addressing - easy and fast */ |
||
293 | MEMCPY(GM + (y * CI.xdim + x), colors, length); |
||
294 | return 0; |
||
295 | case G320x240x256: |
||
296 | case G320x400x256: |
||
297 | case G360x480x256: |
||
298 | case G400x300x256X: |
||
299 | modeX: |
||
300 | { |
||
301 | int first, offset, pixel, plane; |
||
302 | |||
303 | for (plane = 0; plane < 4; plane++) { |
||
304 | /* select plane */ |
||
305 | __svgalib_outseq(0x02,1 << plane ); |
||
306 | |||
307 | pixel = ((4 - (x & 3) + plane) & 3); |
||
308 | first = (y * CI.xdim + x) / 4; |
||
309 | if((x & 3) + pixel > 3) |
||
310 | first++; |
||
311 | for (offset = first; pixel < length; offset++) { |
||
312 | *(GM+offset) = colors[pixel]; |
||
313 | pixel += 4; |
||
314 | } |
||
315 | } |
||
316 | } |
||
317 | return 0; |
||
318 | } |
||
319 | { |
||
320 | unsigned long offset; |
||
321 | int segment, free; |
||
322 | |||
323 | SegmentedCopy: |
||
324 | offset = y * CI.xbytes + x; |
||
325 | if (__svgalib_modeinfo_linearset & IS_LINEAR ) { |
||
326 | MEMCPY(LINEAR_POINTER+offset, colors, length); |
||
327 | } else { |
||
328 | segment = offset >> 16; |
||
329 | free = ((segment + 1) << 16) - offset; |
||
330 | offset &= 0xFFFF; |
||
331 | |||
332 | if (free < length) { |
||
333 | vga_setpage(segment); |
||
334 | MEMCPY(GM + offset, colors, free); |
||
335 | vga_setpage(segment + 1); |
||
336 | MEMCPY(GM, colors + free, length - free); |
||
337 | } else { |
||
338 | vga_setpage(segment); |
||
339 | MEMCPY(GM + offset, colors, length); |
||
340 | } |
||
341 | } |
||
342 | } |
||
343 | } |
||
344 | break; |
||
345 | case 32768: |
||
346 | case 65536: |
||
347 | x *= 2; |
||
348 | goto SegmentedCopy; |
||
349 | case 1 << 24: |
||
350 | if (__svgalib_cur_info.bytesperpixel == 4) { |
||
351 | x <<= 2; |
||
352 | if (MODEFLAGS & RGB_MISORDERED) { |
||
353 | unsigned long offset; |
||
354 | int segment, free; |
||
355 | |||
356 | offset = y * CI.xbytes + x; |
||
357 | if (__svgalib_modeinfo_linearset & IS_LINEAR ) { |
||
358 | shifted_memcpy(LINEAR_POINTER+offset, colors, length); |
||
359 | } else { |
||
360 | segment = offset >> 16; |
||
361 | free = ((segment + 1) << 16) - offset; |
||
362 | offset &= 0xFFFF; |
||
363 | |||
364 | if (free < length) { |
||
365 | vga_setpage(segment); |
||
366 | shifted_memcpy(GM + offset, colors, free); |
||
367 | vga_setpage(segment + 1); |
||
368 | shifted_memcpy(GM, colors + free, length - free); |
||
369 | } else { |
||
370 | vga_setpage(segment); |
||
371 | shifted_memcpy(GM + offset, colors, length); |
||
372 | } |
||
373 | } |
||
374 | } else { |
||
375 | goto SegmentedCopy; |
||
376 | } |
||
377 | break; |
||
378 | } |
||
379 | x *= 3; |
||
380 | if (MODEFLAGS & RGB_MISORDERED) { |
||
381 | unsigned long offset; |
||
382 | int segment, free; |
||
383 | |||
384 | offset = y * CI.xbytes + x; |
||
385 | if (__svgalib_modeinfo_linearset & IS_LINEAR ) { |
||
386 | RGB_swapped_memcpy(LINEAR_POINTER+offset, colors, length); |
||
387 | } else { |
||
388 | segment = offset >> 16; |
||
389 | free = ((segment + 1) << 16) - offset; |
||
390 | offset &= 0xFFFF; |
||
391 | |||
392 | if (free < length) { |
||
393 | int i; |
||
394 | |||
395 | vga_setpage(segment); |
||
396 | i = RGB_swapped_memcpy(GM + offset, colors, free); |
||
397 | colors += (free - i); |
||
398 | |||
399 | switch (i) { |
||
400 | case 2: |
||
401 | *(GM+0xfffe) = colors[2]; |
||
402 | *(GM+0xffff) = colors[1]; |
||
403 | break; |
||
404 | case 1: |
||
405 | *(GM+0xffff) = colors[2]; |
||
406 | break; |
||
407 | } |
||
408 | |||
409 | vga_setpage(segment + 1); |
||
410 | |||
411 | switch (i) { |
||
412 | case 1: |
||
413 | *(GM+1) = colors[0]; |
||
414 | *(GM) = colors[1]; |
||
415 | i = 3 - i; |
||
416 | free += i; |
||
417 | colors += 3; |
||
418 | break; |
||
419 | case 2: |
||
420 | *(GM) = colors[0]; |
||
421 | i = 3 - i; |
||
422 | free += i; |
||
423 | colors += 3; |
||
424 | break; |
||
425 | } |
||
426 | |||
427 | RGB_swapped_memcpy(GM + i, colors, length - free); |
||
428 | } else { |
||
429 | vga_setpage(segment); |
||
430 | RGB_swapped_memcpy(GM + offset, colors, length); |
||
431 | } |
||
432 | } |
||
433 | } else { |
||
434 | goto SegmentedCopy; |
||
435 | } |
||
436 | } |
||
437 | |||
438 | return 0; |
||
439 | } |
||
440 | |||
441 | int vga_getscansegment(unsigned char *colors, int x, int y, int length) |
||
442 | { |
||
443 | |||
444 | if (MODEX) |
||
445 | goto modeX2; |
||
446 | switch (CI.colors) { |
||
447 | case 16: |
||
448 | { |
||
449 | int i, k, page, l1, l2; |
||
450 | int offset, eoffs, soffs, nbytes, bit; |
||
451 | unsigned char *address; |
||
452 | unsigned char color; |
||
453 | k = 0; |
||
454 | soffs = (x & 0x7); /* starting offset into first byte */ |
||
455 | eoffs = (x + length) & 0x7; /* ending offset into last byte */ |
||
456 | offset = (y * CI.xdim + x) / 8; |
||
457 | vga_setpage((page = offset >> 16)); |
||
458 | l1 = 0x10000 - (offset &= 0xffff); |
||
459 | if (soffs) |
||
460 | nbytes = (length - (8 - soffs)) / 8 + 1; |
||
461 | else |
||
462 | nbytes = length / 8; |
||
463 | if (eoffs) |
||
464 | nbytes++; |
||
465 | if (l1 > nbytes) |
||
466 | l1 = nbytes; |
||
467 | l2 = nbytes - l1; |
||
468 | address = GM + offset; |
||
469 | /* disable Set/Reset Register */ |
||
470 | __svgalib_outgra(0x01,0x00); |
||
471 | /* read plane 0 */ |
||
472 | __svgalib_outgra(0x04,0x00); |
||
473 | memcpy(plane0, address, l1); |
||
474 | /* read plane 1 */ |
||
475 | __svgalib_outgra(0x04,0x01); |
||
476 | memcpy(plane1, address, l1); |
||
477 | /* read plane 2 */ |
||
478 | __svgalib_outgra(0x04,0x02); |
||
479 | memcpy(plane2, address, l1); |
||
480 | /* read plane 3 */ |
||
481 | __svgalib_outgra(0x04,0x03); |
||
482 | memcpy(plane3, address, l1); |
||
483 | if (l2 > 0) { |
||
484 | vga_setpage(page + 1); |
||
485 | /* read plane 0 */ |
||
486 | __svgalib_outgra(0x04,0x00); |
||
487 | memcpy(&plane0[l1], GM, l2); |
||
488 | /* read plane 1 */ |
||
489 | __svgalib_outgra(0x04,0x01); |
||
490 | memcpy(&plane1[l1], GM, l2); |
||
491 | /* read plane 2 */ |
||
492 | __svgalib_outgra(0x04,0x02); |
||
493 | memcpy(&plane2[l1], GM, l2); |
||
494 | /* read plane 3 */ |
||
495 | __svgalib_outgra(0x04,0x03); |
||
496 | memcpy(&plane3[l1], GM, l2); |
||
497 | } |
||
498 | /* enable Set/Reset Register */ |
||
499 | __svgalib_outgra(0x01,0x0f); |
||
500 | k = 0; |
||
501 | for (i = 0; i < length;) { |
||
502 | for (bit = 7 - soffs; bit >= 0 && i < length; bit--, i++) { |
||
503 | color = (plane0[k] & (1 << bit) ? 1 : 0); |
||
504 | color |= (plane1[k] & (1 << bit) ? 1 : 0) << 1; |
||
505 | color |= (plane2[k] & (1 << bit) ? 1 : 0) << 2; |
||
506 | color |= (plane3[k] & (1 << bit) ? 1 : 0) << 3; |
||
507 | colors[i] = color; |
||
508 | } |
||
509 | k++; |
||
510 | soffs = 0; |
||
511 | } |
||
512 | } |
||
513 | break; |
||
514 | case 2: |
||
515 | { |
||
516 | /* disable Set/Reset Register */ |
||
517 | __svgalib_outgra(0x01,0x00); |
||
518 | /* read from plane 0 */ |
||
519 | __svgalib_outseq(0x04,0x00); |
||
520 | memcpy(colors, GM + (y * CI.xdim + x) / 8, length); |
||
521 | /* enable Set/Reset Register */ |
||
522 | __svgalib_outgra(0x01,0x0f); |
||
523 | } |
||
524 | break; |
||
525 | case 256: |
||
526 | { |
||
527 | switch (CM) { |
||
528 | case G320x200x256: /* linear addressing - easy and fast */ |
||
529 | memcpy(colors, GM + y * CI.xdim + x, length); |
||
530 | return 0; |
||
531 | case G320x240x256: |
||
532 | case G320x400x256: |
||
533 | case G360x480x256: |
||
534 | case G400x300x256X: |
||
535 | modeX2: |
||
536 | { |
||
537 | int first, offset, pixel, plane; |
||
538 | for (plane = 0; plane < 4; plane++) { |
||
539 | /* select plane */ |
||
540 | __svgalib_outgra(0x04, plane); |
||
541 | pixel = ((4 - (x & 3) + plane) & 3); |
||
542 | first = (y * CI.xdim + x) / 4; |
||
543 | if((x & 3) + pixel > 3) |
||
544 | first++; |
||
545 | for (offset = first; pixel < length; offset++) { |
||
546 | colors[pixel] = gr_readb(offset); |
||
547 | pixel += 4; |
||
548 | } |
||
549 | } |
||
550 | } |
||
551 | return 0; |
||
552 | } |
||
553 | { |
||
554 | unsigned long offset; |
||
555 | int segment, free; |
||
556 | SegmentedCopy2: |
||
557 | offset = y * CI.xbytes + x; |
||
558 | if (__svgalib_modeinfo_linearset & IS_LINEAR ) { |
||
559 | memcpy(colors, LINEAR_POINTER+offset, length); |
||
560 | } else { |
||
561 | segment = offset >> 16; |
||
562 | free = ((segment + 1) << 16) - offset; |
||
563 | offset &= 0xFFFF; |
||
564 | if (free < length) { |
||
565 | vga_setpage(segment); |
||
566 | memcpy(colors, GM + offset, free); |
||
567 | vga_setpage(segment + 1); |
||
568 | memcpy(colors + free, GM, length - free); |
||
569 | } else { |
||
570 | vga_setpage(segment); |
||
571 | memcpy(colors, GM + offset, length); |
||
572 | } |
||
573 | } |
||
574 | } |
||
575 | } |
||
576 | break; |
||
577 | case 32768: |
||
578 | case 65536: |
||
579 | x *= 2; |
||
580 | goto SegmentedCopy2; |
||
581 | case 1 << 24: |
||
582 | if (__svgalib_cur_info.bytesperpixel == 4) { |
||
583 | x<<=2; |
||
584 | } else { |
||
585 | x *= 3; |
||
586 | } |
||
587 | goto SegmentedCopy2; |
||
588 | } |
||
589 | return 0; |
||
590 | } |