// Written by Mathias Lasser // License terms are unclear at the moment #include #include #include #include #include int enable_debug=0; #define debugf(...) do{if(enable_debug)fprintf(stderr,__VA_ARGS__);}while(0) #pragma pack(2) typedef struct { uint16_t bfType; uint32_t bfSize; uint16_t bfReserved1; uint16_t bfReserved2; uint32_t bfOffBits; }BITMAPFILEHEADER; typedef struct { uint32_t biSize; uint32_t biWidth; uint32_t biHeight; uint16_t biPlanes; uint16_t biBitCount; uint32_t biCompression; uint32_t biSizeImage; uint32_t biXPelsPerMeter; uint32_t biYPelsPerMeter; uint32_t biClrUsed; uint32_t biClrImportant; }BITMAPINFOHEADER; typedef struct{ uint16_t boot_mode; uint16_t crc; uint8_t freq; uint8_t bank; uint32_t write_pointer; uint32_t CRAM_rowsize; uint32_t CRAM_colsize; uint8_t* CRAM[4]; uint32_t BRAM_rowsize; uint32_t BRAM_colsize; uint8_t* BRAM[4]; }FPGA_t; typedef struct{ uint32_t len; uint32_t pointer; uint16_t crc; uint8_t payload[0]; }bitstream_t; typedef union{ struct{ uint8_t lo:4; uint8_t hi:4; }; uint8_t full; }nibble_t; const char* freq_settings[]={"low","medium","high"}; const char* boot_settings[]={"Disable","Enable"}; uint16_t crc16(uint32_t crc,uint8_t in){ for(int i=7;i>=0;i--){ crc<<=1; if((crc^(in<<(16-i)))&0x10000) crc^=0x1021; } return crc; } uint32_t get_byte(bitstream_t* bitstream){ if(bitstream->pointer>=bitstream->len)return 0xFFFFFF; uint8_t data=bitstream->payload[bitstream->pointer++]; bitstream->crc=crc16(bitstream->crc,data); return data; } uint32_t get_payload(bitstream_t* bitstream,int len){ uint32_t ret=get_byte(bitstream); for(int i=1;iCRAM_colsize*FPGA->CRAM_rowsize/8; uint8_t* temp=(uint8_t*)malloc(n); for(int i=0;iCRAM[FPGA->bank]=temp; } void FPGA_EBR_write(FPGA_t* FPGA,bitstream_t* bitstream){ int n=FPGA->BRAM_colsize*FPGA->BRAM_rowsize/8; uint8_t* temp=(uint8_t*)malloc(FPGA->write_pointer+n); if(FPGA->write_pointer!=0){ uint8_t* old_data=FPGA->BRAM[FPGA->bank]; memcpy(temp,old_data,FPGA->write_pointer); free(old_data); } for(int i=0;iwrite_pointer++]=get_byte(bitstream); FPGA->BRAM[FPGA->bank]=temp; } int parse(bitstream_t* bitstream, FPGA_t* FPGA) { uint32_t preamble=0; while(1){ preamble<<=8; preamble|=get_byte(bitstream); if(preamble==0x7EAA997E){ debugf("Got preamble\n"); break; } if(preamble==0xFFFFFFFF){ fprintf(stderr,"Error: could not find preamble...\n"); return -1; } } nibble_t command; uint32_t payload; uint16_t crc; while(1){ crc=bitstream->crc; command.full=get_byte(bitstream); if(command.full==0xFF){ payload=get_byte(bitstream); if(payload!=0x00)goto err; char*comment=(char*)&bitstream->payload[bitstream->pointer]; debugf("Got comment section start\n"); while(1){ payload<<=8; payload|=get_byte(bitstream); if((payload&0xFFFF)==0x00FF)break; if(payload==0xFFFFFFFF){ fprintf(stderr,"Error: could not find comment section end\n"); return -1; } } debugf("\n%s\n\n",comment); debugf("Got comment section end\n"); continue; } payload=get_payload(bitstream,command.lo); switch(command.hi){ case 0x0: if(command.lo!=0x01)goto err; switch(payload){ case 0x01: debugf("Write to CRAM!!!\n"); FPGA_write(FPGA,bitstream); get_payload(bitstream,2); break; case 0x03: debugf("Write to BRAM!!!\n"); FPGA_EBR_write(FPGA,bitstream); get_payload(bitstream,2); break; case 0x05: debugf("Resetting CRC\n"); bitstream->crc=0; break; case 0x06: debugf("Wake up\n"); return 0; default: goto err; } break; case 0x1: if(command.lo!=0x01)goto err; if(payload>3){ fprintf(stderr,"Error: bank %u does not exist...\n",payload); } debugf("Set bank to %u\n",payload); FPGA->bank=payload; break; case 0x2: if(command.lo!=0x02)goto err; debugf("CRC check: %04X %04X\n",payload,crc); break; case 0x5: if(command.lo!=0x01)goto err; if(payload>2){ fprintf(stderr,"Error: unknown frequency setting...\n"); return -1; } debugf("Boot frequency set to %s\n",freq_settings[payload]); FPGA->freq=payload; break; case 0x6: if(command.lo!=0x02)goto err; payload++; debugf("Row size: %i\n",payload); if(FPGA->CRAM_rowsize)FPGA->BRAM_rowsize=payload; else FPGA->CRAM_rowsize=payload; break; case 0x7: if(command.lo!=0x02)goto err; debugf("Column size: %i\n",payload); if(FPGA->CRAM_colsize)FPGA->BRAM_colsize=payload; else FPGA->CRAM_colsize=payload; break; case 0x8: if(command.lo!=0x02)goto err; if(payload==0x0000){ debugf("Reset write pointer\n"); FPGA->write_pointer=0; } else if(payload==0x0080){ debugf("Don't reset write pointer\n"); } else goto err; break; case 0x9: if(command.lo!=0x02)goto err; if(payload&0xFFDF){ fprintf(stderr,"Error: Unknown warmboot setting... %04X\n",payload); return -1; } debugf("%s warmboot\n",boot_settings[payload?1:0]); FPGA->boot_mode=payload; break; default: goto err; } } err: fprintf(stderr,"Error: unkown command... %08X\n",bitstream->pointer); return -1; } uint8_t get_CRAM_bit_from_sector(FPGA_t* FPGA,int bank,int x,int y){ if(x<0||x>=FPGA->CRAM_rowsize)return 0xFF; if(y<0||y>=FPGA->CRAM_colsize)return 0xFF; if(bank<0||bank>=4)return 0xFF; int bit=y*FPGA->CRAM_rowsize+x; int pointer=bit>>3; int shifts=7-(bit&7); return (FPGA->CRAM[bank][pointer]>>shifts)&1; } int tiles[2][20]={ {18,54,54,42,54,54,54}, {18,2,54,54,54,54,54,54,54,42,54,54,54,54,54,54,54,54} }; int permx[2][18]={ {23,25,26,27,16,17,18,19,20,14,32,33,34,35,36,37,4,5}, {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17}}; int permy[4][16]={ {0,1,3,2,4,5,7,6,8,9,11,10,12,13,15,14}, {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}, }; int tile_row_size[2]={7,17}; int tile_col_size[2]={9,17}; void print_tile(FPGA_t* FPGA,int x,int y){ int type=FPGA->CRAM_rowsize==872; int dirx=0; int diry=0; int tx=x; int ty=y; int corner_flags=0; if(x==0)corner_flags|=1; if(y==0)corner_flags|=2; if(x==tile_row_size[type]*2-1)corner_flags|=4; if(y==tile_col_size[type]*2-1)corner_flags|=8; if(corner_flags&(corner_flags-1)) return; if(x>=tile_row_size[type]){ dirx=1; tx=tile_row_size[type]*2-1-x; } if(y>=tile_col_size[type]){ diry=1; ty=tile_col_size[type]*2-1-y; } int sector=(diry|dirx<<1); int offx=0;for(int i=0;i=2&&!strcmp(argv[1], "-v")) { enable_debug=1; argc--; argv++; } if(argc!=2) { fprintf(stderr,"iceunpack [-v] input\n"); return 1; } FILE*r_file=fopen(argv[1],"rb"); if(r_file==NULL) { fprintf(stderr,"could not open %s\n",argv[1]); return 1; } fseek(r_file,0,SEEK_END); size_t r_size=ftell(r_file); fseek(r_file,0,SEEK_SET); bitstream_t* bitstream=(bitstream_t*)malloc(sizeof(bitstream_t)+r_size); bitstream->len=r_size; bitstream->pointer=0; fread(bitstream->payload,1,r_size,r_file); fclose(r_file); FPGA_t FPGA; memset(&FPGA,0,sizeof(FPGA)); parse(bitstream,&FPGA); free(bitstream); printf(".device 1k\n"); for(int y=0;y<18;y++)for(int x=0;x<14;x++)print_tile(&FPGA,x,y); return 0; }