/* PuteBysh: A BytePusher VM by Ben "GreaseMonkey" Russell, 2010. Public domain. Tested on FreeBSD 8.1-PRERELEASE. Keypad is hard-wired to: 1 2 3 4 q w e r a s d f z x c v Javamannen's audio code has been fixed, now it's a lot smoother. zzo38's code doesn't appear very well timed (it doesn't frameskip AFAIK and the audio tends to stutter) - I should probably prod him about that. */ #include #include #include #include #include #include // must be divisible by 256 #define BUF_LEN 2048 // CPU_DEBUG: print all non-halt steps //define CPU_DEBUG // VUPD_UNLAGGED: draw a pixel after each instruction //define VUPD_UNLAGGED // VUPD_LIVE: allow changing of xx---- byte while drawing // NOTE: REQUIRES VUPD_UNLAGGED TO BE EFFECTIVE, OTHERWISE IT SLOWS DOWN RENDERING //define VUPD_LIVE unsigned char *vmmem = NULL; BITMAP *blah = NULL; unsigned char *aubuf = NULL; int aubufpos = 0; int tick_logic = 0; int tick_logic_catchup; void tick_logic_fn(void) { tick_logic++; } void cleanup(void) { if(vmmem != NULL) free(vmmem); } int main(int argc, char *argv[]) { if(argc <= 1) { printf("usage:\n\t%s prog.bytepusher\n", argv[0]); return 99; } allegro_init(); printf("install_timer: %i\n",install_timer()); printf("install_keyboard: %i\n",install_keyboard()); printf("install_sound: %i\n",install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL)); set_volume_per_voice(0); // thanks to Javamannen for this suggestion (boosts vol to 100%). set_color_depth(8); set_gfx_mode(GFX_AUTODETECT_WINDOWED, 256, 256, 0, 0); PALETTE p; { int r,g,b,i; i = 0; for(r = 0x00; r <= 0xFF; r += 0x33) for(g = 0x00; g <= 0xFF; g += 0x33) for(b = 0x00; b <= 0xFF; b += 0x33) { p[i].r = r*63/255; p[i].g = g*63/255; p[i].b = b*63/255; i++; } i--; while(++i < 256) p[i].r = p[i].g = p[i].b = 0; } set_palette(p); blah = create_bitmap(256, 256); // load program about... NOW { vmmem = malloc(256*256*256+8); int i; for(i = 0; i < 256*256*256+8; i++) vmmem[i] = 0; FILE *fp = fopen(argv[1],"rb"); fread(vmmem, 1, 256*256*256+8, fp); // slow but saves effort fclose(fp); } AUDIOSTREAM *dsp = play_audio_stream(BUF_LEN, 8, 0, 256*60, 256, 128); int x,y,vp,pc,sp,dp,i; install_int_ex(tick_logic_fn, BPS_TO_TIMER(60)); tick_logic_catchup = tick_logic; while(!key[KEY_ESC]) { int doshowgfx = (tick_logic_catchup == tick_logic); vmmem[0] = vmmem[1] = 0; if(key[KEY_X]) vmmem[1] |= 1; if(key[KEY_1]) vmmem[1] |= 2; if(key[KEY_2]) vmmem[1] |= 4; if(key[KEY_3]) vmmem[1] |= 8; if(key[KEY_Q]) vmmem[1] |= 16; if(key[KEY_W]) vmmem[1] |= 32; if(key[KEY_E]) vmmem[1] |= 64; if(key[KEY_A]) vmmem[1] |= 128; if(key[KEY_S]) vmmem[0] |= 1; if(key[KEY_D]) vmmem[0] |= 2; if(key[KEY_Z]) vmmem[0] |= 4; if(key[KEY_C]) vmmem[0] |= 8; if(key[KEY_4]) vmmem[0] |= 16; if(key[KEY_R]) vmmem[0] |= 32; if(key[KEY_F]) vmmem[0] |= 64; if(key[KEY_V]) vmmem[0] |= 128; pc = ( ((unsigned int)vmmem[2]<<16) |((unsigned int)vmmem[3]<<8) |((unsigned int)vmmem[4]) ); #ifdef VUPD_LIVE vp = 0; #else vp = (unsigned int)vmmem[5]<<16; #endif #ifdef VUPD_UNLAGGED if(doshowgfx) lock_bitmap(blah); #endif for(y = 0; y < 256; y++) for(x = 0; x < 256; x++) { sp = ( ((unsigned int)vmmem[pc]<<16) |((unsigned int)vmmem[pc+1]<<8) |((unsigned int)vmmem[pc+2]) ); pc += 3; dp = ( ((unsigned int)vmmem[pc]<<16) |((unsigned int)vmmem[pc+1]<<8) |((unsigned int)vmmem[pc+2]) ); pc += 3; pc = ( ((unsigned int)vmmem[pc]<<16) |((unsigned int)vmmem[pc+1]<<8) |((unsigned int)vmmem[pc+2]) ); vmmem[dp] = vmmem[sp]; #ifdef CPU_DEBUG if(dp != sp) printf("%06X-[%02X]->%06X => %06X\n",sp,vmmem[sp],dp,pc); #endif #ifndef VUPD_UNLAGGED } if(doshowgfx) { lock_bitmap(blah); for(y = 0; y < 256; y++) for(x = 0; x < 256; x++) { #else if(doshowgfx) { #endif #ifdef VUPD_LIVE _putpixel(blah, x,y,vmmem[((unsigned int)vmmem[5]<<16)|vp++]); #else _putpixel(blah, x,y,vmmem[vp++]); #endif } #ifdef VUPD_UNLAGGED if(doshowgfx) release_bitmap(blah); #endif } if(aubuf == NULL) { aubuf = get_audio_stream_buffer(dsp); aubufpos = 0; } if(aubuf != NULL) { pc = ( ((unsigned int)vmmem[6]<<16) |((unsigned int)vmmem[7]<<8) ); // VARIABLE REUSE ABUSE for(i = 0; i < 256; i++) aubuf[aubufpos++] = vmmem[pc++]+0x80; if(aubufpos == BUF_LEN) { free_audio_stream_buffer(dsp); aubuf = NULL; } } if(doshowgfx) { blit(blah, screen, 0, 0, 0, 0, 256, 256); while(tick_logic == tick_logic_catchup) rest(5); } tick_logic_catchup++; if(keyboard_needs_poll()) poll_keyboard(); } return 0; } END_OF_MAIN()