#include #include #include #include #include #include #include #include #include "z80emu.c" // bez toho nejni Z80reset // #include "z80emu.h" // bez toho nejni zxout #include "zxem.h" #include "PMI80_rom.h" #include "megaROM2.h" //#include "ROM3.h" #define Z80_SPH 12 #define Z80_SPL 13 static int touchpad_fd = -1; // touchpad input device static int keypad_fd = -1; // keypad input device static int printer_fd = -1; // printer output device static int dsp_fd = -1; // sound device, not finished yet int fbfd = 0; // framebuffer nastavení rozlišeí atd. struct fb_var_screeninfo vinfo; struct fb_fix_screeninfo finfo; long int screensize = 0; char *fbp = 0; char *framebuffer; int x = 0, y = 0; int seq, t; long int location = 0; long int framebuffer_pos; // unsigned short int int red = 254<<11 | 0 | 0;// ostrá červená = svítíme int tma = 100 | 0 | 0 ; // tmavě modrá unsigned char LEDcontrol; unsigned char prevLEDcon; unsigned char *memory; // memory space including ROM, screenbuffer, etc. unsigned char kbdlines[8]; // keyboard lines, as per http://www.breakintoprogram.co.uk/hardware/computers/zx-spectrum/keyboard #include "img.h" // soubor s hexadecimálními daty obrázku klávesnice PMI void HEXA1(int seq,int t) //seq je pozice 0-9 a t je RGB color { //seg A1 for (y = 4; y < 11; y++) { x = 319; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (y = 3; y < 11; y++) { x = 318; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (y = 4; y < 11; y++) { x = 317; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } } void HEXA2(int seq,int t) //seq je pozice 0-9 a t je RGB color { //seg A2 for (y = 13; y < 20; y++) { x = 319; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (y = 13; y < 21; y++) { x = 318; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (y = 14; y < 20; y++) { x = 317; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } } void HEXB(int seq,int t) //seq je pozice 0-9 a t je RGB color { // seg B for (x = 316; x > 293; x--) { y = 21; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (x = 317; x > 292; x--) { y = 22; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (x = 316; x > 292; x--) { y = 23; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } } void HEXC(int seq,int t) //seq je pozice 0-9 a t je RGB color { // seg C for (x = 289; x > 266; x--) { y = 21; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (x = 290; x > 265; x--) { y = 22; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (x = 290; x > 266; x--) { y = 23; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } } void HEXD1(int seq,int t) //seq je pozice 0-9 a t je RGB color { //seg D1 for (y = 4; y < 10; y++) { x = 265; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (y = 3; y < 11; y++) { x = 264; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (y = 4; y < 11; y++) { x = 263; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } } void HEXD2(int seq,int t) //seq je pozice 0-9 a t je RGB color { //seg D2 for (y = 14; y < 20; y++) { x = 265; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (y = 13; y < 21; y++) { x = 264; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (y = 13; y < 20; y++) { x = 263; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } } void HEXE(int seq,int t) //seq je pozice 0-9 a t je RGB color { // seg E for (x = 290; x > 266; x--) { y = 1; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (x = 290; x > 265; x--) { y = 2; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (x = 289; x > 266; x--) { y = 3; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } } void HEXF(int seq,int t) //seq je pozice 0-9 a t je RGB color { // seg F for (x = 316; x > 292; x--) { y = 1; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (x = 317; x > 292; x--) { y = 2; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (x = 316; x > 293; x--) { y = 3; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } } void HEXG1(int seq,int t) //seq je pozice 0-9 a t je RGB color { //seg G1 for (y = 5; y < 10; y++) { x = 292; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (y = 4; y < 11; y++) { x = 291; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (y = 5; y < 10; y++) { x = 290; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } } void HEXG2(int seq,int t) //seq je pozice 0-9 a t je RGB color { //seg G2 for (y = 14; y < 19; y++) { x = 292; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (y = 13; y < 20; y++) { x = 291; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (y = 14; y < 19; y++) { x = 290; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } } void HEXH(int seq,int t) //seq je pozice 0-9 a t je RGB color { // seg H for (x = 315; x > 312; x--) { y = 5; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (x = 315; x > 303; x--) { y = 6; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (x = 312; x > 297; x--) { y = 7; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (x = 305; x > 294; x--) { y = 8; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (x = 297; x > 294; x--) { y = 9; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } } void HEXI(int seq,int t) //seq je pozice 0-9 a t je RGB color { // seg I for (x = 316; x > 293; x--) { y = 11; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (x = 317; x > 292; x--) { y = 12; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (x = 316; x > 293; x--) { y = 13; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } } void HEXJ(int seq,int t) //seq je pozice 0-9 a t je RGB color { // seg J for (x = 315; x > 312; x--) { y = 19; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (x = 315; x > 303; x--) { y = 18; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (x = 312; x > 297; x--) { y = 17; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (x = 305; x > 294; x--) { y = 16; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (x = 297; x > 294; x--) { y = 15; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } } void HEXK(int seq,int t) //seq je pozice 0-9 a t je RGB color { // seg K for (x = 270; x > 267; x--) { y = 19; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (x = 278; x > 267; x--) { y = 18; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (x = 285; x > 270; x--) { y = 17; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (x = 288; x > 276; x--) { y = 16; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (x = 288; x > 285; x--) { y = 15; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } } void HEXL(int seq,int t) //seq je pozice 0-9 a t je RGB color { // seg L for (x = 289; x > 266; x--) { y = 11; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (x = 290; x > 265; x--) { y = 12; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (x = 289; x > 266; x--) { y = 13; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } } void HEXM(int seq,int t) //seq je pozice 0-9 a t je RGB color { // seg M for (x = 270; x > 267; x--) { y = 5; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (x = 278; x > 267; x--) { y = 6; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (x = 285; x > 270; x--) { y = 7; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (x = 288; x > 276; x--) { y = 8; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } for (x = 288; x > 285; x--) { y = 9; location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = t; } } void display (int value, int seq ) // zobrazujeme na pozici seq obsah z value { printf ("Voláme display X=%X val= %X\n", seq, value); if (~value & 0x40) {HEXG1(seq,red); HEXG2(seq,red);} if (~value & 0x20) HEXF(seq,red); if (~value & 0x10) HEXE(seq,red); if (~value & 0x08) { HEXD1(seq,red); HEXD2(seq,red);} if (~value & 0x04) HEXC(seq,red); if (~value & 0x02) HEXB(seq,red); if (~value & 0x01) { HEXA1(seq,red); HEXA2(seq,red);} // kdyz nema sviti smazeme if (value & 0x40) {HEXG1(seq,tma); HEXG2(seq,tma);} if (value & 0x20) HEXF(seq,tma); if (value & 0x10) HEXE(seq,tma); if (value & 0x08) { HEXD1(seq,tma); HEXD2(seq,tma);} if (value & 0x04) HEXC(seq,tma); if (value & 0x02) HEXB(seq,tma); if (value & 0x01) { HEXA1(seq,tma); HEXA2(seq,tma);} } /* ZX OUT port this should be implemented for sound */ void zxout (int port, int value) { printf ("OUT %X %X\n", port, value); switch (port & 0xFF) { /* Periferie PMI-80 * periferiemi se komunikovalo na adresách F8, F9, FA a FB * (klasická čtveřice registrů 8255 – PA, PB, PC, řídicí). * Displej používal budič a dekodér 1-z-9 typu MH1082, * připojený na port PC (=adresa FA), bity 0-3. * Tímto bitem se vybírala pozice na displeji. * Segmenty ovládal port PA (=adresa F8), * a to bity 0-6 (bit 7 nebyl zapojený, desetinná tečka nefungovala). * PC4 5 6 slouží pro čtení klavesnice */ case 0xFA: //// 0xFA led control řídící bity 0-3 která pozice 0xF je poslední a 7 je první a klavesnice sloupce prevLEDcon = LEDcontrol; LEDcontrol = value & 0x0f; //B00001111; break; case 0xF8: // 0xF8 led value - segmenty bity 0-6 - bacha jsou negované PA-0xF8 a PB-0xFA (LEDcontrol) switch (LEDcontrol){ case 0x0F: //první segmentofka 0xF display ( value,0); break; case 0x0E: //druhá segmentofka display ( value,1); break; case 0x0D: //třetí segmentofka display ( value,2); break; case 0x0C: //čtvrtá segmentofka display ( value,3); break; case 0x0B: //pátá segmentofka display ( value,4); break; case 0x0A: //šestá segmentofka display ( value,5); break; case 0x09: //sedmá segmentofka display ( value,6); break; case 0x08: //osmá segmentofka display ( value,7); break; case 0x07: //devátá segmentofka display ( value,8); break; } break; } //********************************************** } /* Z80 in-port */ int zxin (int port) { int i, v; /* tehere is some kind of bug that prevents me from masking keystrokes if manic miner is reading multiple keylines at one time. this happens at 0x8c5c, see https://skoolkid.github.io/manicminer/asm/8BDD.html so we force the last keyline with space to allow jumping this should be fixed for other games or if it becomes obvious that manic miner needs more keys than implemented now :) */ if ((port & 0xFF) == 0xFE) { v = 0x1f; for (i = 0; i < 8; i++) if ((port & (1 << (i + 8))) == 0) { v &= kbdlines[i]; return v; } //return v; } printf ("IN %X\n", port); return 0; } /* This handles writes to low memory to allow screen redraw. All changes are stored in global memory[] buffer */ void z80lowmemwrite (int addr, int val) { // pokus o zápis do dolního kila ROM paměti (podívej do z80user.h) < 0x400 printf ("Unhandled ROMwrite addr=%X val= %X\n", addr, val); } int _init() { // Open the file for reading and writing fbfd = open("/dev/fb", O_RDWR); if (fbfd == -1) { perror("Error: cannot open framebuffer device"); exit(1); } printf("The framebuffer device was opened successfully.\n"); // Get fixed screen information if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo) == -1) { perror("Error reading fixed information"); exit(2); } // Get variable screen information if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo) == -1) { perror("Error reading variable information"); exit(3); } // printf("%dx%d, %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel); // Figure out the size of the screen in bytes screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8; // Map the device to memory fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0); if ((int)fbp == -1) { perror("Error: failed to map framebuffer device to memory"); exit(4); } // Figure out where in memory to put the picure for (y = 00; y < 240; y++) for (x = 00; x < 260; x++) { location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + (y+vinfo.yoffset) * finfo.line_length; { //assume 16bpp int b = 64 - (y-100)/16; //100; int g = (x-100)/6; // A little green int r = x; //31-(y-100)/16; // A lot of red int picturepos = ((260-x)*240+y); // 6 0 0 unsigned short int t = img_data[picturepos*3] << 6 | img_data[picturepos*3+1] | img_data[picturepos*3+2] ; // r<<11 | g << 5 | b; *((unsigned short int*)(fbp + location)) = t; } } // prostor pro display je y:0-240 a x:260-320 // celý display zhasneme t = tma; for (int seq = 0; seq < 9; seq++) { HEXA1 (seq,t); HEXA2 (seq,t); HEXB (seq,t); HEXC (seq,t); HEXD1 (seq,t); HEXD2 (seq,t); HEXE (seq,t); HEXF (seq,t); HEXG1 (seq,t); HEXG2 (seq,t); HEXH (seq,t); HEXI (seq,t); HEXJ (seq,t); HEXK (seq,t); HEXL (seq,t); HEXM (seq,t); } // emulovat char *romfilename; int fd; int cycles; int i; struct stat sb; Z80_STATE state; memory = (unsigned char *) malloc (0x10000); memset (memory, 0, 0x10000); memcpy (&memory[0x0], &ROM[0x0], 1024); //zkopirujeme PMI-ROM do RAM memcpy (&memory[0x0400], &ROM2[0x1400], 1024); //zkopirujeme část megaROM2.h do RAM na 0x0400 /* &ROM2[0x000] Cosmos a pong &ROM2[0x100] "br-Stop" &ROM2[0x1000] "pmi -80" A DALSI EFEKT / intension &ROM2[0x1400] "Spool" */ for (i = 0; i < 8; i++) kbdlines[i] = 0x1f; Z80Reset (&state); state.pc = 0x0000; cycles = 0; while (1) { cycles += Z80Emulate (&state, 200 /*cycles */ , NULL); // for (int o = 0; o < (10000); o++) ; //zpomlait /*if (cycles > 1024*10) { handle_x (); // handle keyboard (keypad) Z80Interrupt (&state, 0, NULL); cycles = 0; } */ if (cycles > 3024000 * 2) { // Z80Interrupt (&state, 0, NULL); cycles = 0; printf ("smycka dobehla\n"); for (x = 0; x < 320; x++) // CLS for (y = 0; y < 240; y++) { location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + ((seq*27)+y+vinfo.yoffset) * finfo.line_length; *((unsigned short int*)(fbp + location)) = 0 | 0 | 0; } munmap(fbp, screensize); sleep (1); exit (1); } } return 0; // Uzavřít framebuffer close(fbfd); return 0; }