00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <p24FJ64GA002.h>
00021
00022 #include "types.h"
00023 #include "table.h"
00024
00025 #include "librtc.h"
00026 #include "libfontx2.h"
00027 #include "libvideo.h"
00028
00029
00030
00031
00032
00033 #define abs(a) (((a)>0) ? (a) : -(a))
00034
00035
00036 #define NTSC_SYNC LATBbits.LATB12
00037 #define NTSC_VIDEO LATBbits.LATB13
00038
00039
00040 #define NTSC_LINE 263
00041 #define NTSC_LINE_SYNC 13
00042 #define NTSC_LINE_SPACE_TOP 29
00043
00044
00045 #define NTSC_DEFAULT_FCY cpu_fcy[0]
00046 #define NTSC_HORIZON_PULSE 1015
00047 #define NTSC_SERRATION_PULSE 936
00048 #define NTSC_EQUALIZING_PULSE 70
00049 #define NTSC_LEFT_SPACE 180
00050 #define NTSC_VIDEO_WIDTH 256
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 static unsigned int __attribute__((far)) video_memory[ NTSC_VRAM_SIZE / 2 ];
00063
00064
00065 NTSC_T ntsc = {
00066 video_memory,
00067 0,
00068
00069 {
00070 video_memory,
00071 NTSC_LINE,
00072 NTSC_LINE_SYNC,
00073 NTSC_LINE_SYNC + NTSC_LINE_SPACE_TOP,
00074 NTSC_LINE_SYNC + NTSC_LINE_SPACE_TOP + NTSC_HEIGHT,
00075 NTSC_HORIZON_PULSE,
00076 NTSC_SERRATION_PULSE,
00077 NTSC_EQUALIZING_PULSE,
00078 NTSC_LEFT_SPACE,
00079 NTSC_WIDTH,
00080 0x0000,
00081 0x0000,
00082 0x0000,
00083 },
00084
00085 {
00086 video_memory,
00087 NTSC_LINE,
00088 NTSC_LINE_SYNC,
00089 NTSC_LINE_SYNC + NTSC_LINE_SPACE_TOP + 10,
00090 NTSC_LINE_SYNC + NTSC_LINE_SPACE_TOP + 10 + NTSC_HEIGHT,
00091 NTSC_HORIZON_PULSE,
00092 NTSC_SERRATION_PULSE,
00093 NTSC_EQUALIZING_PULSE,
00094 NTSC_LEFT_SPACE,
00095 NTSC_WIDTH,
00096 0x0000,
00097 0x0000,
00098 0x0000,
00099 },
00100
00101 };
00102
00103
00104 VIDEO_T video;
00105
00106
00107
00108
00109
00110 static void VIDEO_init_superimpose(void);
00111
00112
00113
00114
00115
00116 void VIDEO_init(void)
00117 {
00118
00119 video.cx = 0;
00120 video.cy = 0;
00121 VIDEO_vram_clear(0xaaaa);
00122
00123
00124 VIDEO_line( 1, 1, NTSC_WIDTH - 2, 1);
00125 VIDEO_line( 1, 1, 1, NTSC_HEIGHT - 1);
00126 VIDEO_line(NTSC_WIDTH - 2, 1, NTSC_WIDTH - 2, NTSC_HEIGHT - 1);
00127 VIDEO_line( 1, NTSC_HEIGHT - 1, NTSC_WIDTH - 2, NTSC_HEIGHT - 1);
00128
00129 VIDEO_line( 2, 2, NTSC_WIDTH - 3, 2);
00130 VIDEO_line( 2, 2, 2, NTSC_HEIGHT - 2);
00131 VIDEO_line(NTSC_WIDTH - 3, 2, NTSC_WIDTH - 3, NTSC_HEIGHT - 2);
00132 VIDEO_line( 2, NTSC_HEIGHT - 2, NTSC_WIDTH - 3, NTSC_HEIGHT - 2);
00133
00134 VIDEO_line( 3, 3, NTSC_WIDTH - 4, 3);
00135 VIDEO_line( 3, 3, 3, NTSC_HEIGHT - 3);
00136 VIDEO_line(NTSC_WIDTH - 4, 3, NTSC_WIDTH - 4, NTSC_HEIGHT - 3);
00137 VIDEO_line( 3, NTSC_HEIGHT - 3, NTSC_WIDTH - 4, NTSC_HEIGHT - 3);
00138
00139 VIDEO_line( 4, 4, NTSC_WIDTH - 5, 4);
00140 VIDEO_line( 4, 4, 4, NTSC_HEIGHT - 4);
00141 VIDEO_line(NTSC_WIDTH - 5, 4, NTSC_WIDTH - 5, NTSC_HEIGHT - 4);
00142 VIDEO_line( 4, NTSC_HEIGHT - 4, NTSC_WIDTH - 5, NTSC_HEIGHT - 4);
00143
00144
00145 VIDEO_init_clock();
00146 RPOR6bits.RP13R = 7;
00147
00148 if(ntsc.monitor.video_width > NTSC_WIDTH) ntsc.monitor.video_width = NTSC_WIDTH;
00149 ntsc.monitor.video_width = ntsc.monitor.video_width >> 4;
00150 ntsc.superimpose.video_width = ntsc.monitor.video_width;
00151
00152
00153 SPI1CON1 = 0b0000010000110111;
00154 SPI1CON2 = 0b0000000000000000;
00155 SPI1STAT = 0b1000000000000000;
00156 IPC2bits.SPI1IP = 7;
00157 IEC0bits.SPI1IE = 1;
00158 IFS0bits.SPI1IF = 0;
00159 IPC0bits.OC1IP = 7;
00160 IEC0bits.OC1IE = 1;
00161 IFS0bits.OC1IF = 0;
00162 IPC1bits.OC2IP = 7;
00163 IEC0bits.OC2IE = 1;
00164 IFS0bits.OC2IF = 0;
00165
00166 PR2 = ntsc.monitor.horizon_pulse;
00167 TMR2 = 0x0000;
00168 IPC1bits.T2IP = 7;
00169 IEC0bits.T2IE = 1;
00170 IFS0bits.T2IF = 0;
00171
00172
00173 T2CON = 0b1000000000000000;
00174
00175
00176 VIDEO_init_superimpose();
00177
00178 return;
00179 }
00180
00181 static void VIDEO_init_superimpose(void)
00182 {
00183 RPOR7bits.RP15R = 10;
00184
00185
00186 RPINR0bits.INT1R = 10;
00187 INTCON2bits.INT1EP = 1;
00188 IPC5bits.INT1IP = 6;
00189 IEC1bits.INT1IE = 1;
00190 IFS1bits.INT1IF = 0;
00191
00192
00193 RPINR1bits.INT2R = 11;
00194 INTCON2bits.INT2EP = 0;
00195 IPC7bits.INT2IP = 6;
00196 IEC1bits.INT2IE = 1;
00197 IFS1bits.INT2IF = 0;
00198
00199
00200
00201 SPI2CON1 = 0b0000010000110111;
00202 SPI2CON2 = 0b0000000000000000;
00203 SPI2STAT = 0b1000000000000000;
00204 IPC8bits.SPI2IP = 6;
00205 IEC2bits.SPI2IE = 1;
00206 IFS2bits.SPI2IF = 0;
00207
00208 IPC6bits.OC3IP = 6;
00209 IEC1bits.OC3IE = 0;
00210 IFS1bits.OC3IF = 0;
00211
00212 PR3 = 0xffff;
00213 TMR3 = 0x0000;
00214 T3CON = 0x8000;
00215 IPC2bits.T3IP = 6;
00216 IEC0bits.T3IE = 1;
00217 IFS0bits.T3IF = 0;
00218
00219 return;
00220 }
00221
00222
00223
00224
00225
00226 void VIDEO_init_clock(void)
00227 {
00228 ntsc.monitor.horizon_pulse = (double)NTSC_HORIZON_PULSE * ((double)cpu_fcy[ OSCTUN ] / (double)NTSC_DEFAULT_FCY);
00229 ntsc.monitor.serration_pulse = (double)NTSC_SERRATION_PULSE * ((double)cpu_fcy[ OSCTUN ] / (double)NTSC_DEFAULT_FCY);
00230 ntsc.monitor.equalizing_pulse = (double)NTSC_EQUALIZING_PULSE * ((double)cpu_fcy[ OSCTUN ] / (double)NTSC_DEFAULT_FCY);
00231 ntsc.monitor.left_space = (double)NTSC_LEFT_SPACE * ((double)cpu_fcy[ OSCTUN ] / (double)NTSC_DEFAULT_FCY);
00232 ntsc.monitor.video_width = (double)NTSC_VIDEO_WIDTH * ((double)cpu_fcy[ OSCTUN ] / (double)NTSC_DEFAULT_FCY);
00233
00234 ntsc.superimpose.left_space = (double)60 * ((double)cpu_fcy[ OSCTUN ] / (double)NTSC_DEFAULT_FCY);
00235
00236 return;
00237 }
00238
00239
00240
00241
00242
00243 void __attribute__((interrupt, no_auto_psv, shadow)) _T2Interrupt(void)
00244 {
00245 IFS0bits.T2IF = 0;
00246 NTSC_SYNC = 0;
00247 ntsc.monitor.vsync++;
00248
00249
00250 if(ntsc.monitor.vsync < ntsc.monitor.line_sync){
00251 OC1R = ntsc.monitor.serration_pulse;
00252 OC1CON = 0x0001;
00253 ntsc.output = 0;
00254
00255
00256 } else if(ntsc.monitor.vsync < ntsc.monitor.line_space_top){
00257 OC1R = ntsc.monitor.equalizing_pulse;
00258 OC1CON = 0x0001;
00259
00260
00261 } else if(ntsc.monitor.vsync < ntsc.monitor.line_video){
00262 OC1R = ntsc.monitor.equalizing_pulse;
00263 OC1CON = 0x0001;
00264 OC2R = ntsc.monitor.left_space;
00265 OC2CON = 0x0001;
00266
00267
00268 } else if(ntsc.monitor.vsync < ntsc.monitor.line - 1){
00269 OC1R = ntsc.monitor.equalizing_pulse;
00270 OC1CON = 0x0001;
00271
00272 } else {
00273 OC1R = ntsc.monitor.equalizing_pulse;
00274 OC1CON = 0x0001;
00275 PR2 = ntsc.monitor.horizon_pulse;
00276 ntsc.monitor.vsync = 0;
00277 ntsc.monitor.vram = ntsc.vram;
00278
00279
00280 RPOR7bits.RP15R = 0;
00281 LATBbits.LATB15 = 1;
00282 ntsc.output = 0;
00283
00284 }
00285
00286 return;
00287 }
00288
00289 void __attribute__((interrupt, no_auto_psv, shadow)) _OC1Interrupt(void)
00290 {
00291 IFS0bits.OC1IF = 0;
00292 NTSC_SYNC = 1;
00293 return;
00294 }
00295
00296
00297 void __attribute__((interrupt, no_auto_psv, shadow)) _OC2Interrupt(void)
00298 {
00299 unsigned int dummy;
00300
00301 IFS0bits.OC2IF = 0;
00302
00303 SPI1BUF = *ntsc.monitor.vram++;
00304 ntsc.monitor.hsync = 2;
00305 while(SPI1STATbits.SPITBF);
00306 dummy = SPI1BUF;
00307 SPI1BUF = *ntsc.monitor.vram++;
00308 return;
00309 }
00310
00311 void __attribute__((interrupt, no_auto_psv, shadow)) _SPI1Interrupt(void)
00312 {
00313 unsigned int dummy;
00314
00315 IFS0bits.SPI1IF = 0;
00316
00317 if(ntsc.monitor.hsync == 0){
00318 SPI1BUF = (*ntsc.monitor.vram++) & 0x7fff;
00319 ntsc.monitor.hsync++;
00320
00321 } else if(ntsc.monitor.hsync < ntsc.monitor.video_width - 1){
00322 SPI1BUF = *ntsc.monitor.vram++;
00323 ntsc.monitor.hsync++;
00324
00325 } else if(ntsc.monitor.hsync < ntsc.monitor.video_width){
00326 SPI1BUF = (*ntsc.monitor.vram++) & 0xfffe;
00327 ntsc.monitor.hsync++;
00328
00329 } else {
00330 for(;ntsc.monitor.hsync < (NTSC_WIDTH >> 4); ntsc.monitor.hsync++){
00331 ntsc.monitor.vram++;
00332 }
00333 }
00334
00335 dummy = SPI1BUF;
00336 return;
00337 }
00338
00339
00340
00341
00342
00343 void __attribute__((interrupt, auto_psv)) _INT1Interrupt(void)
00344 {
00345 unsigned int dummy;
00346
00347 IFS1bits.INT1IF = 0;
00348
00349
00350 IEC0bits.T2IE = 0;
00351
00352
00353 VIDEO_init_superimpose();
00354 ntsc.output = 1;
00355
00356 dummy = SPI2BUF;
00357 ntsc.superimpose.vram = ntsc.vram;
00358 ntsc.superimpose.vsync = 0;
00359
00360 return;
00361 }
00362
00363
00364 void __attribute__((interrupt, auto_psv)) _INT2Interrupt(void)
00365 {
00366 unsigned int dummy;
00367
00368 IFS1bits.INT2IF = 0;
00369
00370 ntsc.superimpose.vsync++;
00371
00372
00373 if(ntsc.superimpose.vsync < ntsc.superimpose.line_space_top){
00374
00375
00376
00377 } else if (ntsc.superimpose.vsync < ntsc.superimpose.line_video){
00378 TMR3 = 0x0000;
00379 OC3R = ntsc.superimpose.left_space;
00380 OC3CON = 0b0000000000001001;
00381 IEC1bits.OC3IE = 1;
00382 dummy = SPI2BUF;
00383
00384 } else {
00385 IEC1bits.INT2IE = 0;
00386 dummy = SPI2BUF;
00387 }
00388
00389 return;
00390 }
00391
00392 void __attribute__((interrupt, auto_psv)) _OC3Interrupt(void)
00393 {
00394 unsigned int dummy;
00395
00396 IFS1bits.OC3IF = 0;
00397
00398 SPI2BUF = *ntsc.superimpose.vram++;
00399 ntsc.superimpose.hsync = 2;
00400 while(SPI2STATbits.SPITBF);
00401 dummy = SPI2BUF;
00402 SPI2BUF = *ntsc.superimpose.vram++;
00403
00404 IEC1bits.OC3IE = 0;
00405 return;
00406 }
00407
00408 void __attribute__((interrupt, auto_psv)) _SPI2Interrupt(void)
00409 {
00410 unsigned int dummy;
00411
00412 IFS2bits.SPI2IF = 0;
00413
00414 if(ntsc.superimpose.hsync == 0){
00415 SPI2BUF = (*ntsc.superimpose.vram++) & 0x7fff;
00416 ntsc.superimpose.hsync++;
00417
00418 } else if(ntsc.superimpose.hsync < ntsc.superimpose.video_width - 1){
00419 SPI2BUF = *ntsc.superimpose.vram++;
00420 ntsc.superimpose.hsync++;
00421
00422 } else if(ntsc.superimpose.hsync < ntsc.superimpose.video_width){
00423 SPI2BUF = (*ntsc.superimpose.vram++) & 0xfffe;
00424 ntsc.superimpose.hsync++;
00425
00426 } else {
00427 for(;ntsc.superimpose.hsync < (NTSC_WIDTH >> 4); ntsc.superimpose.hsync++){
00428 ntsc.superimpose.vram++;
00429 }
00430 }
00431
00432 dummy = SPI2BUF;
00433 return;
00434 }
00435
00436 void __attribute__((interrupt, auto_psv)) _T3Interrupt(void)
00437 {
00438
00439 IFS0bits.T3IF = 0;
00440
00441 IEC0bits.T2IE = 1;
00442 IEC0bits.T3IE = 0;
00443 IEC1bits.INT2IE = 0;
00444
00445 ntsc.output = 0;
00446
00447 return;
00448 }
00449
00450
00451
00452
00453
00454
00455 void VIDEO_vram_clear(unsigned int pattern)
00456 {
00457 unsigned int i, *vram;
00458
00459 vram = ntsc.vram;
00460
00461 for(i = 0; i < (NTSC_VRAM_SIZE >> 1); i++){
00462 *vram = pattern;
00463 vram++;
00464 }
00465
00466 return;
00467 }
00468
00469
00470
00471
00472
00473 unsigned char VIDEO_get_output(void)
00474 {
00475 return(ntsc.output);
00476 }
00477
00478
00479
00480
00481
00482 unsigned int VIDEO_get_point(unsigned int x, unsigned int y)
00483 {
00484 const unsigned int table[] = {
00485
00486 0b1000000000000000,
00487 0b0100000000000000,
00488 0b0010000000000000,
00489 0b0001000000000000,
00490 0b0000100000000000,
00491 0b0000010000000000,
00492 0b0000001000000000,
00493 0b0000000100000000,
00494 0b0000000010000000,
00495 0b0000000001000000,
00496 0b0000000000100000,
00497 0b0000000000010000,
00498 0b0000000000001000,
00499 0b0000000000000100,
00500 0b0000000000000010,
00501 0b0000000000000001,
00502 };
00503
00504 #ifndef VIDEO_FAST
00505 if(x >= NTSC_WIDTH) x = NTSC_WIDTH - 1;
00506 if(y >= NTSC_HEIGHT) y = NTSC_HEIGHT - 1;
00507 #endif
00508
00509 #ifdef VIDEO_MIRROR
00510 x = (NTSC_WIDTH - 1) - x;
00511 #endif
00512
00513 return(ntsc.vram[ (y << 4) + (x >> 4) ] & table[ (x & 0x0f) ] ? 1 : 0);
00514 }
00515
00516
00517
00518
00519
00520 void VIDEO_point(unsigned int x, unsigned int y)
00521 {
00522 #ifndef VIDEO_FAST
00523 if(x >= NTSC_WIDTH) x = NTSC_WIDTH - 1;
00524 if(y >= NTSC_HEIGHT) y = NTSC_HEIGHT - 1;
00525 #endif
00526
00527 #ifdef VIDEO_MIRROR
00528 x = (NTSC_WIDTH - 1) - x;
00529 #endif
00530
00531 ntsc.vram[ ((NTSC_HEIGHT - 1 - y) << 4) + (x >> 4) ] |= (0x8000 >> (x & 0x0f));
00532 return;
00533 }
00534 void VIDEO_point_(unsigned int x, unsigned int y)
00535 {
00536 #ifndef VIDEO_FAST
00537 if(x >= NTSC_WIDTH) x = NTSC_WIDTH - 1;
00538 if(y >= NTSC_HEIGHT) y = NTSC_HEIGHT - 1;
00539 #endif
00540
00541 #ifdef VIDEO_MIRROR
00542 x = (NTSC_WIDTH - 1) - x;
00543 #endif
00544
00545 ntsc.vram[ ((NTSC_HEIGHT - 1 - y) << 4) + (x >> 4) ] &= ‾(0x8000 >> (x & 0x0f));
00546 return;
00547 }
00548
00549
00550
00551
00552
00553 void VIDEO_line(int x0, int y0, int x1, int y1)
00554 {
00555 int steep, t;
00556 int deltax, deltay, error;
00557 int x, y;
00558 int ystep;
00559
00560 #ifndef VIDEO_FAST
00561 if(x0 < 0) x0 = 0;
00562 if(x0 >= NTSC_WIDTH) x0 = NTSC_WIDTH - 1;
00563 if(x1 < 0) x1 = 0;
00564 if(x1 >= NTSC_WIDTH) x1 = NTSC_WIDTH - 1;
00565 if(y0 < 0) y0 = 0;
00566 if(y0 >= NTSC_HEIGHT) y0 = NTSC_HEIGHT - 1;
00567 if(y1 < 0) y1 = 0;
00568 if(y1 >= NTSC_HEIGHT) y1 = NTSC_HEIGHT - 1;
00569 #endif
00570
00571 steep = (abs(y1 - y0) > abs(x1 - x0));
00572
00573 if(steep){
00574 t = x0; x0 = y0; y0 = t;
00575 t = x1; x1 = y1; y1 = t;
00576 }
00577 if(x0 > x1) {
00578 t = x0; x0 = x1; x1 = t;
00579 t = y0; y0 = y1; y1 = t;
00580 }
00581
00582 deltax = x1 - x0;
00583 deltay = abs(y1 - y0);
00584 error = 0;
00585 y = y0;
00586
00587 if(y0 < y1) ystep = 1;
00588 else ystep = -1;
00589
00590 if(steep){
00591 for(x = x0; x < x1; x++) {
00592 VIDEO_point(y,x);
00593
00594 error += deltay;
00595
00596 if((error << 1) >= deltax){
00597 y += ystep;
00598 error -= deltax;
00599 }
00600 }
00601 } else {
00602 for(x = x0; x < x1; x++) {
00603 VIDEO_point(x,y);
00604
00605 error += deltay;
00606
00607 if((error << 1) >= deltax){
00608 y += ystep;
00609 error -= deltax;
00610 }
00611 }
00612 }
00613
00614 return;
00615 }
00616
00617 void VIDEO_line_(int x0, int y0, int x1, int y1)
00618 {
00619 int steep, t;
00620 int deltax, deltay, error;
00621 int x, y;
00622 int ystep;
00623
00624 #ifndef VIDEO_FAST
00625 if(x0 < 0) x0 = 0;
00626 if(x0 >= NTSC_WIDTH) x0 = NTSC_WIDTH - 1;
00627 if(x1 < 0) x1 = 0;
00628 if(x1 >= NTSC_WIDTH) x1 = NTSC_WIDTH - 1;
00629 if(y0 < 0) y0 = 0;
00630 if(y0 >= NTSC_HEIGHT) y0 = NTSC_HEIGHT - 1;
00631 if(y1 < 0) y1 = 0;
00632 if(y1 >= NTSC_HEIGHT) y1 = NTSC_HEIGHT - 1;
00633 #endif
00634
00635 steep = (abs(y1 - y0) > abs(x1 - x0));
00636
00637 if(steep){
00638 t = x0; x0 = y0; y0 = t;
00639 t = x1; x1 = y1; y1 = t;
00640 }
00641 if(x0 > x1) {
00642 t = x0; x0 = x1; x1 = t;
00643 t = y0; y0 = y1; y1 = t;
00644 }
00645
00646 deltax = x1 - x0;
00647 deltay = abs(y1 - y0);
00648 error = 0;
00649 y = y0;
00650
00651 if(y0 < y1) ystep = 1;
00652 else ystep = -1;
00653
00654 if(steep){
00655 for(x = x0; x < x1; x++) {
00656 VIDEO_point_(y,x);
00657
00658 error += deltay;
00659
00660 if((error << 1) >= deltax){
00661 y += ystep;
00662 error -= deltax;
00663 }
00664 }
00665 } else {
00666 for(x = x0; x < x1; x++) {
00667 VIDEO_point_(x,y);
00668
00669 error += deltay;
00670
00671 if((error << 1) >= deltax){
00672 y += ystep;
00673 error -= deltax;
00674 }
00675 }
00676 }
00677
00678 return;
00679 }
00680
00681
00682
00683
00684
00685 void VIDEO_arc (unsigned int x, unsigned int y, unsigned int r, unsigned int start, unsigned int end)
00686 {
00687 unsigned int deg;
00688
00689 #ifndef VIDEO_FAST
00690 if(start > end){
00691 deg = end;
00692 end = start;
00693 start = deg;
00694 }
00695 #endif
00696
00697 for(deg = start; deg < end; deg++){
00698 VIDEO_point (x + (double)r * tcos[deg], y + (double)r * tsin[deg]);
00699 }
00700
00701 return;
00702 }
00703
00704 void VIDEO_arc_(unsigned int x, unsigned int y, unsigned int r, unsigned int start, unsigned int end)
00705 {
00706 unsigned int deg;
00707
00708 #ifndef VIDEO_FAST
00709 if(start > end){
00710 deg = end;
00711 end = start;
00712 start = deg;
00713 }
00714 #endif
00715
00716 for(deg = start; deg < end; deg++){
00717 VIDEO_point_(x + (double)r * tcos[deg], y + (double)r * tsin[deg]);
00718 }
00719
00720 return;
00721 }
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733 #ifdef VIDEO_MIRROR
00734 static unsigned char reverse (unsigned char buf)
00735 {
00736 return(
00737 ((buf & 0b00000001) << 7)
00738 + ((buf & 0b00000010) << 5)
00739 + ((buf & 0b00000100) << 3)
00740 + ((buf & 0b00001000) << 1)
00741 + ((buf & 0b00010000) >> 1)
00742 + ((buf & 0b00100000) >> 3)
00743 + ((buf & 0b01000000) >> 5)
00744 + ((buf & 0b10000000) >> 7)
00745 );
00746
00747 }
00748 #endif
00749
00750
00751
00752
00753
00754 void VIDEO_locate(unsigned int x, unsigned int y)
00755 {
00756 #ifdef VIDEO_MIRROR
00757 video.cx = NTSC_WIDTH / FONTX2_get_ascii_width() - x - 1;
00758 #else
00759 video.cx = x;
00760 #endif
00761 video.cy = y;
00762 return;
00763 }
00764
00765
00766
00767
00768
00769 void VIDEO_putch(unsigned char c)
00770 {
00771
00772 #ifdef VIDEO_MIRROR
00773 if(video.cx == 0){
00774 video.cx = NTSC_WIDTH / FONTX2_get_ascii_width();
00775
00776 }
00777 #else
00778 if(video.cx >= (NTSC_WIDTH / FONTX2_get_ascii_width())){
00779 video.cx = 0;
00780 video.cy++;
00781 }
00782 #endif
00783
00784 if(video.cy >= (NTSC_HEIGHT / FONTX2_get_ascii_height())){
00785 video.cy = 0;
00786 }
00787
00788 #if defined FONT_FAST8
00789 {
00790
00791 unsigned char i;
00792 unsigned int *vram;
00793 unsigned char *font;
00794
00795 vram = &ntsc.vram[ video.cy * FONTX2_get_ascii_height() * (NTSC_WIDTH >> 4) + (video.cx >> 1)];
00796 font = FONTX2_get_ascii_font(c);
00797
00798 if(video.cx & 0x01){
00799 for(i = 0; i < FONTX2_get_ascii_height(); i++){
00800 *vram &= 0xff00;
00801 #ifdef VIDEO_MIRROR
00802 *vram |= (int)reverse(*font++);
00803 #else
00804 *vram |= (int)(*font++);
00805 #endif
00806 vram += (NTSC_WIDTH >> 4);
00807 }
00808 } else {
00809 for(i = 0; i < FONTX2_get_ascii_height(); i++){
00810 *vram &= 0x00ff;
00811 #ifdef VIDEO_MIRROR
00812 *vram |= (int)reverse(*font++) << 8;
00813 #else
00814 *vram |= (int)(*font++) << 8;
00815 #endif
00816 vram += (NTSC_WIDTH >> 4);
00817 }
00818 }
00819 }
00820 #else
00821 {
00822
00823
00824 unsigned int x, y, i, j, k;
00825 unsigned char grif;
00826
00827 for(y = 0; y < FONTX2_get_ascii_height(); y++){
00828
00829 i = FONTX2_get_ascii_height() * video.cy + y;
00830
00831 for(j = 0; j < FONTX2_get_ascii_width_byte(); j++){
00832
00833 #ifdef VIDEO_MIRROR
00834 grif = reverse(FONTX2_get_ascii_font_data(c, j, y));
00835 #else
00836 grif = FONTX2_get_ascii_font_data(c, j, y);
00837 #endif
00838
00839 for(x = 0; x < 8 && (j * 8 + x) < FONTX2_get_ascii_width(); x++){
00840
00841 k = x + video.cx * FONTX2_get_ascii_width();
00842
00843 if(grif & 0x80) ntsc.vram[(i << 4) + (k >> 4)] |= (0x8000 >> (k & 0x0F));
00844 else ntsc.vram[(i << 4) + (k >> 4)] &= ‾(0x8000 >> (k & 0x0F));
00845
00846 grif = grif << 1;
00847 }
00848 }
00849 }
00850 }
00851 #endif
00852
00853 #ifdef VIDEO_MIRROR
00854 video.cx--;
00855 #else
00856 video.cx++;
00857 #endif
00858 return;
00859 }
00860
00861
00862
00863
00864
00865 void VIDEO_putstr(const char *s)
00866 {
00867 while(*s){
00868 VIDEO_putch(*s++);
00869 }
00870
00871 return;
00872 }
00873
00874
00875
00876
00877 void VIDEO_puthex(unsigned char a)
00878 {
00879 VIDEO_putch(hex[(a >> 4) & 0x0f]);
00880 VIDEO_putch(hex[ a & 0x0f]);
00881 return;
00882 }
00883
00884
00885
00886
00887
00888 void VIDEO_putbin(unsigned char a)
00889 {
00890 VIDEO_putch('0' + ((a >> 7) & 0x01));
00891 VIDEO_putch('0' + ((a >> 6) & 0x01));
00892 VIDEO_putch('0' + ((a >> 5) & 0x01));
00893 VIDEO_putch('0' + ((a >> 4) & 0x01));
00894 VIDEO_putch('0' + ((a >> 3) & 0x01));
00895 VIDEO_putch('0' + ((a >> 2) & 0x01));
00896 VIDEO_putch('0' + ((a >> 1) & 0x01));
00897 VIDEO_putch('0' + ( a & 0x01));
00898
00899 return;
00900 }
00901
00902
00903
00904
00905
00906 void VIDEO_putuint(unsigned int digit, unsigned char size)
00907 {
00908
00909 if(size > 4){ if(digit > 9999){ VIDEO_putch('0' + digit / 10000 % 10); } else { VIDEO_putch(' '); }; };
00910 if(size > 3){ if(digit > 999){ VIDEO_putch('0' + digit / 1000 % 10); } else { VIDEO_putch(' '); }; };
00911 if(size > 2){ if(digit > 99){ VIDEO_putch('0' + digit / 100 % 10); } else { VIDEO_putch(' '); }; };
00912 if(size > 1){ if(digit > 9){ VIDEO_putch('0' + digit / 10 % 10); } else { VIDEO_putch(' '); }; };
00913
00914 VIDEO_putch('0' + digit % 10);
00915 return;
00916 }
00917
00918
00919 void VIDEO_putint(int digit, unsigned char size)
00920 {
00921 if(digit < 0) VIDEO_putch('-');
00922 else VIDEO_putch(' ');
00923
00924 digit = abs(digit);
00925 if(size > 4){ if(digit > 9999){ VIDEO_putch('0' + digit / 10000 % 10); } else { VIDEO_putch(' '); }; };
00926 if(size > 3){ if(digit > 999){ VIDEO_putch('0' + digit / 1000 % 10); } else { VIDEO_putch(' '); }; };
00927 if(size > 2){ if(digit > 99){ VIDEO_putch('0' + digit / 100 % 10); } else { VIDEO_putch(' '); }; };
00928 if(size > 1){ if(digit > 9){ VIDEO_putch('0' + digit / 10 % 10); } else { VIDEO_putch(' '); }; };
00929 VIDEO_putch('0' + digit % 10);
00930 return;
00931 }
00932
00933
00934 void VIDEO_putdouble(double digit, unsigned char size, unsigned char size2)
00935 {
00936 if(digit < 0) VIDEO_putch('-');
00937 else VIDEO_putch(' ');
00938
00939 digit = abs(digit);
00940
00941 if(size > 4){ if((unsigned int)digit > 9999){ VIDEO_putch('0' + (unsigned char)((unsigned int)(digit / 10000) % 10)); } else { VIDEO_putch(' '); }; };
00942 if(size > 3){ if((unsigned int)digit > 999){ VIDEO_putch('0' + (unsigned char)((unsigned int)(digit / 1000) % 10)); } else { VIDEO_putch(' '); }; };
00943 if(size > 2){ if((unsigned int)digit > 99){ VIDEO_putch('0' + (unsigned char)((unsigned int)(digit / 100) % 10)); } else { VIDEO_putch(' '); }; };
00944 if(size > 1){ if((unsigned int)digit > 9){ VIDEO_putch('0' + (unsigned char)((unsigned int)(digit / 10) % 10)); } else { VIDEO_putch(' '); }; };
00945 VIDEO_putch('0' + (unsigned char)((unsigned int)digit % 10));
00946 VIDEO_putch('.');
00947 VIDEO_putch('0' + (unsigned int)((unsigned int)(digit * 10.0) % 10));
00948 if(size2 > 1) VIDEO_putch('0' + (unsigned int)((unsigned int)(digit * 100.0) % 10));
00949 if(size2 > 2) VIDEO_putch('0' + (unsigned int)((unsigned int)(digit * 1000.0) % 10));
00950 if(size2 > 3) VIDEO_putch('0' + (unsigned int)((unsigned int)(digit * 10000.0) % 10));
00951
00952 return;
00953 }
00954
00955
00956
00957
00958
00959 void GRAPH_init(pGRAPH_T graph, unsigned int x, unsigned int y, unsigned int width, unsigned int height)
00960 {
00961 unsigned int i;
00962
00963 #ifndef VIDEO_FAST
00964 if(width >= GRAPH_SIZE){
00965 width = GRAPH_SIZE;
00966 }
00967 if(x + width > NTSC_WIDTH){
00968 width = NTSC_WIDTH - x;
00969 }
00970 if(y + height > NTSC_HEIGHT){
00971 height = NTSC_HEIGHT - y;
00972 }
00973 #endif
00974
00975 graph->x = x;
00976 graph->y = y;
00977 graph->width = width;
00978 graph->height = height;
00979 graph->ptr = 0;
00980
00981 for(i = 0; i < GRAPH_SIZE; i++){
00982 graph->data[i] = 0;
00983 }
00984
00985 return;
00986 }
00987
00988
00989
00990
00991
00992 void GRAPH_putdata(pGRAPH_T graph, unsigned int data)
00993 {
00994 if(data > 100) data = 100;
00995
00996 graph->data[graph->ptr] = data;
00997 graph->ptr = (graph->ptr + 1) % graph->width;
00998
00999 return;
01000 }
01001
01002
01003
01004
01005
01006 void GRAPH_draw_point(pGRAPH_T graph)
01007 {
01008 unsigned int i, w, x, y;
01009
01010 for(i = graph->y; i < graph->y + graph->height; i++){
01011 VIDEO_point_(graph->x, i);
01012 }
01013
01014 w = graph->width * 2;
01015 for(i = graph->width; i < w; i++){
01016 x = graph->x + i - graph->width;
01017
01018 y = graph->y + (((unsigned int)graph->data[(graph->ptr + i - 1) % graph->width] * graph->height) / 100);
01019 VIDEO_point_(x, y);
01020
01021 y = graph->y + (((unsigned int)graph->data[(graph->ptr + i ) % graph->width] * graph->height) / 100);
01022 VIDEO_point(x, y);
01023 }
01024
01025 return;
01026 }
01027
01028 void GRAPH_draw_line(pGRAPH_T graph)
01029 {
01030 unsigned int i, w, x, y1, y2, y3;
01031
01032 w = graph->width * 2 - 2;
01033 for(i = graph->width + 1; i < w; i++){
01034 x = graph->x + i - graph->width;
01035 y1 = graph->y + (((unsigned int)graph->data[(graph->ptr + i - 1) % graph->width] * graph->height) / 100);
01036 y2 = graph->y + (((unsigned int)graph->data[(graph->ptr + i ) % graph->width] * graph->height) / 100);
01037 y3 = graph->y + (((unsigned int)graph->data[(graph->ptr + i + 1) % graph->width] * graph->height) / 100);
01038 VIDEO_line_(x, y1, x + 1, y2);
01039 VIDEO_line (x, y2, x + 1, y3);
01040 }
01041
01042 for(i = graph->y; i < graph->y + graph->height; i++){
01043 VIDEO_point_(graph->x, i);
01044 VIDEO_point_(graph->x + graph->width, i);
01045 }
01046
01047 return;
01048 }
01049
01050 void GRAPH_draw_bar(pGRAPH_T graph)
01051 {
01052 unsigned int i, x, y;
01053
01054 for(i = 0; i < graph->width; i++){
01055 x = graph->x + i;
01056 y = graph->y + (((unsigned int)graph->data[(graph->ptr + i) % graph->width] * graph->height) / 100);
01057 VIDEO_line_(x, graph->y, x, y);
01058 VIDEO_line (x, y , x, graph->y + graph->height);
01059 }
01060
01061 return;
01062 }
01063
01064
01065
01066
01067
01068 void METER_init(pMETER_T meter, unsigned int x, unsigned int y, unsigned char r)
01069 {
01070 meter->x = x;
01071 meter->y = y;
01072 meter->r = r;
01073 meter->old = 0;
01074
01075 VIDEO_arc(x, y, r, 270, 360);
01076
01077 return;
01078 }
01079
01080
01081
01082
01083
01084 void METER_draw(pMETER_T meter, unsigned int value)
01085 {
01086 double rc, rs;
01087
01088 if(value > 100) value = 100;
01089 rc = (double)meter->r * tcos[0];
01090 rs = (double)meter->r * tsin[0];
01091 VIDEO_line(meter->x + rc, meter->y + rs, meter->x + 0.7 * rc, meter->y + 0.7 * rs);
01092
01093 rc = (double)meter->r * tcos[270];
01094 rs = (double)meter->r * tsin[270];
01095 VIDEO_line(meter->x + rc, meter->y + rs, meter->x + 0.7 * rc, meter->y + 0.7 * rs);
01096
01097 rc = (double)meter->r * tcos[meter->old];
01098 rs = (double)meter->r * tsin[meter->old];
01099 VIDEO_line_(meter->x + rc, meter->y + rs, meter->x + 0.7 * rc, meter->y + 0.7 * rs);
01100
01101 meter->old = ((100 - value) * 27) / 10;
01102 rc = (double)meter->r * tcos[meter->old];
01103 rs = (double)meter->r * tsin[meter->old];
01104 VIDEO_line (meter->x + rc, meter->y + rs, meter->x + 0.7 * rc, meter->y + 0.7 * rs);
01105
01106 return;
01107 }
01108
01109
01110
01111
01112
01113 void TRACK_init(pTRACK_T track, unsigned int x, unsigned int y, unsigned int width, unsigned int height)
01114 {
01115 unsigned int i;
01116
01117 track->x = x;
01118 track->y = y;
01119 track->width = width;
01120 track->height = height;
01121 track->ptr = 0;
01122
01123 for(i = 0; i < TRACK_SIZE; i++){
01124 track->data[i][0] = 0;
01125 track->data[i][1] = 0;
01126 }
01127
01128 return;
01129 }
01130
01131
01132
01133
01134
01135 void TRACK_putdata(pTRACK_T track, unsigned int x, unsigned int y)
01136 {
01137 if(x > 100) x = 100;
01138 if(y > 100) y = 100;
01139
01140 track->ptr = (track->ptr + 1) % TRACK_SIZE;
01141 track->data[ track->ptr ][0] = x;
01142 track->data[ track->ptr ][1] = y;
01143
01144 return;
01145 }
01146
01147
01148
01149
01150
01151 void TRACK_draw_point(pTRACK_T track)
01152 {
01153 unsigned int tmp;
01154
01155
01156 tmp = (track->ptr + 1) % TRACK_SIZE;
01157 VIDEO_point_(track->x + (track->width * track->data[ tmp ][0]) / 100,
01158 track->y + (track->height * track->data[ tmp ][1]) / 100);
01159
01160 VIDEO_point_(track->x + (track->width * track->data[ tmp ][0]) / 100 + 1,
01161 track->y + (track->height * track->data[ tmp ][1]) / 100);
01162
01163 VIDEO_point_(track->x + (track->width * track->data[ tmp ][0]) / 100,
01164 track->y + (track->height * track->data[ tmp ][1]) / 100 + 1);
01165
01166 VIDEO_point_(track->x + (track->width * track->data[ tmp ][0]) / 100 + 1,
01167 track->y + (track->height * track->data[ tmp ][1]) / 100 + 1);
01168
01169 VIDEO_point_(track->x + (track->width * track->data[ tmp ][0]) / 100 + 2,
01170 track->y + (track->height * track->data[ tmp ][1]) / 100);
01171
01172 VIDEO_point_(track->x + (track->width * track->data[ tmp ][0]) / 100,
01173 track->y + (track->height * track->data[ tmp ][1]) / 100 + 2);
01174
01175 VIDEO_point_(track->x + (track->width * track->data[ tmp ][0]) / 100 + 1,
01176 track->y + (track->height * track->data[ tmp ][1]) / 100 + 2);
01177
01178 VIDEO_point_(track->x + (track->width * track->data[ tmp ][0]) / 100 + 2,
01179 track->y + (track->height * track->data[ tmp ][1]) / 100 + 1);
01180
01181 VIDEO_point_(track->x + (track->width * track->data[ tmp ][0]) / 100 + 2,
01182 track->y + (track->height * track->data[ tmp ][1]) / 100 + 2);
01183
01184
01185
01186 VIDEO_point(track->x + (track->width * track->data[ track->ptr ][0]) / 100,
01187 track->y + (track->height * track->data[ track->ptr ][1]) / 100);
01188
01189 VIDEO_point(track->x + (track->width * track->data[ track->ptr ][0]) / 100 + 1,
01190 track->y + (track->height * track->data[ track->ptr ][1]) / 100);
01191
01192 VIDEO_point(track->x + (track->width * track->data[ track->ptr ][0]) / 100,
01193 track->y + (track->height * track->data[ track->ptr ][1]) / 100 + 1);
01194
01195 VIDEO_point(track->x + (track->width * track->data[ track->ptr ][0]) / 100 + 1,
01196 track->y + (track->height * track->data[ track->ptr ][1]) / 100 + 1);
01197
01198 VIDEO_point(track->x + (track->width * track->data[ track->ptr ][0]) / 100 + 2,
01199 track->y + (track->height * track->data[ track->ptr ][1]) / 100);
01200
01201 VIDEO_point(track->x + (track->width * track->data[ track->ptr ][0]) / 100,
01202 track->y + (track->height * track->data[ track->ptr ][1]) / 100 + 2);
01203
01204 VIDEO_point(track->x + (track->width * track->data[ track->ptr ][0]) / 100 + 1,
01205 track->y + (track->height * track->data[ track->ptr ][1]) / 100 + 2);
01206
01207 VIDEO_point(track->x + (track->width * track->data[ track->ptr ][0]) / 100 + 2,
01208 track->y + (track->height * track->data[ track->ptr ][1]) / 100 + 1);
01209
01210 VIDEO_point(track->x + (track->width * track->data[ track->ptr ][0]) / 100 + 2,
01211 track->y + (track->height * track->data[ track->ptr ][1]) / 100 + 2);
01212
01213
01214
01215 tmp = track->y + (track->height >> 1);
01216 VIDEO_line(track->x, tmp, track->x + track->width, tmp);
01217
01218 tmp = track->x + (track->width >> 1);
01219 VIDEO_line(tmp, track->y, tmp, track->y + track->height);
01220
01221 return;
01222 }