diff -ruN hobones-0.2/AUTHORS /root/nes/AUTHORS --- hobones-0.2/AUTHORS 2006-09-30 18:21:30.000000000 -0500 +++ /root/nes/AUTHORS 2006-10-05 16:35:22.975262624 -0500 @@ -1,3 +1,4 @@ 6502 code - Marat Fayzullin & Alex Krasivsky & Thea DeSilva +APU code - Matthew Conte self test - FluBBa YaDa YaDa everything else - Thea DeSilva diff -ruN hobones-0.2/Debug.c /root/nes/Debug.c --- hobones-0.2/Debug.c 2006-10-05 16:40:06.428171232 -0500 +++ /root/nes/Debug.c 2006-10-05 16:08:59.473991408 -0500 @@ -26,6 +26,8 @@ #include "ram.h" #include "io.h" #include "mapper.h" +#include "apu/types.h" +#include "apu/nes_apu.h" #include "header.h" #include "ppu.h" @@ -131,6 +133,7 @@ int J,I,i,j; DAsm(S,R->PC.W); + printf("Enter\n"); printf("ppu_cur_address: 0x%04X\n", cur_state.ppu_cur_address); @@ -303,7 +306,6 @@ /* Continue with emulation */ done: - SDL_SetTimer(0, NULL); return(1); } diff -ruN hobones-0.2/M6502.c /root/nes/M6502.c --- hobones-0.2/M6502.c 2006-09-30 18:21:30.000000000 -0500 +++ /root/nes/M6502.c 2006-10-05 16:30:54.580064896 -0500 @@ -27,9 +27,12 @@ #include "ram.h" #include "io.h" #include "mapper.h" +#include "apu/types.h" +#include "apu/nes_apu.h" #include "header.h" #include "ppu.h" #include "config.h" +#include "sound.h" int pctrace[MAX_TRACE]; @@ -193,6 +196,15 @@ #define M_ROR(Rg) K.B.l=(Rg>>1)|(R->P<<7); \ R->P&=~C_FLAG;R->P|=Rg&C_FLAG;Rg=K.B.l; \ M_FL(Rg) +int apu_cycles; + +int GetCycles6502(int reset) { + int ret; + ret = cur_state.apu_cycles; + if(reset == 1) + cur_state.apu_cycles = 0; + return ret; +} /** Reset6502() **********************************************/ /** This function can be used to reset the registers before **/ @@ -214,6 +226,7 @@ bzero(pctrace, MAX_TRACE); pctrace_index = 0; total_pc = 0; + cur_state.apu_cycles = 0; } /** Int6502() ************************************************/ @@ -258,6 +271,12 @@ sw1 = 0; for(;;) { + if(sound_on ==1) { + if(R->Trace ==1 ) + SDL_PauseAudio(1); + else + SDL_PauseAudio(0); + } #ifdef DEBUG /* Turn tracing on when reached trap address */ if(R->PC.W==R->Trap) R->Trace=1; @@ -287,6 +306,7 @@ #include "Codes.h" } cur_state.cycles+=run_cy; + cur_state.apu_cycles++; cur_state.h_scroll_counter+=run_cy; if((cur_state.cycles > (20 * config.cycles_per_hblank)) && sw1 == 0) { diff -ruN hobones-0.2/M6502.h /root/nes/M6502.h --- hobones-0.2/M6502.h 2006-09-30 18:21:30.000000000 -0500 +++ /root/nes/M6502.h 2006-10-05 14:58:33.209962912 -0500 @@ -20,6 +20,10 @@ extern int globl_count; +extern int apu_cycles; + +int GetCycles6502(int reset); + #ifndef M6502_H #define M6502_H diff -ruN hobones-0.2/Makefile /root/nes/Makefile --- hobones-0.2/Makefile 1969-12-31 18:00:00.000000000 -0600 +++ /root/nes/Makefile 2006-10-05 15:05:47.891632096 -0500 @@ -0,0 +1,68 @@ + + + + + + + +MAKE = make + +CC=gcc + +LDFLAGS=-L/usr/local/lib -L/usr/X11R6/lib -lSDL -lX11 -g3 -ggdb + +CFLAGS=-DLSB_FIRST -I/usr/include/SDL -I/usr/include -DDEBUG -O3 -g3 -ggdb + +PREFIX=/usr/local + +INSTALL=ginstall + +MAN=/usr/man/man3 + +OBJS = disp.o M6502.o main.o ram.o header.o io.o Debug.o ppu.o sound.o config.o \ + mapper.o gg.o nes_apu.o + +all: ${OBJS} + gcc ${CFLAGS} ${LDFLAGS} -o hobones ${OBJS} + +ram.o: ram.c ram.h +main.o: main.c disp.h version.h self_test.h +disp.o: disp.c disp.h +header.o: header.c header.h +M6502.o: M6502.c M6502.h Tables.h Codes.h +io.o: io.c io.h +Debug.o: Debug.c +ppu.o: ppu.c +sound.o: sound.c +config.o: config.c +mapper.o: mapper.c +gg.o: gg.c +self_test.h: + ${MAKE} -C self_test self_test.h + +nes_apu.o: + ${MAKE} -C apu nes_apu.o + +version.h: + ./tools/genversion > version.h + +install: all + if test -e ${PREFIX}/hobones; then rm -rf ${PREFIX}/hobones; fi + if test -e /usr/bin/hobones; then rm -f /usr/bin/hobones; fi + mkdir -p ${PREFIX}/hobones/roms + mkdir ${PREFIX}/hobones/bin + mkdir ${PREFIX}/hobones/etc + ${INSTALL} hobones ${PREFIX}/hobones/bin + ln -s ${PREFIX}/hobones/bin/hobones /usr/bin/hobones + ${INSTALL} man3/hobones.3 ${MAN} + +distclean: clean + ${MAKE} -C tools distclean + ${MAKE} -C apu distclean + rm -f Makefile + rm -f tools/bin2head + +clean: + ${MAKE} -C self_test clean + ${MAKE} -C tools clean + rm -f *.o hobones self_test.h version.h diff -ruN hobones-0.2/Makefile.m4 /root/nes/Makefile.m4 --- hobones-0.2/Makefile.m4 2006-09-30 18:21:30.000000000 -0500 +++ /root/nes/Makefile.m4 2006-10-05 15:04:47.438354592 -0500 @@ -13,7 +13,7 @@ MAN=CONFqqMAN() OBJS = disp.o M6502.o main.o ram.o header.o io.o Debug.o ppu.o sound.o config.o \ - mapper.o gg.o + mapper.o gg.o nes_apu.o all: ${OBJS} gcc ${CFLAGS} ${LDFLAGS} -o hobones ${OBJS} @@ -33,6 +33,9 @@ self_test.h: ${MAKE} -C self_test self_test.h +nes_apu.o: + ${MAKE} -C apu nes_apu.o + version.h: ./tools/genversion > version.h @@ -48,6 +51,7 @@ distclean: clean ${MAKE} -C tools distclean + ${MAKE} -C apu distclean rm -f Makefile rm -f tools/bin2head diff -ruN hobones-0.2/apu/Makefile /root/nes/apu/Makefile --- hobones-0.2/apu/Makefile 1969-12-31 18:00:00.000000000 -0600 +++ /root/nes/apu/Makefile 2006-10-05 15:05:47.897625184 -0500 @@ -0,0 +1,19 @@ + + + + + + + +CC=gcc + +CFLAGS=-DLSB_FIRST -I/usr/include/SDL -I/usr/include -DDEBUG -O3 -g3 -ggdb + +nes_apu.o: nes_apu.c + ${CC} ${CFLAGS} -I../ -c -o ../nes_apu.o nes_apu.c + +distclean: clean + rm -f Makefile + +clean: + rm -f ../nes_apu.o diff -ruN hobones-0.2/apu/Makefile.m4 /root/nes/apu/Makefile.m4 --- hobones-0.2/apu/Makefile.m4 1969-12-31 18:00:00.000000000 -0600 +++ /root/nes/apu/Makefile.m4 2006-10-05 15:05:43.108149024 -0500 @@ -0,0 +1,12 @@ +CC=CONFqqCC() + +CFLAGS=CONFqqCFLAGS() + +nes_apu.o: nes_apu.c + ${CC} ${CFLAGS} -I../ -c -o ../nes_apu.o nes_apu.c + +distclean: clean + rm -f Makefile + +clean: + rm -f ../nes_apu.o diff -ruN hobones-0.2/apu/nes_apu.c /root/nes/apu/nes_apu.c --- hobones-0.2/apu/nes_apu.c 1969-12-31 18:00:00.000000000 -0600 +++ /root/nes/apu/nes_apu.c 2006-10-05 15:28:13.580278472 -0500 @@ -0,0 +1,1213 @@ +/* +** Nofrendo (c) 1998-2000 Matthew Conte (matt@conte.com) +** +** +** This program is free software; you can redistribute it and/or +** modify it under the terms of version 2 of the GNU Library General +** Public License as published by the Free Software Foundation. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Library General Public License for more details. To obtain a +** copy of the GNU Library General Public License, write to the Free +** Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +** +** Any permitted reproduction of these routines, in whole or in part, +** must bear this legend. +** +** +** nes_apu.c +** +** NES APU emulation +** $Id: nes_apu.c,v 1.2 2003/04/09 14:50:32 ben Exp $ +*/ + +#include +#include +#include +#include +#include +#include "types.h" +#include "nes_apu.h" + + +#include +#include +#include +#include +#include +#include + +#include +#include + + +#define APU_OVERSAMPLE +#define APU_VOLUME_DECAY(x) ((x) -= ((x) >> 7)) + + +/* pointer to active APU */ +static apu_t *apu; + +/* look up table madness */ +static int32 decay_lut[16]; +static int vbl_lut[32]; +static int trilength_lut[128]; + +/* noise lookups for both modes */ +#ifndef REALTIME_NOISE +static int8 noise_long_lut[APU_NOISE_32K]; +static int8 noise_short_lut[APU_NOISE_93]; +#endif /* !REALTIME_NOISE */ + +/* $$$ ben : last error */ +#define SET_APU_ERROR(APU,X) \ +if (APU) (APU)->errstr = "apu: " X; else + +#define APU_MIX_ENABLE(BIT) (apu->mix_enable&(1<<(BIT))) + +/* vblank length table used for rectangles, triangle, noise */ +static const uint8 vbl_length[32] = +{ + 5, 127, + 10, 1, + 19, 2, + 40, 3, + 80, 4, + 30, 5, + 7, 6, + 13, 7, + 6, 8, + 12, 9, + 24, 10, + 48, 11, + 96, 12, + 36, 13, + 8, 14, + 16, 15 +}; + +/* frequency limit of rectangle channels */ +static const int freq_limit[8] = +{ + 0x3FF, 0x555, 0x666, 0x71C, 0x787, 0x7C1, 0x7E0, 0x7F0 +}; + +/* noise frequency lookup table */ +static const int noise_freq[16] = +{ + 4, 8, 16, 32, 64, 96, 128, 160, + 202, 254, 380, 508, 762, 1016, 2034, 4068 +}; + +/* DMC transfer freqs */ +const int dmc_clocks[16] = +{ + 428, 380, 340, 320, 286, 254, 226, 214, + 190, 160, 142, 128, 106, 85, 72, 54 +}; + +/* ratios of pos/neg pulse for rectangle waves */ +static const int duty_lut[4] = { 2, 4, 8, 12 }; + + +void apu_setcontext(apu_t *src_apu) +{ + apu = src_apu; + /* $$$ ben reset eoor string here. */ + SET_APU_ERROR(apu,"no error"); +} + +/* +** Simple queue routines +*/ +#define APU_QEMPTY() (apu->q_head == apu->q_tail) + +static int apu_enqueue(apudata_t *d) +{ + ASSERT(apu); + apu->queue[apu->q_head] = *d; + + apu->q_head = (apu->q_head + 1) & APUQUEUE_MASK; + + if (APU_QEMPTY()) { + return -1; + } + return 0; +} + +static apudata_t *apu_dequeue(void) +{ + int loc; + + ASSERT(apu); + + loc = apu->q_tail; + apu->q_tail = (apu->q_tail + 1) & APUQUEUE_MASK; + + return &apu->queue[loc]; +} + +int apu_setchan(int chan, boolean enabled) +{ + const unsigned int max = 6; + int old; + + ASSERT(apu); + if ((unsigned int)chan >= max) { + SET_APU_ERROR(apu,"channel out of range"); + return -1; + } + old = (apu->mix_enable>>chan) & 1; + if (enabled != (boolean)-1) { + apu->mix_enable = (apu->mix_enable & ~(1<>= 1; + sreg |= (bit14 << 14); + return (bit0 ^ 1); +} +#else +static void shift_register15(int8 *buf, int count) +{ + static int sreg = 0x4000; + int bit0, bit1, bit6, bit14; + + if (count == APU_NOISE_93) + { + while (count--) + { + bit0 = sreg & 1; + bit6 = (sreg & 0x40) >> 6; + bit14 = (bit0 ^ bit6); + sreg >>= 1; + sreg |= (bit14 << 14); + *buf++ = bit0 ^ 1; + } + } + else /* 32K noise */ + { + while (count--) + { + bit0 = sreg & 1; + bit1 = (sreg & 2) >> 1; + bit14 = (bit0 ^ bit1); + sreg >>= 1; + sreg |= (bit14 << 14); + *buf++ = bit0 ^ 1; + } + } +} +#endif + +/* RECTANGLE WAVE +** ============== +** reg0: 0-3=volume, 4=envelope, 5=hold, 6-7=duty cycle +** reg1: 0-2=sweep shifts, 3=sweep inc/dec, 4-6=sweep length, 7=sweep on +** reg2: 8 bits of freq +** reg3: 0-2=high freq, 7-4=vbl length counter +*/ +#define APU_RECTANGLE_OUTPUT chan->output_vol +static int32 apu_rectangle(rectangle_t *chan) +{ + int32 output; + +#ifdef APU_OVERSAMPLE + int num_times; + int32 total; +#endif + + APU_VOLUME_DECAY(chan->output_vol); + + if (FALSE == chan->enabled || 0 == chan->vbl_length) + return APU_RECTANGLE_OUTPUT; + + /* vbl length counter */ + if (FALSE == chan->holdnote) + chan->vbl_length--; + + /* envelope decay at a rate of (env_delay + 1) / 240 secs */ + chan->env_phase -= 4; /* 240/60 */ + while (chan->env_phase < 0) + { + chan->env_phase += chan->env_delay; + + if (chan->holdnote) + chan->env_vol = (chan->env_vol + 1) & 0x0F; + else if (chan->env_vol < 0x0F) + chan->env_vol++; + } + + if ((FALSE == chan->sweep_inc && chan->freq > chan->freq_limit) + || chan->freq < APU_TO_FIXED(4)) + return APU_RECTANGLE_OUTPUT; + + /* frequency sweeping at a rate of (sweep_delay + 1) / 120 secs */ + if (chan->sweep_on && chan->sweep_shifts) + { + chan->sweep_phase -= 2; /* 120/60 */ + while (chan->sweep_phase < 0) + { + chan->sweep_phase += chan->sweep_delay; + if (chan->sweep_inc) /* ramp up */ + chan->freq -= chan->freq >> (chan->sweep_shifts); + else /* ramp down */ + chan->freq += chan->freq >> (chan->sweep_shifts); + } + } + + chan->phaseacc -= apu->cycle_rate; /* # of cycles per sample */ + if (chan->phaseacc >= 0) + return APU_RECTANGLE_OUTPUT; + +#ifdef APU_OVERSAMPLE + num_times = total = 0; + + if (chan->fixed_envelope) + output = chan->volume << 8; /* fixed volume */ + else + output = (chan->env_vol ^ 0x0F) << 8; +#endif + + while (chan->phaseacc < 0) + { + chan->phaseacc += chan->freq; + chan->adder = (chan->adder + 1) & 0x0F; + +#ifdef APU_OVERSAMPLE + if (chan->adder < chan->duty_flip) + total += output; + else + total -= output; + + num_times++; +#endif + } + +#ifdef APU_OVERSAMPLE + chan->output_vol = total / num_times; +#else + if (chan->fixed_envelope) + output = chan->volume << 8; /* fixed volume */ + else + output = (chan->env_vol ^ 0x0F) << 8; + + if (0 == chan->adder) + chan->output_vol = output; + else if (chan->adder == chan->duty_flip) + chan->output_vol = -output; +#endif + + return APU_RECTANGLE_OUTPUT; +} + +/* TRIANGLE WAVE +** ============= +** reg0: 7=holdnote, 6-0=linear length counter +** reg2: low 8 bits of frequency +** reg3: 7-3=length counter, 2-0=high 3 bits of frequency +*/ +#define APU_TRIANGLE_OUTPUT (chan->output_vol + (chan->output_vol >> 2)) +static int32 apu_triangle(triangle_t *chan) +{ + APU_VOLUME_DECAY(chan->output_vol); + + if (FALSE == chan->enabled || 0 == chan->vbl_length) + return APU_TRIANGLE_OUTPUT; + + if (chan->counter_started) + { + if (chan->linear_length > 0) + chan->linear_length--; + if (chan->vbl_length && FALSE == chan->holdnote) + chan->vbl_length--; + } + else if (FALSE == chan->holdnote && chan->write_latency) + { + if (--chan->write_latency == 0) + chan->counter_started = TRUE; + } +/* + if (chan->countmode == COUNTMODE_COUNT) + { + if (chan->linear_length > 0) + chan->linear_length--; + if (chan->vbl_length) + chan->vbl_length--; + } +*/ + if (0 == chan->linear_length || chan->freq < APU_TO_FIXED(4)) /* inaudible */ + return APU_TRIANGLE_OUTPUT; + + chan->phaseacc -= apu->cycle_rate; /* # of cycles per sample */ + while (chan->phaseacc < 0) + { + chan->phaseacc += chan->freq; + chan->adder = (chan->adder + 1) & 0x1F; + + if (chan->adder & 0x10) + chan->output_vol -= (2 << 8); + else + chan->output_vol += (2 << 8); + } + + return APU_TRIANGLE_OUTPUT; +} + + +/* WHITE NOISE CHANNEL +** =================== +** reg0: 0-3=volume, 4=envelope, 5=hold +** reg2: 7=small(93 byte) sample,3-0=freq lookup +** reg3: 7-4=vbl length counter +*/ +#define APU_NOISE_OUTPUT ((chan->output_vol + chan->output_vol + chan->output_vol) >> 2) + +static int32 apu_noise(noise_t *chan) +{ + int32 outvol; + +#if defined(APU_OVERSAMPLE) && defined(REALTIME_NOISE) +#else + int32 noise_bit; +#endif +#ifdef APU_OVERSAMPLE + int num_times; + int32 total; +#endif + + APU_VOLUME_DECAY(chan->output_vol); + + if (FALSE == chan->enabled || 0 == chan->vbl_length) + return APU_NOISE_OUTPUT; + + /* vbl length counter */ + if (FALSE == chan->holdnote) + chan->vbl_length--; + + /* envelope decay at a rate of (env_delay + 1) / 240 secs */ + chan->env_phase -= 4; /* 240/60 */ + while (chan->env_phase < 0) + { + chan->env_phase += chan->env_delay; + + if (chan->holdnote) + chan->env_vol = (chan->env_vol + 1) & 0x0F; + else if (chan->env_vol < 0x0F) + chan->env_vol++; + } + + chan->phaseacc -= apu->cycle_rate; /* # of cycles per sample */ + if (chan->phaseacc >= 0) + return APU_NOISE_OUTPUT; + +#ifdef APU_OVERSAMPLE + num_times = total = 0; + + if (chan->fixed_envelope) + outvol = chan->volume << 8; /* fixed volume */ + else + outvol = (chan->env_vol ^ 0x0F) << 8; +#endif + + while (chan->phaseacc < 0) + { + chan->phaseacc += chan->freq; + +#ifdef REALTIME_NOISE + +#ifdef APU_OVERSAMPLE + if (shift_register15(chan->xor_tap)) + total += outvol; + else + total -= outvol; + + num_times++; +#else + noise_bit = shift_register15(chan->xor_tap); +#endif + +#else + chan->cur_pos++; + + if (chan->short_sample) + { + if (APU_NOISE_93 == chan->cur_pos) + chan->cur_pos = 0; + } + else + { + if (APU_NOISE_32K == chan->cur_pos) + chan->cur_pos = 0; + } + +#ifdef APU_OVERSAMPLE + if (chan->short_sample) + noise_bit = noise_short_lut[chan->cur_pos]; + else + noise_bit = noise_long_lut[chan->cur_pos]; + + if (noise_bit) + total += outvol; + else + total -= outvol; + + num_times++; +#endif +#endif /* REALTIME_NOISE */ + } + +#ifdef APU_OVERSAMPLE + chan->output_vol = total / num_times; +#else + if (chan->fixed_envelope) + outvol = chan->volume << 8; /* fixed volume */ + else + outvol = (chan->env_vol ^ 0x0F) << 8; + +#ifndef REALTIME_NOISE + if (chan->short_sample) + noise_bit = noise_short_lut[chan->cur_pos]; + else + noise_bit = noise_long_lut[chan->cur_pos]; +#endif /* !REALTIME_NOISE */ + + if (noise_bit) + chan->output_vol = outvol; + else + chan->output_vol = -outvol; +#endif + + return APU_NOISE_OUTPUT; +} + + +inline void apu_dmcreload(dmc_t *chan) +{ + chan->address = chan->cached_addr; + chan->dma_length = chan->cached_dmalength; + chan->irq_occurred = FALSE; +} + +/* DELTA MODULATION CHANNEL +** ========================= +** reg0: 7=irq gen, 6=looping, 3-0=pointer to clock table +** reg1: output dc level, 6 bits unsigned +** reg2: 8 bits of 64-byte aligned address offset : $C000 + (value * 64) +** reg3: length, (value * 16) + 1 +*/ +#define APU_DMC_OUTPUT ((chan->output_vol + chan->output_vol + chan->output_vol) >> 2) +static int32 apu_dmc(dmc_t *chan) +{ + int delta_bit; + + APU_VOLUME_DECAY(chan->output_vol); + + /* only process when channel is alive */ + if (chan->dma_length) + { + chan->phaseacc -= apu->cycle_rate; /* # of cycles per sample */ + + while (chan->phaseacc < 0) + { + chan->phaseacc += chan->freq; + + delta_bit = (chan->dma_length & 7) ^ 7; + + if (7 == delta_bit) + { +// chan->cur_byte = nes6502_getbyte(chan->address); XXX not yet + chan->cur_byte = 0; + /* steal a cycle from CPU*/ +// nes6502_setdma(1); XXX not yet + + + if (0xFFFF == chan->address) + chan->address = 0x8000; + else + chan->address++; + } + + if (--chan->dma_length == 0) + { + /* if loop bit set, we're cool to retrigger sample */ + if (chan->looping) + apu_dmcreload(chan); + else + { + /* check to see if we should generate an irq */ + if (chan->irq_gen) + { + chan->irq_occurred = TRUE; + Int6502( &cur_state.cpu, INT_IRQ); + } + + /* bodge for timestamp queue */ + chan->enabled = FALSE; + break; + } + } + + /* positive delta */ + if (chan->cur_byte & (1 << delta_bit)) + { + if (chan->regs[1] < 0x7D) + { + chan->regs[1] += 2; + chan->output_vol += (2 << 8); + } +/* + if (chan->regs[1] < 0x3F) + chan->regs[1]++; + + chan->output_vol &= ~(0x7E << 8); + chan->output_vol |= ((chan->regs[1] << 1) << 8); +*/ + } + /* negative delta */ + else + { + if (chan->regs[1] > 1) + { + chan->regs[1] -= 2; + chan->output_vol -= (2 << 8); + } + +/* + if (chan->regs[1] > 0) + chan->regs[1]--; + + chan->output_vol &= ~(0x7E << 8); + chan->output_vol |= ((chan->regs[1] << 1) << 8); +*/ + } + } + } + + return APU_DMC_OUTPUT; +} + + +static void apu_regwrite(uint32 address, uint8 value) +{ + int chan; + + ASSERT(apu); + switch (address) + { + /* rectangles */ + case APU_WRA0: + case APU_WRB0: + chan = (address & 4) ? 1 : 0; + apu->rectangle[chan].regs[0] = value; + + apu->rectangle[chan].volume = value & 0x0F; + apu->rectangle[chan].env_delay = decay_lut[value & 0x0F]; + apu->rectangle[chan].holdnote = (value & 0x20) ? TRUE : FALSE; + apu->rectangle[chan].fixed_envelope = (value & 0x10) ? TRUE : FALSE; + apu->rectangle[chan].duty_flip = duty_lut[value >> 6]; + break; + + case APU_WRA1: + case APU_WRB1: + chan = (address & 4) ? 1 : 0; + apu->rectangle[chan].regs[1] = value; + apu->rectangle[chan].sweep_on = (value & 0x80) ? TRUE : FALSE; + apu->rectangle[chan].sweep_shifts = value & 7; + apu->rectangle[chan].sweep_delay = decay_lut[(value >> 4) & 7]; + + apu->rectangle[chan].sweep_inc = (value & 0x08) ? TRUE : FALSE; + apu->rectangle[chan].freq_limit = APU_TO_FIXED(freq_limit[value & 7]); + break; + + case APU_WRA2: + case APU_WRB2: + chan = (address & 4) ? 1 : 0; + apu->rectangle[chan].regs[2] = value; +// if (apu->rectangle[chan].enabled) + apu->rectangle[chan].freq = APU_TO_FIXED((((apu->rectangle[chan].regs[3] & 7) << 8) + value) + 1); + break; + + case APU_WRA3: + case APU_WRB3: + chan = (address & 4) ? 1 : 0; + apu->rectangle[chan].regs[3] = value; + +// if (apu->rectangle[chan].enabled) + { + apu->rectangle[chan].vbl_length = vbl_lut[value >> 3]; + apu->rectangle[chan].env_vol = 0; + apu->rectangle[chan].freq = APU_TO_FIXED((((value & 7) << 8) + apu->rectangle[chan].regs[2]) + 1); + apu->rectangle[chan].adder = 0; + } + break; + + /* triangle */ + case APU_WRC0: +/* + if (0 == (apu->triangle.regs[0] & 0x80)) + apu->triangle.countmode = COUNTMODE_COUNT; + else + { + if (apu->triangle.countmode == COUNTMODE_LOAD && apu->triangle.vbl_length) + apu->triangle.linear_length = trilength_lut[value & 0x7F]; + + if (0 == (value & 0x80)) + apu->triangle.countmode = COUNTMODE_COUNT; + } +*/ + apu->triangle.regs[0] = value; + + apu->triangle.holdnote = (value & 0x80) ? TRUE : FALSE; + + +// if (apu->triangle.enabled) + { + if (FALSE == apu->triangle.counter_started && apu->triangle.vbl_length) + apu->triangle.linear_length = trilength_lut[value & 0x7F]; + } + + break; + + case APU_WRC2: + + apu->triangle.regs[1] = value; + +// if (apu->triangle.enabled) + apu->triangle.freq = APU_TO_FIXED((((apu->triangle.regs[2] & 7) << 8) + value) + 1); + break; + + case APU_WRC3: + + apu->triangle.regs[2] = value; + + /* this is somewhat of a hack. there appears to be some latency on + ** the Real Thing between when trireg0 is written to and when the + ** linear length counter actually begins its countdown. we want to + ** prevent the case where the program writes to the freq regs first, + ** then to reg 0, and the counter accidentally starts running because + ** of the sound queue's timestamp processing. + ** + ** set latency to a couple scanlines -- should be plenty of time for + ** the 6502 code to do a couple of table dereferences and load up the + ** other triregs + */ + + /* 06/13/00 MPC -- seems to work OK */ + apu->triangle.write_latency = (int) (2 * config.cycles_per_hblank / APU_FROM_FIXED(apu->cycle_rate)); +/* + apu->triangle.linear_length = trilength_lut[apu->triangle.regs[0] & 0x7F]; + if (0 == (apu->triangle.regs[0] & 0x80)) + apu->triangle.countmode = COUNTMODE_COUNT; + else + apu->triangle.countmode = COUNTMODE_LOAD; +*/ +// if (apu->triangle.enabled) + { + apu->triangle.freq = APU_TO_FIXED((((value & 7) << 8) + apu->triangle.regs[1]) + 1); + apu->triangle.vbl_length = vbl_lut[value >> 3]; + apu->triangle.counter_started = FALSE; + apu->triangle.linear_length = trilength_lut[apu->triangle.regs[0] & 0x7F]; + } + + break; + + /* noise */ + case APU_WRD0: + apu->noise.regs[0] = value; + apu->noise.env_delay = decay_lut[value & 0x0F]; + apu->noise.holdnote = (value & 0x20) ? TRUE : FALSE; + apu->noise.fixed_envelope = (value & 0x10) ? TRUE : FALSE; + apu->noise.volume = value & 0x0F; + break; + + case APU_WRD2: + apu->noise.regs[1] = value; + apu->noise.freq = APU_TO_FIXED(noise_freq[value & 0x0F]); + +#ifdef REALTIME_NOISE + apu->noise.xor_tap = (value & 0x80) ? 0x40: 0x02; +#else + /* detect transition from long->short sample */ + if ((value & 0x80) && FALSE == apu->noise.short_sample) + { + /* recalculate short noise buffer */ + shift_register15(noise_short_lut, APU_NOISE_93); + apu->noise.cur_pos = 0; + } + apu->noise.short_sample = (value & 0x80) ? TRUE : FALSE; +#endif + break; + + case APU_WRD3: + apu->noise.regs[2] = value; + +// if (apu->noise.enabled) + { + apu->noise.vbl_length = vbl_lut[value >> 3]; + apu->noise.env_vol = 0; /* reset envelope */ + } + break; + + /* DMC */ + case APU_WRE0: + apu->dmc.regs[0] = value; + + apu->dmc.freq = APU_TO_FIXED(dmc_clocks[value & 0x0F]); + apu->dmc.looping = (value & 0x40) ? TRUE : FALSE; + + if (value & 0x80) + apu->dmc.irq_gen = TRUE; + else + { + apu->dmc.irq_gen = FALSE; + apu->dmc.irq_occurred = FALSE; + } + break; + + case APU_WRE1: /* 7-bit DAC */ + /* add the _delta_ between written value and + ** current output level of the volume reg + */ + value &= 0x7F; /* bit 7 ignored */ + apu->dmc.output_vol += ((value - apu->dmc.regs[1]) << 8); + apu->dmc.regs[1] = value; +/* + apu->dmc.output_vol = (value & 0x7F) << 8; + apu->dmc.regs[1] = (value & 0x7E) >> 1; +*/ + break; + + case APU_WRE2: + apu->dmc.regs[2] = value; + apu->dmc.cached_addr = 0xC000 + (uint16) (value << 6); + break; + + case APU_WRE3: + apu->dmc.regs[3] = value; + apu->dmc.cached_dmalength = ((value << 4) + 1) << 3; + break; + + case APU_SMASK: + /* bodge for timestamp queue */ + apu->dmc.enabled = (value & 0x10) ? TRUE : FALSE; + + apu->enable_reg = value; + + for (chan = 0; chan < 2; chan++) + { + if (value & (1 << chan)) + apu->rectangle[chan].enabled = TRUE; + else + { + apu->rectangle[chan].enabled = FALSE; + apu->rectangle[chan].vbl_length = 0; + } + } + + if (value & 0x04) + apu->triangle.enabled = TRUE; + else + { + apu->triangle.enabled = FALSE; + apu->triangle.vbl_length = 0; + apu->triangle.linear_length = 0; + apu->triangle.counter_started = FALSE; + apu->triangle.write_latency = 0; + } + + if (value & 0x08) + apu->noise.enabled = TRUE; + else + { + apu->noise.enabled = FALSE; + apu->noise.vbl_length = 0; + } + + if (value & 0x10) + { + if (0 == apu->dmc.dma_length) + apu_dmcreload(&apu->dmc); + } + else + apu->dmc.dma_length = 0; + + apu->dmc.irq_occurred = FALSE; + break; + + /* unused, but they get hit in some mem-clear loops */ + case 0x4009: + case 0x400D: + break; + + default: + break; + } +} + +/* Read from $4000-$4017 */ +uint8 apu_read(uint32 address) +{ + uint8 value; + + ASSERT(apu); + + switch (address) + { + case APU_SMASK: + /* seems that bit 6 denotes vblank -- return 1 for now */ + value = 0x40; + + /* Return 1 in 0-5 bit pos if a channel is playing */ + if (apu->rectangle[0].enabled && apu->rectangle[0].vbl_length) + value |= 0x01; + if (apu->rectangle[1].enabled && apu->rectangle[1].vbl_length) + value |= 0x02; + if (apu->triangle.enabled && apu->triangle.vbl_length) + value |= 0x04; + if (apu->noise.enabled && apu->noise.vbl_length) + value |= 0x08; + + //if (apu->dmc.dma_length) + /* bodge for timestamp queue */ + if (apu->dmc.enabled) + value |= 0x10; + + if (apu->dmc.irq_occurred) + value |= 0x80; + + break; + + + default: + value = (address >> 8); /* heavy capacitance on data bus */ + break; + } + + return value; +} + + +void apu_write(uint32 address, uint8 value) +{ +#ifndef NSF_PLAYER + static uint8 last_write; +#endif /* !NSF_PLAYER */ + apudata_t d; + + switch (address) + { + case 0x4015: + /* bodge for timestamp queue */ + apu->dmc.enabled = (value & 0x10) ? TRUE : FALSE; + + case 0x4000: case 0x4001: case 0x4002: case 0x4003: + case 0x4004: case 0x4005: case 0x4006: case 0x4007: + case 0x4008: case 0x4009: case 0x400A: case 0x400B: + case 0x400C: case 0x400D: case 0x400E: case 0x400F: + case 0x4010: case 0x4011: case 0x4012: case 0x4013: + d.timestamp = GetCycles6502(0); + d.address = address; + d.value = value; + apu_enqueue(&d); + break; + + default: + break; + } +} + +void apu_getpcmdata(void **data, int *num_samples, int *sample_bits) +{ + ASSERT(apu); + *data = apu->buffer; + *num_samples = apu->num_samples; + *sample_bits = apu->sample_bits; +} + + +void apu_process(void *buffer, int num_samples) +{ + apudata_t *d; + uint32 elapsed_cycles; + static int32 prev_sample = 0; + int32 next_sample, accum; + + ASSERT(apu); + + /* grab it, keep it local for speed */ + elapsed_cycles = (uint32) apu->elapsed_cycles; + + /* BLEH */ + apu->buffer = buffer; + + while (num_samples--) + { + while ((FALSE == APU_QEMPTY()) && (apu->queue[apu->q_tail].timestamp <= elapsed_cycles)) + { + d = apu_dequeue(); + apu_regwrite(d->address, d->value); + } + + elapsed_cycles += APU_FROM_FIXED(apu->cycle_rate); + + accum = 0; + if (APU_MIX_ENABLE(0)) accum += apu_rectangle(&apu->rectangle[0]); + if (APU_MIX_ENABLE(1)) accum += apu_rectangle(&apu->rectangle[1]); + if (APU_MIX_ENABLE(2)) accum += apu_triangle(&apu->triangle); + if (APU_MIX_ENABLE(3)) accum += apu_noise(&apu->noise); + if (APU_MIX_ENABLE(4)) accum += apu_dmc(&apu->dmc); + + if (apu->ext && APU_MIX_ENABLE(5)) accum += apu->ext->process(); + + /* do any filtering */ + if (APU_FILTER_NONE != apu->filter_type) + { + next_sample = accum; + + if (APU_FILTER_LOWPASS == apu->filter_type) + { + accum += prev_sample; + accum >>= 1; + } + else + accum = (accum + accum + accum + prev_sample) >> 2; + + prev_sample = next_sample; + } + + /* little extra kick for the kids */ + accum <<= 1; + + /* prevent clipping */ + if (accum > 0x7FFF) + accum = 0x7FFF; + else if (accum < -0x8000) + accum = -0x8000; + + /* signed 16-bit output, unsigned 8-bit */ + if (16 == apu->sample_bits) + *(int16 *)(buffer)++ = (int16) accum; + else + *(uint8 *)(buffer)++ = (accum >> 8) ^ 0x80; + } + + /* resync cycle counter */ + apu->elapsed_cycles = GetCycles6502(0); +} + +/* set the filter type */ +/* $$$ ben : + * Add a get feature (filter_type == -1) and returns old filter type + */ +int apu_setfilter(int filter_type) +{ + int old; + ASSERT(apu); + old = apu->filter_type; + if (filter_type != -1) { + apu->filter_type = filter_type; + } + return old; +} + +void apu_reset(void) +{ + uint32 address; + + ASSERT(apu); + + apu->elapsed_cycles = 0; + memset(&apu->queue, 0, APUQUEUE_SIZE * sizeof(apudata_t)); + apu->q_head = 0; + apu->q_tail = 0; + + /* use to avoid bugs =) */ + for (address = 0x4000; address <= 0x4013; address++) + apu_regwrite(address, 0); + +#ifdef NSF_PLAYER + apu_regwrite(0x400C, 0x10); /* silence noise channel on NSF start */ + apu_regwrite(0x4015, 0x0F); +#else + apu_regwrite(0x4015, 0); +#endif /* NSF_PLAYER */ + + if (apu->ext) + apu->ext->reset(); +} + +void apu_build_luts(int num_samples) +{ + int i; + + /* lut used for enveloping and frequency sweeps */ + for (i = 0; i < 16; i++) + decay_lut[i] = num_samples * (i + 1); + + /* used for note length, based on vblanks and size of audio buffer */ + for (i = 0; i < 32; i++) + vbl_lut[i] = vbl_length[i] * num_samples; + + /* triangle wave channel's linear length table */ + for (i = 0; i < 128; i++) + trilength_lut[i] = (i * num_samples) / 4; + +#ifndef REALTIME_NOISE + /* generate noise samples */ + shift_register15(noise_long_lut, APU_NOISE_32K); + shift_register15(noise_short_lut, APU_NOISE_93); +#endif /* !REALTIME_NOISE */ +} + +static void apu_setactive(apu_t *active) +{ + ASSERT(active); + apu = active; +} + +/* Initializes emulated sound hardware, creates waveforms/voices */ +apu_t *apu_create(int sample_rate, int refresh_rate, int sample_bits, boolean stereo) +{ + apu_t *temp_apu; +/* int channel; */ + + temp_apu = malloc(sizeof(apu_t)); + if (NULL == temp_apu) + return NULL; + /* $$$ ben : safety net, in case we forgot to init something */ + memset(temp_apu,0,sizeof(apu_t)); + + SET_APU_ERROR(temp_apu,"no error"); + temp_apu->sample_rate = sample_rate; + temp_apu->refresh_rate = refresh_rate; + temp_apu->sample_bits = sample_bits; + + temp_apu->num_samples = sample_rate / refresh_rate; + /* turn into fixed point! */ + temp_apu->cycle_rate = (int32) (APU_BASEFREQ * 65536.0 / (float) sample_rate); + + /* build various lookup tables for apu */ + apu_build_luts(temp_apu->num_samples); + + /* set the update routine */ + temp_apu->process = apu_process; + temp_apu->ext = NULL; + + apu_setactive(temp_apu); + apu_reset(); + + temp_apu->mix_enable = 0x3F; +/* for (channel = 0; channel < 6; channel++) */ +/* apu_setchan(channel, TRUE); */ + + apu_setfilter(APU_FILTER_LOWPASS); + + return temp_apu; +} + +apu_t *apu_getcontext(void) +{ + return apu; +} + +void apu_destroy(apu_t *src_apu) +{ + if (src_apu) + { + if (src_apu->ext) + src_apu->ext->shutdown(); + free(src_apu); + } +} + +int apu_setext(apu_t *src_apu, apuext_t *ext) +{ + ASSERT(src_apu); + + /* $$$ ben : seem cleaner like this */ + if (src_apu->ext) { + src_apu->ext->shutdown(); + } + + src_apu->ext = ext; + + /* initialize it */ + if (src_apu->ext) + src_apu->ext->init(); + + /* $$$ ben : May be one day extension int () will return error code */ + return 0; +} + +/* this exists for external mixing routines */ +int32 apu_getcyclerate(void) +{ + ASSERT(apu); + return apu->cycle_rate; +} + +/* +** $Log: nes_apu.c,v $ +** Revision 1.2 2003/04/09 14:50:32 ben +** Clean NSF api. +** +** Revision 1.1 2003/04/08 20:53:01 ben +** Adding more files... +** +** Revision 1.19 2000/07/04 04:53:26 matt +** minor changes, sound amplification +** +** Revision 1.18 2000/07/03 02:18:53 matt +** much better external module exporting +** +** Revision 1.17 2000/06/26 11:01:55 matt +** made triangle a tad quieter +** +** Revision 1.16 2000/06/26 05:10:33 matt +** fixed cycle rate generation accuracy +** +** Revision 1.15 2000/06/26 05:00:37 matt +** cleanups +** +** Revision 1.14 2000/06/23 11:06:24 matt +** more faithful mixing of channels +** +** Revision 1.13 2000/06/23 03:29:27 matt +** cleaned up external sound inteface +** +** Revision 1.12 2000/06/20 00:08:39 matt +** bugfix to rectangle wave +** +** Revision 1.11 2000/06/13 13:48:58 matt +** fixed triangle write latency for fixed point apu cycle rate +** +** Revision 1.10 2000/06/12 01:14:36 matt +** minor change to clipping extents +** +** Revision 1.9 2000/06/09 20:00:56 matt +** fixed noise hiccup in NSF player mode +** +** Revision 1.8 2000/06/09 16:49:02 matt +** removed all floating point from sound generation +** +** Revision 1.7 2000/06/09 15:12:28 matt +** initial revision +** +*/ diff -ruN hobones-0.2/apu/nes_apu.h /root/nes/apu/nes_apu.h --- hobones-0.2/apu/nes_apu.h 1969-12-31 18:00:00.000000000 -0600 +++ /root/nes/apu/nes_apu.h 2006-10-05 15:15:22.863320608 -0500 @@ -0,0 +1,332 @@ +/* +** Nofrendo (c) 1998-2000 Matthew Conte (matt@conte.com) +** +** +** This program is free software; you can redistribute it and/or +** modify it under the terms of version 2 of the GNU Library General +** Public License as published by the Free Software Foundation. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Library General Public License for more details. To obtain a +** copy of the GNU Library General Public License, write to the Free +** Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +** +** Any permitted reproduction of these routines, in whole or in part, +** must bear this legend. +** +** +** nes_apu.h +** +** NES APU emulation header file +** $Id: nes_apu.h,v 1.2 2003/04/09 14:50:32 ben Exp $ +*/ + +#ifndef _NES_APU_H_ +#define _NES_APU_H_ + +#ifdef __GNUC__ +#elif defined(WIN32) +#define INLINE static __inline +#else +#define INLINE static +#endif + +#define NES_MASTER_CLOCK 21477272.7272 + +/* define this for realtime generated noise */ +#define REALTIME_NOISE + +#define APU_WRA0 0x4000 +#define APU_WRA1 0x4001 +#define APU_WRA2 0x4002 +#define APU_WRA3 0x4003 +#define APU_WRB0 0x4004 +#define APU_WRB1 0x4005 +#define APU_WRB2 0x4006 +#define APU_WRB3 0x4007 +#define APU_WRC0 0x4008 +#define APU_WRC2 0x400A +#define APU_WRC3 0x400B +#define APU_WRD0 0x400C +#define APU_WRD2 0x400E +#define APU_WRD3 0x400F +#define APU_WRE0 0x4010 +#define APU_WRE1 0x4011 +#define APU_WRE2 0x4012 +#define APU_WRE3 0x4013 + +#define APU_OAMDMA 0x4014 +#define APU_SMASK 0x4015 +#define APU_JOY0 0x4016 +#define APU_JOY1 0x4017 + +/* length of generated noise */ +#define APU_NOISE_32K 0x7FFF +#define APU_NOISE_93 93 + +#define APU_BASEFREQ (NES_MASTER_CLOCK / 12) + +/* to/from 16.16 fixed point */ +#define APU_TO_FIXED(x) ((x) << 16) +#define APU_FROM_FIXED(x) ((x) >> 16) + + +/* channel structures */ +/* As much data as possible is precalculated, +** to keep the sample processing as lean as possible +*/ + +typedef struct rectangle_s +{ + uint8 regs[4]; + + boolean enabled; + + int32 phaseacc; + int32 freq; + int32 output_vol; + boolean fixed_envelope; + boolean holdnote; + uint8 volume; + + int32 sweep_phase; + int32 sweep_delay; + boolean sweep_on; + uint8 sweep_shifts; + uint8 sweep_length; + boolean sweep_inc; + int32 freq_limit; + + int32 env_phase; + int32 env_delay; + uint8 env_vol; + + int vbl_length; + uint8 adder; + int duty_flip; +} rectangle_t; + +/* +enum +{ + COUNTMODE_LOAD, + COUNTMODE_COUNT +}; +*/ + +typedef struct triangle_s +{ + uint8 regs[3]; + + boolean enabled; + + int32 freq; + int32 phaseacc; + int32 output_vol; + + uint8 adder; + + boolean holdnote; + boolean counter_started; + /* quasi-hack */ + int write_latency; + +// boolean countmode; + + int vbl_length; + int linear_length; + +} triangle_t; + + +typedef struct noise_s +{ + uint8 regs[3]; + + boolean enabled; + + int32 freq; + int32 phaseacc; + int32 output_vol; + + int32 env_phase; + int32 env_delay; + uint8 env_vol; + boolean fixed_envelope; + boolean holdnote; + + uint8 volume; + + int vbl_length; + +#ifdef REALTIME_NOISE + uint8 xor_tap; +#else + boolean short_sample; + int cur_pos; +#endif /* REALTIME_NOISE */ +} noise_t; + +typedef struct dmc_s +{ + uint8 regs[4]; + + /* bodge for timestamp queue */ + boolean enabled; + + int32 freq; + int32 phaseacc; + int32 output_vol; + + uint32 address; + uint32 cached_addr; + int dma_length; + int cached_dmalength; + uint8 cur_byte; + + boolean looping; + boolean irq_gen; + boolean irq_occurred; + +} dmc_t; + +enum +{ + APU_FILTER_NONE, + APU_FILTER_LOWPASS, + APU_FILTER_WEIGHTED +}; + +typedef struct +{ + uint32 min_range, max_range; + uint8 (*read_func)(uint32 address); +} apu_memread; + +typedef struct +{ + uint32 min_range, max_range; + void (*write_func)(uint32 address, uint8 value); +} apu_memwrite; + +/* external sound chip stuff */ +typedef struct apuext_s +{ + void (*init)(void); + void (*shutdown)(void); + void (*reset)(void); + int32 (*process)(void); + apu_memread *mem_read; + apu_memwrite *mem_write; +} apuext_t; + + +/* APU queue structure */ +#define APUQUEUE_SIZE 4096 +#define APUQUEUE_MASK (APUQUEUE_SIZE - 1) + +/* apu ring buffer member */ +typedef struct apudata_s +{ + uint32 timestamp, address; + uint8 value; +} apudata_t; + + +typedef struct apu_s +{ + rectangle_t rectangle[2]; + triangle_t triangle; + noise_t noise; + dmc_t dmc; + uint8 enable_reg; + + apudata_t queue[APUQUEUE_SIZE]; + int q_head, q_tail; + uint32 elapsed_cycles; + + void *buffer; /* pointer to output buffer */ + int num_samples; + + int mix_enable; /* $$$ben : should improve emulation */ + int filter_type; + + int32 cycle_rate; + + int sample_rate; + int sample_bits; + int refresh_rate; + + void (*process)(void *buffer, int num_samples); + + /* $$$ ben : last error string */ + const char * errstr; + + /* external sound chip */ + apuext_t *ext; +} apu_t; + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Function prototypes */ +extern apu_t *apu_create(int sample_rate, int refresh_rate, int sample_bits, boolean stereo); +extern void apu_destroy(apu_t *apu); +extern int apu_setext(apu_t *apu, apuext_t *ext); +extern int apu_setfilter(int filter_type); +extern void apu_process(void *buffer, int num_samples); +extern void apu_reset(void); +extern int apu_setchan(int chan, boolean enabled); +extern int32 apu_getcyclerate(void); +extern apu_t *apu_getcontext(void); + +extern uint8 apu_read(uint32 address); +extern void apu_write(uint32 address, uint8 value); + +/* for visualization */ +extern void apu_getpcmdata(void **data, int *num_samples, int *sample_bits); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _NES_APU_H_ */ + +/* +** $Log: nes_apu.h,v $ +** Revision 1.2 2003/04/09 14:50:32 ben +** Clean NSF api. +** +** Revision 1.1 2003/04/08 20:53:01 ben +** Adding more files... +** +** Revision 1.12 2000/07/04 04:54:48 matt +** minor changes that helped with MAME +** +** Revision 1.11 2000/07/03 02:18:53 matt +** much better external module exporting +** +** Revision 1.10 2000/06/26 05:00:37 matt +** cleanups +** +** Revision 1.9 2000/06/23 03:29:28 matt +** cleaned up external sound inteface +** +** Revision 1.8 2000/06/20 04:06:16 matt +** migrated external sound definition to apu module +** +** Revision 1.7 2000/06/20 00:07:35 matt +** added convenience members to apu_t struct +** +** Revision 1.6 2000/06/09 16:49:02 matt +** removed all floating point from sound generation +** +** Revision 1.5 2000/06/09 15:12:28 matt +** initial revision +** +*/ diff -ruN hobones-0.2/apu/types.h /root/nes/apu/types.h --- hobones-0.2/apu/types.h 1969-12-31 18:00:00.000000000 -0600 +++ /root/nes/apu/types.h 2006-10-05 15:27:13.562402576 -0500 @@ -0,0 +1,108 @@ +/* +** Nofrendo (c) 1998-2000 Matthew Conte (matt@conte.com) +** +** +** This program is free software; you can redistribute it and/or +** modify it under the terms of version 2 of the GNU Library General +** Public License as published by the Free Software Foundation. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Library General Public License for more details. To obtain a +** copy of the GNU Library General Public License, write to the Free +** Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +** +** Any permitted reproduction of these routines, in whole or in part, +** must bear this legend. +** +** +** types.h +** +** Data type definitions +** $Id: types.h,v 1.1 2003/04/08 20:46:46 ben Exp $ +*/ + +#ifndef _TYPES_H_ +#define _TYPES_H_ + +/* Define this if running on little-endian (x86) systems */ + +#ifndef DCPLAYA +# define HOST_LITTLE_ENDIAN +#endif + +#ifdef __GNUC__ +#elif defined(WIN32) +#define INLINE static __inline +#else /* crapintosh? */ +#define INLINE static +#endif + +/* These should be changed depending on the platform */ + + + +#ifdef __BEOS__ /* added by Eli Dayan (for compiling under BeOS) */ + + /* use types in the BeOS Support Kit instead */ + #include +#elif defined (DCPLAYA) /* $$$ added by ben (for compiling with dcplaya) */ +# include +#else + typedef char int8; + typedef short int16; + typedef int int32; + + typedef unsigned char uint8; + typedef unsigned short uint16; + typedef unsigned int uint32; + +#endif + +typedef uint8 boolean; + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef NULL +#define NULL ((void *) 0) +#endif + +#ifdef NOFRENDO_DEBUG +#include +#include "log.h" +#define ASSERT(expr) if (FALSE == (expr))\ + {\ + log_printf("ASSERT: line %d of %s\n", __LINE__, __FILE__);\ + log_shutdown();\ + exit(1);\ + } +#define ASSERT_MSG(msg) {\ + log_printf("ASSERT: %s\n", msg);\ + log_shutdown();\ + exit(1);\ + } +#else /* Not debugging */ +#define ASSERT(expr) +#define ASSERT_MSG(msg) +#endif + +#endif /* _TYPES_H_ */ + +/* +** $Log: types.h,v $ +** Revision 1.1 2003/04/08 20:46:46 ben +** add new input for NES music file. +** +** Revision 1.7 2000/07/04 04:46:44 matt +** moved INLINE define from osd.h +** +** Revision 1.6 2000/06/09 15:12:25 matt +** initial revision +** +*/ diff -ruN hobones-0.2/config.c /root/nes/config.c --- hobones-0.2/config.c 2006-10-05 16:40:28.486003112 -0500 +++ /root/nes/config.c 2006-10-05 16:05:46.359349296 -0500 @@ -33,7 +33,8 @@ 114, "pctrace.log", "memcmp.log", - 4000 + 4000, + 5 }; // default values char *def_keymap[] = { diff -ruN hobones-0.2/config.h /root/nes/config.h --- hobones-0.2/config.h 2006-09-30 18:21:30.000000000 -0500 +++ /root/nes/config.h 2006-10-05 15:42:23.469072496 -0500 @@ -33,6 +33,7 @@ char pctrace_log[128]; char memcmp_log[128]; int keypress_hblanks; + int delay; } config_t; extern config_t def_config, config; diff -ruN hobones-0.2/configure /root/nes/configure --- hobones-0.2/configure 2006-09-30 18:21:30.000000000 -0500 +++ /root/nes/configure 2006-10-05 14:40:51.381173296 -0500 @@ -169,6 +169,9 @@ m4 /tmp/def Makefile.m4 > Makefile m4 /tmp/def tools/Makefile.m4 > tools/Makefile +echo "building Makefile apu/Makefile" +m4 /tmp/def apu/Makefile.m4 > apu/Makefile + echo "building tools/bin2head" printf "#!%s\n" ${PERL} > tools/bin2head cat tools/bin2head.tail >> tools/bin2head diff -ruN hobones-0.2/disp.c /root/nes/disp.c --- hobones-0.2/disp.c 2006-10-05 16:40:34.712056608 -0500 +++ /root/nes/disp.c 2006-10-05 15:57:15.982389848 -0500 @@ -34,6 +34,8 @@ #include "ram.h" #include "io.h" #include "mapper.h" +#include "apu/types.h" +#include "apu/nes_apu.h" #include "header.h" #include "ppu.h" #include "disp.h" @@ -62,11 +64,6 @@ int is_freescroll; int freescroll_x, freescroll_y; -Uint32 jtimer(Uint32 interval) { - - q_input(); - -} void lock_control(void) { lock_controler = 1; @@ -442,7 +439,7 @@ d_screen = SDL_SetVideoMode(screen_w, screen_h, 8, SDL_HWSURFACE| SDL_HWPALETTE | SDL_DOUBLEBUF ); - is_fullscreen = 1; + is_fullscreen = 0; is_freescroll = 0; mouse_x = 0; @@ -469,7 +466,7 @@ frame_step = 0; if(is_fullscreen == 1) SDL_WM_ToggleFullScreen(d_screen); - + } char *but_strings[] = { diff -ruN hobones-0.2/gg.c /root/nes/gg.c --- hobones-0.2/gg.c 2006-09-30 18:21:30.000000000 -0500 +++ /root/nes/gg.c 2006-10-05 15:11:59.339230944 -0500 @@ -35,6 +35,8 @@ #include "ram.h" #include "io.h" #include "mapper.h" +#include "apu/types.h" +#include "apu/nes_apu.h" #include "header.h" #include "ppu.h" #include "gg.h" diff -ruN hobones-0.2/header.c /root/nes/header.c --- hobones-0.2/header.c 2006-09-30 18:21:30.000000000 -0500 +++ /root/nes/header.c 2006-10-05 15:12:14.888297760 -0500 @@ -39,6 +39,8 @@ #include "disp.h" #include "ram.h" #include "mapper.h" +#include "apu/types.h" +#include "apu/nes_apu.h" #include "header.h" #include "io.h" #include "ppu.h" diff -ruN hobones-0.2/header.h /root/nes/header.h --- hobones-0.2/header.h 2006-09-30 18:21:30.000000000 -0500 +++ /root/nes/header.h 2006-10-05 15:25:18.095956144 -0500 @@ -46,6 +46,7 @@ typedef struct { M6502 cpu; + apu_t *apu; // XXX no pointers here, please MMC_t mapper; int have_interrupt; @@ -77,11 +78,13 @@ int ppu_cur_address_high; int ppu_cur_address, ppu_last_address; int tmp_sprite_hit, cycles, frame_num; + int apu_cycles; unsigned char *rom_page_table[8]; unsigned char *vrom_page_table[2]; unsigned char *cram_page_table[2]; - + + } nes_state; extern nes_state cur_state; diff -ruN hobones-0.2/io.c /root/nes/io.c --- hobones-0.2/io.c 2006-09-30 18:21:30.000000000 -0500 +++ /root/nes/io.c 2006-10-05 16:27:42.207310000 -0500 @@ -39,6 +39,8 @@ #include "sound.h" #include "mapper.h" +#include "apu/types.h" +#include "apu/nes_apu.h" #include "header.h" #include "config.h" @@ -52,7 +54,13 @@ register byte ret; int tmp; unsigned char top, bot; // XXX find a better way to do this - + + if(mode == WRITE) + apu_write(Addr, Value); + else + RANGE(0x4000, 0x400f) + return apu_read(Addr); + switch(Addr) { case 0x2000: /* PPU Control Register RW */ @@ -167,145 +175,27 @@ return 0; } break; - - /* Sound registers go here */ - case 0x4000: - if(mode == WRITE) - square1.control1 = Value; - else - return square1.control1; - break; - - case 0x4001: - if(mode == WRITE) - square1.control2 = Value; - else - return square1.control2; - break; - - case 0x4002: - if(mode == WRITE) - square1.freq_low = Value; - else - return square1.freq_low; - break; - - case 0x4003: - if(mode == WRITE) - square1.freq_high = Value; - else - return square1.freq_high; - break; - - - case 0x4004: - if(mode == WRITE) - square2.control1 = Value; - else - return square2.control1; - break; - - case 0x4005: - if(mode == WRITE) - square2.control2 = Value; - else - return square2.control2; - break; - - case 0x4006: - if(mode == WRITE) - square2.freq_low = Value; - else - return square2.freq_low; - break; - - case 0x4007: - if(mode == WRITE) - square2.freq_high = Value; - else - return square2.freq_high; - break; - -// TRI - case 0x4008: - if(mode == WRITE) - tri.control1 = Value; - else - return tri.control1; - break; - - case 0x4009: - if(mode == WRITE) - tri.control2 = Value; - else - return tri.control2; - break; - - case 0x400a: - if(mode == WRITE) - tri.freq_low = Value; - else - return tri.freq_low; - break; - - case 0x400b: - if(mode == WRITE) - tri.freq_high = Value; - else - return tri.freq_high; - break; - - case 0x400c: - if(mode == WRITE) - noise.control1 = Value; - else - return tri.control1; - break; - - case 0x400d: - if(mode == WRITE) - noise.control2 = Value; - else - return tri.control2; - break; - - case 0x400e: - if(mode == WRITE) - noise.freq_low = Value; - else - return tri.freq_low; - break; - - case 0x400f: - if(mode == WRITE) - noise.freq_high = Value; - else - return tri.freq_high; - break; - - - case 0x4014: /* DMA Access to the Sprite Memory W */ - for(tmp = 0; tmp < 256;tmp++) - cur_state.sprite_ram[tmp] = Rd6502( (0x100*Value) + tmp); - return 0; + if(mode == WRITE) { + for(tmp = 0; tmp < 256;tmp++) + cur_state.sprite_ram[tmp] = Rd6502( (0x100*Value) + tmp); + return 0; + } else + return apu_read(0x4014); break; - /* Sound Channel Switch */ case 0x4015: - if(mode == WRITE) { - channel_mask = Value; - } else - return channel_mask; + if(mode == READ) + return apu_read(0x4015); break; - case 0x4016: /* Joystick1 + Strobe RW */ if(mode == READ) { - tmp = 0x40; // always set 7th bit? donno + tmp = apu_read(0x4016); +// tmp = 0x40; // always set 7th bit? donno if(joy1_shift<16) tmp |= ((joy1>>(joy1_shift&7))&1); else { @@ -327,14 +217,15 @@ case 0x4017: /* Joystick2 + Strobe RW */ if(mode == READ) { - tmp = 0x40; // XXX sound verks +// tmp = 0x40; // XXX sound verks + tmp = apu_read(0x4017); tmp |= ((joy2>>joy2_shift)&1); tmp |= (zapper^1)<<4; tmp &= 0xf7; joy1_shift++; return tmp; } else { - control_4017 = Value; +// control_4017 = Value; if(Value&1 == 1) { joy2 = pjoy2; // latch; pjoy2 = 0; diff -ruN hobones-0.2/main.c /root/nes/main.c --- hobones-0.2/main.c 2006-09-30 18:21:30.000000000 -0500 +++ /root/nes/main.c 2006-10-05 16:31:27.202105592 -0500 @@ -36,6 +36,8 @@ #include "disp.h" #include "ram.h" #include "mapper.h" +#include "apu/types.h" +#include "apu/nes_apu.h" #include "header.h" #include "io.h" #include "ppu.h" @@ -104,6 +106,8 @@ fill_seeks( gg_codes[0], gg_codes[1], gg_codes[2]); ram_init(); + init_snd(1); + if(strcmp(argv[i] ,"self") == 0) { start_internal(st_header, st_rom, st_vrom, -1, 1); diff -ruN hobones-0.2/mapper.c /root/nes/mapper.c --- hobones-0.2/mapper.c 2006-09-30 18:21:30.000000000 -0500 +++ /root/nes/mapper.c 2006-10-05 15:13:11.601888352 -0500 @@ -35,6 +35,8 @@ #include "ram.h" #include "io.h" #include "mapper.h" +#include "apu/types.h" +#include "apu/nes_apu.h" #include "header.h" #include "ppu.h" diff -ruN hobones-0.2/ppu.c /root/nes/ppu.c --- hobones-0.2/ppu.c 2006-10-05 16:40:46.330290368 -0500 +++ /root/nes/ppu.c 2006-10-05 16:33:16.808442896 -0500 @@ -38,6 +38,8 @@ #include "io.h" #include "ppu.h" #include "mapper.h" +#include "apu/types.h" +#include "apu/nes_apu.h" #include "header.h" #include "nes_palette.h" #include "config.h" @@ -59,6 +61,9 @@ unsigned char low, mid; sprite_offset = ((((cur_state.ppu_control1_latch>>4)&1)^1)*0x1000); +// We have to copy some of the sprite code here because h_blank uses +// the scans buffer. + for(s=0;s<8;s++) for(i=0;i<8;i++) { y = cur_state.sprite_ram[0]; @@ -82,7 +87,7 @@ x--; data = ((low>>x)&1)|(((mid>>x)&1)<<1); if(data!=0) - if(h_blank(y, x, (struct info *)-1)!=0) goto found; + if(h_blank(y, x, (void *)-1)!=0) goto found; } found: p.hit = (((y+(8+21)) * (config.cycles_per_hblank*3) )+x)/3; @@ -96,8 +101,7 @@ cur_state.sprite_size = SPRITE_SIZE; for(j=0;j<64;j++) if((vert > cur_state.sprite_ram[j*4]) && - (vert < cur_state.sprite_ram[j*4] + (cur_state.sprite_size * 9)) && - j!=0 ){ + (vert < cur_state.sprite_ram[j*4] + (cur_state.sprite_size * 9))) { scan[vert].sprites[scan[vert].counter] = j; scan[vert].SRAM_y[scan[vert].counter] = cur_state.sprite_ram[ (j*4) ]; scan[vert].SRAM_x[scan[vert].counter] = cur_state.sprite_ram[ (j*4) + 3] - 1; @@ -109,17 +113,21 @@ scan[vert].sprite_y[scan[vert].counter] += (8*cur_state.sprite_size); } else scan[vert].sprite_y[scan[vert].counter]--; + if(cur_state.sprite_size ==1 ) q = scan[vert].sprite_offset; else { // here we get data for 8x16 - - q2 =scan[vert].SRAM_i[scan[vert].counter]>>7; + if( scan[vert].sprite_y[scan[vert].counter] < 8) + q = 0; + else + q = 0x1000; +/* q2 =scan[vert].SRAM_i[scan[vert].counter]>>7; q = (scan[vert].SRAM_i[scan[vert].counter]&1)*0x1000; scan[vert].SRAM_i[scan[vert].counter] = clear_bit( scan[vert].SRAM_i[scan[vert].counter],0); - scan[vert].SRAM_i[scan[vert].counter]|=q2; + scan[vert].SRAM_i[scan[vert].counter]|=q2; */ } @@ -152,7 +160,9 @@ } - int h_blank(int vert, int x, struct info *inf) { + int h_blank(int vert, int x, void *inf) { + struct info *sparky; + int loc_h_s; // local h-scroll unsigned char pcolor, back_index; struct zero_pixel z; int sprite_x, sprite_y; @@ -162,16 +172,19 @@ unsigned char low, mid; int full_color, color; - - if(x == -1) + + if(x == -1) { z.pix = d_screen->pixels + (vert*d_screen->pitch) -4 ; // XXX fix the -4 + loc_h_s = cur_state.h_scroll[vert]; + } else + loc_h_s = cur_state.h_scroll_latch; z.pattern_offset = PATTERN_OFFSET; // NAME TABLE if(vhmirror == 0) { if(is_freescroll == 0) - z.nt_bound = (cur_state.h_scroll[vert] * -1)-1; + z.nt_bound = (loc_h_s * -1)-1; else z.nt_bound = (freescroll_x * -1) -1; } else { @@ -181,7 +194,6 @@ z.nt_bound = (freescroll_y * -1) -17; } - if(vhmirror == 0) { z.nt_left = NAME_TABLE_SELECT&1; z.nt_right = z.nt_left^1; // (NAME_TABLE_SELECT+1)&1; @@ -192,88 +204,91 @@ z.nt_right = z.nt_left^1; } - if(is_freescroll == 0) { - z.ntsprite_y = (((vert+cur_state.v_scroll)%240) % 8); - z.name_table_y = (((vert+cur_state.v_scroll)%240) / 8) % 30; - z.attrib_y = (((vert+cur_state.v_scroll)%240) / 32) % 8; - z.attrib_suby = ((((vert+cur_state.v_scroll)%240)) / 16) % 2; - } else { - z.ntsprite_y = (((vert+freescroll_y)%240) % 8); - z.name_table_y = (((vert+freescroll_y)%240) / 8) % 30; - z.attrib_y = (((vert+freescroll_y)%240) / 32) % 8; - z.attrib_suby = ((((vert+freescroll_y)%240)) / 16) % 2; - } + if(is_freescroll == 0) { + z.ntsprite_y = (((vert+cur_state.v_scroll)%240) % 8); + z.name_table_y = (((vert+cur_state.v_scroll)%240) / 8) % 30; + z.attrib_y = (((vert+cur_state.v_scroll)%240) / 32) % 8; + z.attrib_suby = ((((vert+cur_state.v_scroll)%240)) / 16) % 2; + } else { + z.ntsprite_y = (((vert+freescroll_y)%240) % 8); + z.name_table_y = (((vert+freescroll_y)%240) / 8) % 30; + z.attrib_y = (((vert+freescroll_y)%240) / 32) % 8; + z.attrib_suby = ((((vert+freescroll_y)%240)) / 16) % 2; + } - if(vhmirror == 1) { - if(vert>z.nt_bound) - name_table = z.nt_right; - else - name_table = z.nt_left; - } - + if(vhmirror == 1) { + if(vert>z.nt_bound) + name_table = z.nt_right; + else + name_table = z.nt_left; + } // /zero_pixel for(i=0;i<256;i++) { color = cur_state.pal[0]; - if(x != -1) i = x; + + if(x != -1) + i = x; + __asm__("// HERE START // "); if(vhmirror == 0) { if(i>z.nt_bound) name_table = z.nt_right; else name_table = z.nt_left; - } - - - if(is_freescroll == 0) { - attrib_x = ((i+cur_state.h_scroll[vert]) & 0xff) / 32; - attrib_subx = (((i+cur_state.h_scroll[vert]) & 0xff) / 16)%2; - name_table_x = ((i+cur_state.h_scroll[vert]) &0xff )/8; - ntsprite_x = ((((i+cur_state.h_scroll[vert])& 0xff)%8)*-1)+7; - } else { - attrib_x = ((i+freescroll_x) & 0xff) / 32; - attrib_subx = (((i+freescroll_x)&0xff) / 16)%2; - name_table_x = ((i+freescroll_x) & 0xff )/8; - ntsprite_x = ((((i+freescroll_x&0xff))%8)*-1)+7; } - q = cur_state.ppu_ram[ ((z.name_table_y*32)+name_table_x) + - (name_table *0x400)]*16; - if(vram0==0) { - low = VROM_TABLE_ADDR( (q+z.ntsprite_y) + z.pattern_offset); - mid = VROM_TABLE_ADDR( (q+z.ntsprite_y+8) +z.pattern_offset); - } else { - low = CRAM_TABLE_ADDR( (q+z.ntsprite_y) + z.pattern_offset); - mid = CRAM_TABLE_ADDR( (q+z.ntsprite_y+8) +z.pattern_offset); - } - back_index = (low>>ntsprite_x)&1 | (((mid>>ntsprite_x)&1)<<1); + if(is_freescroll == 0) { + attrib_x = ((i+loc_h_s) & 0xff) / 32; + attrib_subx = (((i+loc_h_s) & 0xff) / 16)%2; + name_table_x = ((i+loc_h_s) &0xff )/8; + ntsprite_x = ((((i+loc_h_s)& 0xff)%8)*-1)+7; + } else { + attrib_x = ((i+freescroll_x) & 0xff) / 32; + attrib_subx = (((i+freescroll_x)&0xff) / 16)%2; + name_table_x = ((i+freescroll_x) & 0xff )/8; + ntsprite_x = ((((i+freescroll_x&0xff))%8)*-1)+7; + } - if(x != -1) { - if((int)inf != -1) { - inf->name_table =name_table; - inf->attrib_x = attrib_x; - inf->attrib_y = z.attrib_y; - inf->attrib_subx = attrib_subx; - inf->attrib_suby = z.attrib_suby; - inf->ntsprite_x = ntsprite_x; - inf->ntsprite_y = z.ntsprite_y; - inf->name_table_x = name_table_x; - inf->name_table_y = z.name_table_y; + q = cur_state.ppu_ram[ ((z.name_table_y*32)+name_table_x) + + (name_table *0x400)]*16; + + if(vram0==0) { + low = VROM_TABLE_ADDR( (q+z.ntsprite_y) + z.pattern_offset); + mid = VROM_TABLE_ADDR( (q+z.ntsprite_y+8) +z.pattern_offset); + } else { + low = CRAM_TABLE_ADDR( (q+z.ntsprite_y) + z.pattern_offset); + mid = CRAM_TABLE_ADDR( (q+z.ntsprite_y+8) +z.pattern_offset); + } + back_index = (low>>ntsprite_x)&1 | (((mid>>ntsprite_x)&1)<<1); + + if(x != -1) { + if((int)inf != -1) { + sparky = (struct info *)inf; + sparky->name_table =name_table; + sparky->attrib_x = attrib_x; + sparky->attrib_y = z.attrib_y; + sparky->attrib_subx = attrib_subx; + sparky->attrib_suby = z.attrib_suby; + sparky->ntsprite_x = ntsprite_x; + sparky->ntsprite_y = z.ntsprite_y; + sparky->name_table_x = name_table_x; + sparky->name_table_y = z.name_table_y; + } + return back_index; } - return back_index; - } - if(back_index!=0) { - attrib=cur_state.ppu_ram[((z.attrib_y*8)+attrib_x)+((name_table*0x400)+0x3c0)]; - if(attrib_subx == 0) - if(z.attrib_suby == 0) q = 0; else q = 4; - else - if(z.attrib_suby == 0) q = 2; else q = 6; - color = cur_state.pal[back_index | (((attrib>>q)&3)<<2)]; - } - + if(back_index!=0) { + attrib= + cur_state.ppu_ram[((z.attrib_y*8)+attrib_x)+((name_table*0x400)+0x3c0)]; + if(attrib_subx == 0) + if(z.attrib_suby == 0) q = 0; else q = 4; + else + if(z.attrib_suby == 0) q = 2; else q = 6; + color = cur_state.pal[back_index | (((attrib>>q)&3)<<2)]; + } __asm__("// HERE END // "); if(SPRITES_ON && scan[vert].counter != -1) { @@ -287,6 +302,10 @@ sprite_x--; pcolor = (scan[vert].data_low[scan[vert].counter]>>sprite_x)&1 | (((scan[vert].data_mid[scan[vert].counter]>>sprite_x)&1)<<1); + + + if(j == 0) goto no_sprite; + if(SPRITE_BEHIND == 1 && back_index !=0) goto no_sprite; if(pcolor !=0) { pcolor|=((scan[vert].SRAM_a[scan[vert].counter]&3)<<2); @@ -348,9 +367,11 @@ for(vert = 9; vert<240-8;vert++) if( ((cur_state.ppu_control2[vert]>>3)&1)==1) if( (dirt[vert] == 1) || scan[vert].counter != -1) - h_blank(vert, -1, (struct info *)-1); + h_blank(vert, -1, (void *)-1); v_blank(); + SDL_Delay(config.delay); + dirt_latch = 0; } diff -ruN hobones-0.2/ppu.h /root/nes/ppu.h --- hobones-0.2/ppu.h 2006-10-05 16:40:53.127257072 -0500 +++ /root/nes/ppu.h 2006-10-04 14:48:33.000000000 -0500 @@ -76,12 +76,13 @@ int name_table_x, name_table_y; }; + struct zero_pixel scan[240]; void draw(void); void predict(void); void fill_scans(void); -int h_blank(int vert, int x, struct info *inf); +int h_blank(int vert, int x, void *inf); void v_blank(void); void init_ppu(void); diff -ruN hobones-0.2/ram.c /root/nes/ram.c --- hobones-0.2/ram.c 2006-09-30 18:21:30.000000000 -0500 +++ /root/nes/ram.c 2006-10-05 15:13:44.008512864 -0500 @@ -36,6 +36,8 @@ #include "ram.h" #include "io.h" #include "mapper.h" +#include "apu/types.h" +#include "apu/nes_apu.h" #include "header.h" #include "ppu.h" #include "gg.h" diff -ruN hobones-0.2/sound.c /root/nes/sound.c --- hobones-0.2/sound.c 2006-09-30 18:21:30.000000000 -0500 +++ /root/nes/sound.c 2006-10-05 16:27:11.400993272 -0500 @@ -36,57 +36,41 @@ #include "ram.h" #include "io.h" #include "mapper.h" +#include "apu/types.h" +#include "apu/nes_apu.h" #include "header.h" #include "ppu.h" #include "disp.h" #include "sound.h" -unsigned char base_freq; -unsigned char frame_counter; // Possible 5-values? -unsigned char control_4017; - -wav_t square1, square2, tri, noise; -unsigned char channel_mask; - SDL_AudioSpec audio_spec; -int base_mod; - -/* 11050Hz/((240Hz/Divider)*5Steps_per_IRQ) */ -#define FIGURE_BASE base_mod = 11050/((240 / (((control_4017>>6)&1)+4))*5); - - void audio(void *userdata, Uint8 *stream, int len) { - int i; - for(i=0;i>6)&1)^1) )%5; - /* is 4,0,1,2,3 or 0,1,2,3,4 */ - - } + apu_process(stream, len); } -void init_snd(void) { +int sound_on; + + +void init_snd(int on) { SDL_AudioSpec spec; + if(on == 0) { + sound_on = 0; + return; + } + sound_on = 1; spec.freq = 11050; spec.format = AUDIO_S8; spec.channels = 1; spec.samples = 256; spec.callback = audio; - bzero(&square1, sizeof(wav_t) ); - bzero(&square2, sizeof(wav_t) ); - bzero(&tri, sizeof(wav_t) ); - bzero(&noise, sizeof(wav_t) ); - if(SDL_OpenAudio(&spec, &audio_spec) < 0) { printf("sound error: %s\n", SDL_GetError()); exit(-1); } printf("rate: %d\n", audio_spec.freq); - - control_4017 = 0; - frame_counter = 0; - base_freq = 0; + cur_state.apu = apu_create( audio_spec.freq, 60, 8, FALSE); + apu_reset(); SDL_PauseAudio(0); } diff -ruN hobones-0.2/sound.h /root/nes/sound.h --- hobones-0.2/sound.h 2006-09-30 18:21:30.000000000 -0500 +++ /root/nes/sound.h 2006-10-05 16:31:16.635711928 -0500 @@ -26,15 +26,8 @@ Thea DeSilva 2006 */ -typedef struct { - unsigned char control1, control2; - unsigned char freq_low, freq_high; -} wav_t; - -extern wav_t square1, square2, tri, noise; -extern unsigned char channel_mask; -extern unsigned char control_4017; +extern int sound_on; extern SDL_AudioSpec audio_spec; -void init_snd(void); +void init_snd(int on); Binary files hobones-0.2/tmp/.timing.asm.swp and /root/nes/tmp/.timing.asm.swp differ Binary files hobones-0.2/tmp/a.out and /root/nes/tmp/a.out differ Binary files hobones-0.2/tmp/header and /root/nes/tmp/header differ diff -ruN hobones-0.2/tmp/make.sh /root/nes/tmp/make.sh --- hobones-0.2/tmp/make.sh 2006-09-30 18:21:30.000000000 -0500 +++ /root/nes/tmp/make.sh 1969-12-31 18:00:00.000000000 -0600 @@ -1,4 +0,0 @@ -dasm timing.asm -f3 -s timing.sym -cat header > timing.nes -cat a.out >> timing.nes -cat tanks.chr >> timing.nes Binary files hobones-0.2/tmp/tanks.chr and /root/nes/tmp/tanks.chr differ diff -ruN hobones-0.2/tmp/timing.asm /root/nes/tmp/timing.asm --- hobones-0.2/tmp/timing.asm 2006-09-30 18:21:30.000000000 -0500 +++ /root/nes/tmp/timing.asm 1969-12-31 18:00:00.000000000 -0600 @@ -1,104 +0,0 @@ - PROCESSOR 6502 - ORG $8000 - -SetPalette SUBROUTINE - tax - lda #<.Palette - sta PALETTEPTR - lda #>.Palette - sta PALETTEPTR+1 - cpx #$00 - beq .NoAddPalette -.AddPalette - lda PALETTEPTR - clc - adc #$20 - sta PALETTEPTR - lda PALETTEPTR+1 - adc #$00 - sta PALETTEPTR+1 - dex - bne .AddPalette - -.NoAddPalette - ldx #$3f - -Reset_Routine SUBROUTINE -; start here - - sei - cld - - ldx #$ff - txs - -wait_vb0: - lda $2002 - bpl wait_vb0 -wait_vb1: - lda $2002 - bpl wait_vb1 - - lda #$00 - sta $2000 - lda #$80 - sta $2001 - lda #$00 - sta $2005 - sta $2005 - -; Clear PPU - lda #$20 - sta $2006 - lda #$00 - sta $2006 - - ldx #$00 - ldy #$00 -.ClearPPU: - sta $2007 - dex - bne .ClearPPU - dey - bne .ClearPPU - - lda #$00 - sta $2003 - tay -.ClearSpr - sta $2004 - dey - bne .ClearSpr - - lda #$20 - sta $2006 - lda #$10 - sta $2006 - - ldx #$00 - ldy #$00 -.fill0 - sty $2007 - iny - dex - bne .fill0 - -; Turn screen on - - lda #$19 - sta $2001 - -end_loop: - jmp end_loop - rti - -IRQ_Routine SUBROUTINE - rti - -NMI_Routine SUBROUTINE - rti - - ORG $FFFA,0 - dc.w NMI_Routine - dc.w Reset_Routine - dc.w IRQ_Routine Binary files hobones-0.2/tmp/timing.nes and /root/nes/tmp/timing.nes differ diff -ruN hobones-0.2/tmp/timing.sym /root/nes/tmp/timing.sym --- hobones-0.2/tmp/timing.sym 2006-09-30 18:21:30.000000000 -0500 +++ /root/nes/tmp/timing.sym 1969-12-31 18:00:00.000000000 -0600 @@ -1,9 +0,0 @@ -wait_vb0 8005(r ) -wait_vb1 800a(r ) -5.fill0 8052(r ) -end_loop 805e(r ) -NMI_Routine 8063(r ) -IRQ_Routine 8062(r ) -Reset_Routine 8000(r ) -5.ClearSpr 803e(r ) -5.ClearPPU 802f(r ) diff -ruN hobones-0.2/tools/Makefile /root/nes/tools/Makefile --- hobones-0.2/tools/Makefile 1969-12-31 18:00:00.000000000 -0600 +++ /root/nes/tools/Makefile 2006-10-05 15:05:47.894628640 -0500 @@ -0,0 +1,20 @@ + + + + + + + +CC=gcc + +genhead: genhead.c + ${CC} -o genhead genhead.c -ggdb -g3 + +nesinfo: nesinfo.c + ${CC} -o nesinfo nesinfo.c + +distclean: clean + rm -f Makefile + +clean: + rm -f genhead nesinfo diff -ruN hobones-0.2/tools/bin2head /root/nes/tools/bin2head --- hobones-0.2/tools/bin2head 1969-12-31 18:00:00.000000000 -0600 +++ /root/nes/tools/bin2head 2006-10-05 15:05:47.900621728 -0500 @@ -0,0 +1,4 @@ +#!/usr/bin/perl +undef $/;$z=;print "$ARGV[0] = {"; +for($i=0;$i>3; diff -ruN hobones-0.2/www/gen_pack /root/nes/www/gen_pack --- hobones-0.2/www/gen_pack 2006-09-30 18:21:30.000000000 -0500 +++ /root/nes/www/gen_pack 1969-12-31 18:00:00.000000000 -0600 @@ -1,38 +0,0 @@ -#!/bin/sh - -cd ../tools -./genversion > ../version.h -VERSION=`./genversion print` -cd ../www - -printf "Version %s\n" $VERSION - -if [ $1 ]; then - if expr $1 = "clean" > /dev/null; then - cd ../ - make clean - make distclean - rm -f *.log - cd www - rm -rf hobones-$VERSION.tar.gz hobones-$VERSION.sig ../*.tar.gz index.html - else - echo "usage: gen_pack [clean]" - fi -else - ./gen_pack clean - make clean - cd ../../ - cp -rf nes hobones-$VERSION - tar czf hobones-$VERSION.tar.gz hobones-$VERSION - rm -rf hobones-$VERSION - mv hobones-$VERSION.tar.gz nes/www - cd nes/www - man -l ../man3/hobones.3 | man2html > hobones.html - gpg --output hobones-$VERSION.sig --armor --detach-sig hobones-$VERSION.tar.gz - sed -e s/qqVERSION/$VERSION/g < index.in > index.html - cd ../ - cp -rf www host_this-hobones-$VERSION - tar czf host_this-hobones-$VERSION.tar.gz host_this-hobones-$VERSION - rm -rf host_this-hobones-$VERSION - echo "ready" -fi diff -ruN hobones-0.2/www/gg_interaction.txt /root/nes/www/gg_interaction.txt --- hobones-0.2/www/gg_interaction.txt 2006-09-30 18:21:30.000000000 -0500 +++ /root/nes/www/gg_interaction.txt 1969-12-31 18:00:00.000000000 -0600 @@ -1,608 +0,0 @@ -Interacting with the Gamie Genie ROM by THEA! - -Galoob has given us permission (like i'd fucking respect having no permission -anyway) to freely distribute the Codemaster's Game Genie (GG for sort) ROM for -the Nintendo Entertainment System. In this document I have a .NES format of -the ROM uuencoded as gg.nes - -It's been some time since I've actually seen a real Game Genie so I'm not -going to get into how the actual hardware looks but I will get into how the -ROM interacts with the hardware. - -All communication done by the GG ROM is done with writing to these Addresses - -0x8000 0x8008 -0x8001 0x8009 -0x8002 0x800a -0x8003 0x800b -0x8004 0x800c -0x8005 0xfff0 -0x8006 0xfff1 -0x8007 - -0x8000 - 0xffff is mapped to ROM when reading - -When you start the GG ROM it writes: - -0 -> 0xfff0 -1 -> 0xfff1 -0 -> 0xfff0 - -This resets the hardware. - -Assuming X is the cheat code slot, after you've entered your cheat codes the -GG writes: - -Data byte for slot X (0xff if abscent) -> 0x8004 + (X*4) -compare byte for slot X (0xff if abscent) -> 0x8003 + (X*4) -lower address byte for slot X (0xff if abscent) -> 0x8002 + (X*4) -upper address byte - 0x80 for slot X (0xff if abscent) -> 0x8001 + (X*4) - -It then writes a status byte to 0x8000 - -The status bytes is used to tell the hardware which slots are used and whether -or not they have an 8-character code or a 6-character code in them. This bit -of C-style code decodes the status byte: - -for(i=0;i<3;i++) - if( ( status_byte >> (1+i))&1 == 1) - slot_i_is_an_8_character_code - else - if( ( status_byte >> (4+i))&1 == 0) - slot_i_is_a_6_character_code - else - slot_i_is_empty - -After that it writes 0x00 to 0x8000. That starts the game cartridge that's -plugged into the GG. - -begin 644 gg.nes -M3D53&@$!`````````````'C8J0"-`""B_YJI`(WP_R`>\(WQ_R`>\(WP_TPI -M\*)@H`C*T/V(T/I@H@JM`B`0^\K0^*+_FJD'A0&I`(4`J)$`R-#[Q@$0]ZD& -MA0&-`2"I@(4`C0`@SBL`3!_TJ0&-%D"I`(T60*`(K19`:B8'B-#WH`BM%T!J -M)@B(T/=@2(I(F$BE#-`7(&GQ('3QK44`C04@K48`C04@I0"-`""I`8U)`&BH -M:*IH0(87A!@@./*@`+$YA0W(L3F%#JTY`!AI`HTY`*TZ`&D`C3H`J0"%%JD` -MA14@Y_#F%:45Q0W0]>86I1;%#M#I8*46I@T@6O$8916-0`!*J+$YA02M0``I -M`?`'I00I#TP.\:4$2DI*2H49I1<8914XZ02%'J48&&46A1^E'PH*"H4@J0`& -M("H&("H8906%(:4@&&4>A2"E(6D`A2&E(8U!!*4@C4($I1F-0P2I`8U`!""Y -M\6"%)ZD`X`#P!AAE)\K0^V"I`(T#(*D"C11`8*EDA2RD*<0J\#BY``.J&&D% -MA2BE+#CE*)`HA2RE*QAY``-I`X4KR+D``XT&(,BY``.-!B#(N0`#C0<@R,K0 -M]DQZ\80I8*U`!!AI`X4$I2O%!+`*I0SP[B!T\4RY\3CE!(4KH@"D*KU`!)D` -M`^C(Y`30](0J8(4Q(#CRH`"Q.84TJLBQ.84U(%KQA3<8:0(@L/6%.*J]8P6J -MI32=E06E-9V6!>CHH/_(N6,$T/J8G94%Z,8WT/&F.*4Q(.#RIC@@6_*E.&"% -M!*F^A3FI_H4ZI000`N8Z"JBQ.4C(L3D8:;Z%.6AI_H4Z8+UC!:J]E06%-+V6 -M!84UZ.BE+X4\I3"%/:4]T%2E-(4[I2V%/J4NA3^E/]`7O94%J+DC!?`.I3Z9 -MHP2E/)GC!.A,J/*]E06HJ?^9XP3HI3X8:0B%/J4_:0"%/\8[T,JE/!AI"(4\ -MI3UI`(4]QC70J6"E-(4[O94%J*G_F>,$Z,8[T/),N?*%,;UC!1AI`DBE,2`X -M\J``L3F%-,BQ.84UJ0`)'*8SA3:I`J`!A$&%0*D`A4)HJJ4TA3NE0$H8:0&H -ML3F%!*5`*0'P!Z4$*0],,?.E!$I*2DI(O94%J&B9(P6E-IEC!.BE0!AE085` -MQCO0R*5`&&5"A4#&-="Y8*5#20&%0]`7H`BB/;UC!/`'()'SRA#U8""K\\H0 -M[F"@"*(`O6,$\`D@D?/HX#[0\V`@J_/HX#[0ZF"9`@*]XP29``*](P69`0*] -MHP29`P+(R,C(8*G_F0`"R,C(R&"E'RD!"H4$I1XI`04$J*4?"@HI^(4$I1Y* -M&&4$J@G`C4($J2.-002I`8U`!+G[\R4:A02Y^_-)_ST`!`4$G0`$C4,$3+GQ -M`PPPP`T``"P````F````(``````-```3````)@```"`````HJ0&%#*D@A06- -M!B"I`(T&(*($J(T'((C0^LK0]R#3]:(`J0"=8P7HX#+0^"!I\:D.C5``A2VI -M/(U1`(4OJ8"-50"IEHU6`*D4(.GQC4\`J0(@Z?&-5`"I_X4OJ04@Z?&->P"B -M$[U#^)UC!,H0]ZD)C15`J2"-0`2I/XU!!*D`C4($H`"Y__.90P3(P"#0]2"Y -M\:D`A0P@R?2E`0D8A0&-`2`@U/0@R?1,P/2I`(U)`*U)`/#[8"!<\"![]B"2 -M^2#L^B""_"#5_"#:^"#V^"")_:U0`(4MK5$`A2^N3P`@6_(@5_-@K5H`T%VE -M!RD(\"JI"""L]_`CJ3^-60"I]XU:`*D(((_W\`6I($PM]:D`C5L`J0B-7@!, -M9?6E!RD$\">I!""L]_`@J?^-60"I]HU:`*D$((_W\`6I($Q=]:D`C5L`J02- -M7@"M6`#01:4'*0+P'JD"(*SW\!>I/XU7`*GWC5@`J0"-7`"I`HU=`$RO]:4' -M*0'P&ZD!(*SW\!2I_XU7`*GVC5@`J0"-7`"I`8U=`&"%!*+_Z+UD!=UC!=#W -MADN%2NBE!!A]8P6=8P7HX#+0\J5+8*D`A46I!(5&J0&B!:`#(*CPJ0.%3*D$ -MA4VI"(5.I4RF3:1.(*CPI4T8:02%3(!?XI0((_W\`6@+TS[ -M]J`/R(1;8`$!`@(#`P0$`P,"`@(!_X`%!`0#`P0%!`,#`@("`?^``@,$!08& -M!@0#`P("`@'_@`4&!P@'!@4$`P,"`@(!_X#___[^_?W\_/W]_O[^_P&`^_S\ -M_?W\^_S]_?[^_O\!@/[]_/OZ^OK\_?W^_O[_`8#[^OGX^?K[_/W]_O[^_P&` -M2`IH:L9?\`$8=0"5`.9?8,D$T`FE4\D"T!"I`6#)"-`)I5/)`=`#J0%@J0!@ -MR0'0"Z52R0?P,>923.3WR0+0":52\"3&4DSD]\D$T`NE4\D$\!7F4TSD]\D( -MT`FE4_`(QE-,Y/>I`6"I`&"IJH4:B@J%'I@*&&D$R0B0`QAI`84?(+7SYAX@ -MM?/F'R"U\\8>3+7SJ0!,[/>82*9@I&$@$OBE4\D"L!2%885CI5*%8(5BIF"D -M82#J]VBH8(5CI5*%8FBH8!D9&1D:&1D9&1H9&1D9&AD9&1D:K7<$R1K0!:D8 -M3&7XJ1JN;0#@![`""2"-=P2->`2->02->@1@I6,*"@H896)I`TBE90H*&&D2 -MJ*5D"@H8:02J:$@@J/`@"OQH(-G[3*7XYF2E9,D&T!6E90H*"AAI`JJ]:P8X -MZ0,I`?`&I63)"-`1I67)`O`)J0"%9.9E3-?XQF1,"_VE!RF`Q6;0`6"%9LF` -M\`%@I6/)`K`#3'OX3'CYI0P;0#B#Y^]`FI60%9?`@(%OYI64*"AAI -M$JBE9`H*&&D$JB"U^ZD3(*CPJ0!,V?M,6_G&9*5DR?_0#Z5E\`FI!X5DQF5, -M% -M!*`0O>,$R?_P6;UC!$D"G6,$O0L&$`D8?:,$L!9,5OL8?:,$D`VI_YWC!*D` -MG6,$3)/[G:,$O2L&$`D8?>,$L`E,5OL8?>,$L-R=XP2E!-`2O0L&()C[G0L& -MO2L&()C[G2L&Z(C0G&#P"1`$&&D!8#CI`6"@$*D`G6,$J?^=XP3HB-#R8)A( -M"@H*&&D*A7&*2#CI!`H*"AAI#85P(/G[\`,@:/IHJFBH8$@@`/QHG6L&8"`` -M_*5D\`^]:P;0"LJ]:P;0!,9DT/9@(`#\O6L&8*5E"@H*&&5DJF"E8@H*"@H* -MA7:%+:5C"@H*2`H*&&E`A7>%+V@896*-?0!I`Z9[(.#RIGL@6_*E90H*"@H* -M&&F0..5W2DI*2H5YI60XY6(*A7BI$(5ZK7T`"@H*"H4$J0`&!"H&!"H8:0*- -M`T"E!(T"0*DDC0!`J?F-`4"I%(U\`&"E?/`)QGS0!:DPC0!`I7K0`6#&>M`) -MIGNI_X4O3%ORI78897B%=H4MI7<897F%=X4OIGM,6_*%&H0?AGZI`(4>(+7S -MI1X8:0')$-#RYA_&?M#J8*9_I(#(P`70`Z``Z(2`X`C0`J(`AG^]`_V-0P2I -M`8U`!*D_C4$$J0>-0@1,N?$A+"LH)R4D+*:!I(*$@ZFJ(.SWI648:0*%@J5D -MA8$@/?VF@:2"J55,[/>OKZ^OKZ^OK_KZ^OKZ^OKZI8/%@O!%J2.-002IX(U" -M!*`?J?^90P29(`2($/6I((U`!""Y\:6"..D""@H*&&G@C4($J2.-002@#[DM -M_9E#!(@0]ZD0C4`$(+GQ8*4'*3#0!:D!A81@I83P^ZD`C0`@C0$@J6N%@*D& -MA8&ID(6"J0"%@Z(/J?^5D,H0^ZD#A8BI[X6&J0*%AZEQA8F@`(2$L8#P%SCI -M`RD/2@6$D8"I`"H*"@J%A,C`"-#EA(7`"/`'P`;P"DQP_J`#L8!,`/Z@`[&` -MH`"Q@"D'!821@*(`AH2\MOZQ@`H*"@KHO+;^$8"DA)F*`.:$Z.`(T.6EBBE_ -MA8JEBJ:+Q9#0!.21\#7%E-`$Y)7P+<68T`3DF?`EH`&YB@"1@H@0^*`#N8D` -MD8*(N8L`D8*EB26&IH7@"-`"!8>%B3@FA@:'I8`8:0B%@)`"YH&E@AAI!(6" -MD`+F@\:(\`-,R?VB&+V?_I40RA#X3!``H@NUD)T!@,H0^*6)C0"`J0"-`(!L -M_/\#!0($`0`'!@`J`#``;@!R`'P`A@"0`)H`I`"N`+@`P@#,`-8`X`#J`/0` -M_@$(`1(!'`@"`2-%9QX$+,````````+,````"```4C+,798LY`4C+.3<:BSD -M8"H`55J@0`8"H$!0JJ!`#$#`1$@,Q`#$#,1`B`S$`@*Q@`0$"@`%4*S@Q,0$ -M!(W@!Q`%((S`!`2-8`>0!0",``0$"6"@!8$D"$`$!*S@`D`D((S`!`3DY`9` -M)&#$Q`0$C0`%``4@C,`$!.3DH*"@H`Q`!`0)Q:`Q@04(P`0$C:0'0`5@C(0$ -M!`Y`"@`*``Q`!`0L<(<0(.`,0`0$KN`*``H`#$`$!.3D@9`&0`@`!`3DY`9` -M"@`,0`0$X.2FH*#@Q(`$!```(S$`````!00`<`,[<0[_4`S$`SMQ#O]0#,0` -M`````````````*I]\`#P__]XV*D`C0`@HO^:J0"-\/\@'O"-\?\@'O"-\/], -M*?"B8*`(RM#]B-#Z8*(*K0(@$/O*T/BB_YJI!X4!J0"%`*B1`,C0^\8!$/>I -M!H4!C0$@J8"%`(T`(,XK`$P?]*D!C19`J0"-%D"@"*T60&HF!XC0]Z`(K1=` -M:B8(B-#W8$B*2)A(I0S0%R!I\2!T\:U%`(T%(*U&`(T%(*4`C0`@J0&-20!H -MJ&BJ:$"&%X08(#CRH`"Q.84-R+$YA0ZM.0`8:0*-.0"M.@!I`(TZ`*D`A1:I -M`(45(.?PYA6E%<4-T/7F%J46Q0[0Z6"E%J8-(%KQ&&45C4``2JBQ.84$K4`` -M*0'P!Z4$*0],#O&E!$I*2DJ%&:47&&45..D$A1ZE&!AE%H4?I1\*"@J%(*D` -M!B`J!B`J&&4%A2&E(!AE'H4@I2%I`(4AI2&-002E((U"!*49C4,$J0&-0`0@ -MN?%@A2>I`.``\`8892?*T/M@J0"-`R"I`HT40&"I9(4LI"G$*O`XN0`#JAAI -M!84HI2PXY2B0*(4LI2L8>0`#:0.%*\BY``.-!B#(N0`#C08@R+D``XT'(,C* -MT/9,>O&$*6"M0`08:0.%!*4KQ02P"J4,\.X@=/%,N?$XY02%*Z(`I"J]0`29 -M``/HR.0$T/2$*F"%,2`X\J``L3F%-*K(L3F%-2!:\84W&&D"(+#UA3BJO6,% -MJJ4TG94%I36=E@7HZ*#_R+EC!-#ZF)V5!>C&-]#QICBE,2#@\J8X(%ORI3A@ -MA02IOH4YJ?Z%.J4$$`+F.@JHL3E(R+$Y&&F^A3EH:?Z%.F"]8P6JO94%A32] -ME@6%->CHI2^%/*4PA3VE/=!4I32%.Z4MA3ZE+H4_I3_0%[V5!:BY(P7P#J4^ -MF:,$I3R9XP3H3*CRO94%J*G_F>,$Z*4^&&D(A3ZE/VD`A3_&.]#*I3P8:0B% -M/*4]:0"%/<8UT*E@I32%.[V5!:BI_YGC!.C&.]#R3+GRA3&]8P48:0)(I3$@ -M./*@`+$YA33(L3F%-:D`"1RF,X4VJ0*@`81!A4"I`(5":*JE-(4[I4!*&&D! -MJ+$YA02E0"D!\`>E!"D/3#'SI01*2DI*2+V5!:AHF2,%I3:98P3HI4`894&% -M0,8[T,BE0!AE0H5`QC70N6"E0TD!A4/0%Z`(HCV]8P3P!R"1\\H0]6`@J_/* -M$.Y@H`BB`+UC!/`)()'SZ.`^T/-@(*OSZ.`^T.I@F0("O>,$F0`"O2,%F0$" -MO:,$F0,"R,C(R&"I_YD``LC(R,A@I1\I`0J%!*4>*0$%!*BE'PH**?B%!*4> -M2AAE!*H)P(U"!*DCC4$$J0&-0`2Y^_,E&H4$N?OS2?\]``0%!)T`!(U#!$RY -M\0,,,,`-```L````)@```"``````#0``$P```"8````@````**D!A0RI((4% -MC08@J0"-!B"B!*B-!R"(T/K*T/<@T_6B`*D`G6,%Z.`RT/@@:?&I#HU0`(4M -MJ3R-40"%+ZF`C54`J9:-5@"I%"#I\8U/`*D"(.GQC50`J?^%+ZD%(.GQC7L` -MHA.]0_B=8P3*$/>I"8T50*D@C4`$J3^-002I`(U"!*``N?_SF4,$R,`@T/4@ -MN?&I`(4,(,GTI0$)&(4!C0$@(-3T(,GT3,#TJ0"-20"M20#P^V`@7/`@>_8@ -MDOD@[/H@@OP@U?P@VO@@]O@@B?VM4`"%+:U1`(4OKD\`(%OR(%?S8*U:`-!= -MI0-6@"I"""/]_`%J2!,+?6I`(U;`*D(C5X` -M3&7UI0I`HV"`&"E7TD!A5_0`R`#]:58\#*D7+%7R8#0!ZD`A5A,H/:B4"!_ -M]_`(*SW\`ZE7B"/]_`%H"], -M^_:@#\B$6V`!`0("`P,$!`,#`@("`?^`!00$`P,$!00#`P("`@'_@`(#!`4& -M!@8$`P,"`@(!_X`%!@<(!P8%!`,#`@("`?^`___^_OW]_/S]_?[^_O\!@/O\ -M_/W]_/O\_?W^_O[_`8#^_?S[^OKZ_/W]_O[^_P&`^_KY^/GZ^_S]_?[^_O\! -M@$@*:&K&7_`!&'4`E0#F7V#)!-`)I5/)`M`0J0%@R0C0":53R0'0`ZD!8*D` -M8,D!T`NE4LD'\#'F4DSD]\D"T`FE4O`DQE),Y/?)!-`+I5/)!/`5YE-,Y/?) -M"-`)I5/P",933.3WJ0%@J0!@J:J%&HH*A1Z8"AAI!,D(D`,8:0&%'R"U\^8> -M(+7SYA\@M?/&'DRU\ZD`3.SWF$BF8*1A(!+XI5/)`K`4A6&%8Z52A6"%8J9@ -MI&$@ZO=HJ&"%8Z52A6)HJ&`9&1D9&AD9&1D:&1D9&1H9&1D9&JUW!,D:T`6I -M&$QE^*D:KFT`X`>P`@D@C7<$C7@$C7D$C7H$8*5C"@H*&&5B:0-(I64*"AAI -M$JBE9`H*&&D$JFA((*CP(`K\:"#9^TRE^.9DI63)!M`5I64*"@H8:0*JO6L& -M..D#*0'P!J5DR0C0$:5ER0+P":D`A63F94S7^,9D3`O]I0%9,9E -M3'+YYF0@XOM,"_VE8SCI`H5EI6*%9"#B^XI(F$@@"_UHJ&BJ8*5E"@H*"@H8 -M:9B%::5D"@H*"@H8:0J%:*55C6X`I6B-;P`@+_H8:8"%:J5K(%;ZA6NE5HUN -M`*5IC6\`("_Z&&F`A6JE;"!6^H5LI54896N%5:56&&5LA5:F;:55&'T-^H4M -MI588?1[ZA2_HX!#0`J(`AFVF5"!;\DQ7^``$!PD*"0<$`/SY]_;W^?P`]O?Y -M_``$!PD*"0<$`/SY]_:E;L5OD!+0`ZD`8*5O..5NH@,X:LK0^V"E;SCE;J(# -M2LK0_!AI`6!)@,5JD`?P!^D!3&7Z:0%)@&"E,$I030$KT+!B"8^YT+ -M!KTK!B"8^YTK!NB(T)Q@\`D0!!AI`6`XZ0%@H!"I`)UC!*G_G>,$Z(C0\F"8 -M2`H*"AAI"H5QBD@XZ00*"@H8:0V%<"#Y^_`#(&CZ:*IHJ&!((`#\:)UK!F`@ -M`/RE9/`/O6L&T`K*O6L&T`3&9-#V8"``_+UK!F"E90H*"AAE9*I@I6(*"@H* -M"H5VA2VE8PH*"D@*"AAI0(5WA2]H&&5BC7T`:0.F>R#@\J9[(%ORI64*"@H* -M"AAID#CE=TI*2DJ%>:5D..5B"H5XJ1"%>JU]``H*"@J%!*D`!@0J!@0J&&D" -MC0-`I02-`D"I)(T`0*GYC0%`J12-?`!@I7SP"<9\T`6I,(T`0*5ZT`%@QGK0 -M":9[J?^%+TQ;\J5V&&5XA7:%+:5W&&5YA7>%+Z9[3%ORA1J$'X9^J0"%'B"U -M\Z4>&&D!R1#0\N8?QG[0ZF"F?Z2`R,`%T`.@`.B$@.`(T`*B`(9_O0/]C4,$ -MJ0&-0`2I/XU!!*D'C4($3+GQ(2PK*""- -M0@2@'ZG_F4,$F2`$B!#UJ2"-0`0@N?&E@CCI`@H*"AAIX(U"!*DCC4$$H`^Y -M+?V90P2($/>I$(U`!""Y\6"E!RDPT`6I`86$8*6$\/NI`(T`((T!(*EKA8"I -M!H6!J9"%@JD`A8.B#ZG_E9#*$/NI`X6(J>^%AJD"A8>I<86)H`"$A+&`\!!"S````````"S`````@``%(RS%V6+.0%(RSDW&HL -MY&`J`%5:H$`&`J!`4*J@0`Q`P$1(#,0`Q`S$0(@,Q`("L8`$!`H`!5"LX,3$ -M!`2-X`<0!2",P`0$C6`'D`4`C``$!`E@H`6!)`A`!`2LX`)`)"",P`0$Y.0& -M0"1@Q,0$!(T`!0`%((S`!`3DY*"@H*`,0`0$"<6@,8$%",`$!(VD!T`%8(R$ -M!`0.0`H`"@`,0`0$+'"'$"#@#$`$!*[@"@`*``Q`!`3DY(&0!D`(``0$Y.0& -M0`H`#$`$!.#DIJ"@X,2`!`0``",Q``````4$`'`#.W$._U`,Q`,[<0[_4`S$ -M``````````````"J??``\/__>-BI`(T`(*+_FJD`C?#_(![PC?'_(![PC?#_ -M3"GPHF"@",K0_8C0^F"B"JT"(!#[RM#XHO^:J0>%`:D`A0"HD0#(T/O&`1#W -MJ0:%`8T!(*F`A0"-`"#.*P!,'_2I`8T60*D`C19`H`BM%D!J)@>(T/>@"*T7 -M0&HF"(C0]V!(BDB82*4,T!<@:?$@=/&M10"-!2"M1@"-!2"E`(T`(*D!C4D` -M:*AHJFA`AA>$&"`X\J``L3F%#E!"D/3`[QI01*2DI*A1FE%QAE%3CI!(4>I1@891:%'Z4?"@H*A2"I -M``8@*@8@*AAE!84AI2`891Z%(*4A:0"%(:4AC4$$I2"-0@2E&8U#!*D!C4`$ -M(+GQ8(4GJ0#@`/`&&&4GRM#[8*D`C0,@J0*-%$!@J62%+*0IQ"KP.+D``ZH8 -M:06%**4L..4HD"B%+*4K&'D``VD#A2O(N0`#C08@R+D``XT&(,BY``.-!R#( -MRM#V3'KQA"E@K4`$&&D#A02E*\4$L`JE#/#N('3Q3+GQ..4$A2NB`*0JO4`$ -MF0`#Z,CD!-#TA"I@A3$@./*@`+$YA32JR+$YA34@6O&%-QAI`B"P]84XJKUC -M!:JE-)V5!:4UG98%Z.B@_\BY8P30^IB=E07HQC?0\:8XI3$@X/*F."!;\J4X -M8(4$J;Z%.:G^A3JE!!`"YCH*J+$Y2,BQ.1AIOH4Y:&G^A3I@O6,%JKV5!84T -MO98%A37HZ*4OA3RE,(4]I3W05*4TA3NE+84^I2Z%/Z4_T!>]E06HN2,%\`ZE -M/IFC!*4\F>,$Z$RH\KV5!:BI_YGC!.BE/AAI"(4^I3]I`(4_QCO0RJ4\&&D( -MA3RE/6D`A3W&-="I8*4TA3N]E06HJ?^9XP3HQCO0\DRY\H4QO6,%&&D"2*4Q -M(#CRH`"Q.84TR+$YA36I``D@"*(]O6,$\`<@D?/*$/5@(*OS -MRA#N8*`(H@"]8P3P"2"1\^C@/M#S8""K\^C@/M#J8)D"`KWC!)D``KTC!9D! -M`KVC!)D#`LC(R,A@J?^9``+(R,C(8*4?*0$*A02E'BD!!02HI1\*"BGXA02E -M'DH8902J"<"-0@2I(XU!!*D!C4`$N?OS)1J%!+G[\TG_/0`$!02=``2-0P1, -MN?$####`#0``+````"8````@``````T``!,````F````(````"BI`84,J2"% -M!8T&(*D`C08@H@2HC0<@B-#ZRM#W(-/UH@"I`)UC!>C@,M#X(&GQJ0Z-4`"% -M+:D\C5$`A2^I@(U5`*F6C58`J10@Z?&-3P"I`B#I\8U4`*G_A2^I!2#I\8U[ -M`*(3O4/XG6,$RA#WJ0F-%4"I((U`!*D_C4$$J0"-0@2@`+G_\YE#!,C`(-#U -M(+GQJ0"%#"#)]*4!"1B%`8T!("#4]"#)]$S`]*D`C4D`K4D`\/M@(%SP('OV -M()+Y(.SZ((+\(-7\(-KX(/;X((G]K5``A2VM40"%+ZY/`"!;\B!7\V"M6@#0 -M7:4'*0CP*JD((*SW\".I/XU9`*GWC5H`J0@@C_?P!:D@3"WUJ0"-6P"I"(U> -M`$QE]:4'*03P)ZD$(*SW\""I_XU9`*GVC5H`J00@C_?P!:D@3%WUJ0"-6P"I -M!(U>`*U8`-!%I0J0(@K/?P%ZD_C5<`J?>-6`"I`(U<`*D"C5T`3*_U -MI0&2X5*Z*4$&'UC!9UC!>C@,M#RI4M@J0"%1:D$A4:I`:(%H`,@J/"I`X5, -MJ02%3:D(A4ZE3*9-I$X@J/"E31AI!(5-R230"ZD$A4VE3AAI!(5.YDRE3,D3 -MT-FI`X5,J02%3:D2A4ZI$Z9-I$X@J/"E31AI!(5-R230"ZD$A4VE3AAI!(5. -MYDRE3,D;T-FI5:($H``@N/RI`*($H`0@N/RIJJ("H`D@N/RI_Z($H`L@N/RB -M`*``(.KWJ0*-@@!@I5])`85?T`,@`_6E6/`RI%RQ5\F`T`>I`(583*#VHE`@ -M?_?P')@I#\D'T!(@%_BE!R5=\`FE72"L]_`"H`_(A%RE6O`^I%NQ6I -M`(5:3-;VHE$@?_?P*)@I#\D'T!X@%_BE!R5>\!6E7B"L]_`.I5X@C_?P!:`O -M3/OVH`_(A%M@`0$"`@,#!`0#`P("`@'_@`4$!`,#!`4$`P,"`@(!_X`"`P0% -M!@8&!`,#`@("`?^`!08'"`<&!00#`P("`@'_@/___O[]_?S\_?W^_O[_`8#[ -M_/S]_?S[_/W]_O[^_P&`_OW\^_KZ^OS]_?[^_O\!@/OZ^?CY^OO\_?W^_O[_ -M`8!("FAJQE_P`1AU`)4`YE]@R030":53R0+0$*D!8,D(T`FE4\D!T`.I`6"I -M`&#)`=`+I5+)!_`QYE),Y/?)`M`)I5+P),923.3WR030"Z53R03P%>933.3W -MR0C0":53\`C&4TSD]ZD!8*D`8*FJA1J*"H4>F`H8:03)")`#&&D!A1\@M?/F -M'B"U\^8?(+7SQAY,M?.I`$SL]YA(IF"D82`2^*53R0*P%(5AA6.E4H5@A6*F -M8*1A(.KW:*A@A6.E4H5B:*A@&1D9&1H9&1D9&AD9&1D:&1D9&1JM=P3)&M`% -MJ1A,9?BI&JYM`.`'L`()((UW!(UX!(UY!(UZ!&"E8PH*"AAE8FD#2*5E"@H8 -M:1*HI60*"AAI!*IH2""H\"`*_&@@V?M,I?CF9*5DR0;0%:5E"@H*&&D"JKUK -M!CCI`RD!\`:E9,D(T!&E9_A,>/FE!RE`Q6?0`6"%9\E`\`%@3`GYI63P):5ER0+0 -M&JU]!CCI`RD!T`2I!=`"J0?%9-`&JKU[!M`.(/G[T":E9`5E\"`@6_FE90H* -M&&D2J*5D"@H8:02J(+7[J1,@J/"I`$S9^TQ;^<9DI63)_]`/I67P":D'A63& -M94QR^>9D(.+[3`O]I6,XZ0*%9:5BA60@XON*2)A((`O]:*AHJF"E90H*"@H* -M&&F8A6FE9`H*"@H*&&D*A6BE58UN`*5HC6\`("_Z&&F`A6JE:R!6^H5KI5:- -M;@"E:8UO`"`O^AAI@(5JI6P@5OJ%;*55&&5KA56E5AAE;(56IFVE51A]#?J% -M+:56&'T>^H4OZ.`0T`*B`(9MIE0@6_),5_@`!`<)"@D'!`#\^??V]_G\`/;W -M^?P`!`<)"@D'!`#\^??VI6[%;Y`2T`.I`&"E;SCE;J(#.&K*T/M@I6\XY6ZB -M`TK*T/P8:0%@28#%:I`'\`?I`4QE^FD!28!@I7+P#JD`A7*B,""H^JD!A71@ -MJ0&%,$N8CZG0L&N9CZG2L&J0&=(P6I&IUC!.C( -MP!#0TJD.C0Y`J02-#T"I)8T,0*D8A75@I77P"<9UT`6I,(T,0*5S\`VB(.9S -MI7/)&/`5("W[I73P#:(PYG2E=,D8\`X@+?M@J0"%,$ -MJ0"=8P1,D_N=HP2]*P80"1A]XP2P"4Q6^QA]XP2PW)WC!*4$T!*]"P8@F/N= -M"P:]*P8@F/N=*P;HB-"<8/`)$`08:0%@..D!8*`0J0"=8P2I_YWC!.B(T/)@ -MF$@*"@H8:0J%<8I(..D$"@H*&&D-A7`@^?OP`R!H^FBJ:*A@2"``_&B=:P9@ -M(`#\I63P#[UK!M`*RKUK!M`$QF30]F`@`/R]:P9@I64*"@H8962J8*5B"@H* -M"@J%=H4MI6,*"@I("@H8:4"%=X4O:!AE8HU]`&D#IGL@X/*F>R!;\J5E"@H* -M"@H8:9`XY7=*2DI*A7FE9#CE8@J%>*D0A7JM?0`*"@H*A02I``8$*@8$*AAI -M`HT#0*4$C0)`J22-`$"I^8T!0*D4C7P`8*5\\`G&?-`%J3"-`$"E>M`!8,9Z -MT`FF>ZG_A2],6_*E=AAE>(5VA2VE=QAE>85WA2^F>TQ;\H4:A!^&?JD`A1X@ -MM?.E'AAI`E91AI`H6" -MI62%@2`]_::!I(*I54SL]Z^OKZ^OKZ^O^OKZ^OKZ^OJE@\6"\$6I(XU!!*G@ -MC4($H!^I_YE#!)D@!(@0]:D@C4`$(+GQI8(XZ0(*"@H8:>"-0@2I(XU!!*`/ -MN2W]F4,$B!#WJ1"-0`0@N?%@I0`(T`(%AX6).":&!H>E@!AI"(6`D`+F@:6"&&D$ -MA8*0`N:#QHCP`TS)_:(8O9_^E1#*$/A,$`"B"[60G0&`RA#XI8F-`("I`(T` -M@&S\_P,%`@0!``<&`"H`,`!N`'(`?`"&`)``F@"D`*X`N`#"`,P`U@#@`.H` -M]`#^`0@!$@$<"`(!(T5G'@0LP````````LP````(``!2,LQ=EBSD!2,LY-QJ -M+.1@*@!56J!`!@*@0%"JH$`,0,!$2`S$`,0,Q$"(#,0"`K&`!`0*``50K.#$ -MQ`0$C>`'$`4@C,`$!(U@!Y`%`(P`!`0)8*`%@20(0`0$K.`"0"0@C,`$!.3D -M!D`D8,3$!`2-``4`!2",P`0$Y.2@H*"@#$`$!`G%H#&!!0C`!`2-I`=`!6", -MA`0$#D`*``H`#$`$!"QPAQ`@X`Q`!`2NX`H`"@`,0`0$Y.2!D`9`"``$!.3D -M!D`*``Q`!`3@Y*:@H.#$@`0$```C,0`````%!`!P`SMQ#O]0#,0#.W$._U`, -MQ```````````````JGWP`/#__WC8J0"-`""B_YJI`(WP_R`>\(WQ_R`>\(WP -M_TPI\*)@H`C*T/V(T/I@H@JM`B`0^\K0^*+_FJD'A0&I`(4`J)$`R-#[Q@$0 -M]ZD&A0&-`2"I@(4`C0`@SBL`3!_TJ0&-%D"I`(T60*`(K19`:B8'B-#WH`BM -M%T!J)@B(T/=@2(I(F$BE#-`7(&GQ('3QK44`C04@K48`C04@I0"-`""I`8U) -M`&BH:*IH0(87A!@@./*@`+$YA0W(L3F%#JTY`!AI`HTY`*TZ`&D`C3H`J0"% -M%JD`A14@Y_#F%:45Q0W0]>86I1;%#M#I8*46I@T@6O$8916-0`!*J+$YA02M -M0``I`?`'I00I#TP.\:4$2DI*2H49I1<8914XZ02%'J48&&46A1^E'PH*"H4@ -MJ0`&("H&("H8906%(:4@&&4>A2"E(6D`A2&E(8U!!*4@C4($I1F-0P2I`8U` -M!""Y\6"%)ZD`X`#P!AAE)\K0^V"I`(T#(*D"C11`8*EDA2RD*<0J\#BY``.J -M&&D%A2BE+#CE*)`HA2RE*QAY``-I`X4KR+D``XT&(,BY``.-!B#(N0`#C0<@ -MR,K0]DQZ\80I8*U`!!AI`X4$I2O%!+`*I0SP[B!T\4RY\3CE!(4KH@"D*KU` -M!)D``^C(Y`30](0J8(4Q(#CRH`"Q.84TJLBQ.84U(%KQA3<8:0(@L/6%.*J] -M8P6JI32=E06E-9V6!>CHH/_(N6,$T/J8G94%Z,8WT/&F.*4Q(.#RIC@@6_*E -M.&"%!*F^A3FI_H4ZI000`N8Z"JBQ.4C(L3D8:;Z%.6AI_H4Z8+UC!:J]E06% -M-+V6!84UZ.BE+X4\I3"%/:4]T%2E-(4[I2V%/J4NA3^E/]`7O94%J+DC!?`. -MI3Z9HP2E/)GC!.A,J/*]E06HJ?^9XP3HI3X8:0B%/J4_:0"%/\8[T,JE/!AI -M"(4\I3UI`(4]QC70J6"E-(4[O94%J*G_F>,$Z,8[T/),N?*%,;UC!1AI`DBE -M,2`X\J``L3F%-,BQ.84UJ0`)'*8SA3:I`J`!A$&%0*D`A4)HJJ4TA3NE0$H8 -M:0&HL3F%!*5`*0'P!Z4$*0],,?.E!$I*2DI(O94%J&B9(P6E-IEC!.BE0!AE -M085`QCO0R*5`&&5"A4#&-="Y8*5#20&%0]`7H`BB/;UC!/`'()'SRA#U8""K -M\\H0[F"@"*(`O6,$\`D@D?/HX#[0\V`@J_/HX#[0ZF"9`@*]XP29``*](P69 -M`0*]HP29`P+(R,C(8*G_F0`"R,C(R&"E'RD!"H4$I1XI`04$J*4?"@HI^(4$ -MI1Y*&&4$J@G`C4($J2.-002I`8U`!+G[\R4:A02Y^_-)_ST`!`4$G0`$C4,$ -M3+GQ`PPPP`T``"P````F````(``````-```3````)@```"`````HJ0&%#*D@ -MA06-!B"I`(T&(*($J(T'((C0^LK0]R#3]:(`J0"=8P7HX#+0^"!I\:D.C5`` -MA2VI/(U1`(4OJ8"-50"IEHU6`*D4(.GQC4\`J0(@Z?&-5`"I_X4OJ04@Z?&- -M>P"B$[U#^)UC!,H0]ZD)C15`J2"-0`2I/XU!!*D`C4($H`"Y__.90P3(P"#0 -M]2"Y\:D`A0P@R?2E`0D8A0&-`2`@U/0@R?1,P/2I`(U)`*U)`/#[8"!<\"![ -M]B"2^2#L^B""_"#5_"#:^"#V^"")_:U0`(4MK5$`A2^N3P`@6_(@5_-@K5H` -MT%VE!RD(\"JI"""L]_`CJ3^-60"I]XU:`*D(((_W\`6I($PM]:D`C5L`J0B- -M7@!,9?6E!RD$\">I!""L]_`@J?^-60"I]HU:`*D$((_W\`6I($Q=]:D`C5L` -MJ02-7@"M6`#01:4'*0+P'JD"(*SW\!>I/XU7`*GWC5@`J0"-7`"I`HU=`$RO -M]:4'*0'P&ZD!(*SW\!2I_XU7`*GVC5@`J0"-7`"I`8U=`&"%!*+_Z+UD!=UC -M!=#WADN%2NBE!!A]8P6=8P7HX#+0\J5+8*D`A46I!(5&J0&B!:`#(*CPJ0.% -M3*D$A4VI"(5.I4RF3:1.(*CPI4T8:02%3(!?XI0((_W\`6@ -M+TS[]J`/R(1;8`$!`@(#`P0$`P,"`@(!_X`%!`0#`P0%!`,#`@("`?^``@,$ -M!08&!@0#`P("`@'_@`4&!P@'!@4$`P,"`@(!_X#___[^_?W\_/W]_O[^_P&` -M^_S\_?W\^_S]_?[^_O\!@/[]_/OZ^OK\_?W^_O[_`8#[^OGX^?K[_/W]_O[^ -M_P&`2`IH:L9?\`$8=0"5`.9?8,D$T`FE4\D"T!"I`6#)"-`)I5/)`=`#J0%@ -MJ0!@R0'0"Z52R0?P,>923.3WR0+0":52\"3&4DSD]\D$T`NE4\D$\!7F4TSD -M]\D(T`FE4_`(QE-,Y/>I`6"I`&"IJH4:B@J%'I@*&&D$R0B0`QAI`84?(+7S -MYAX@M?/F'R"U\\8>3+7SJ0!,[/>82*9@I&$@$OBE4\D"L!2%885CI5*%8(5B -MIF"D82#J]VBH8(5CI5*%8FBH8!D9&1D:&1D9&1H9&1D9&AD9&1D:K7<$R1K0 -M!:D83&7XJ1JN;0#@![`""2"-=P2->`2->02->@1@I6,*"@H896)I`TBE90H* -M&&D2J*5D"@H8:02J:$@@J/`@"OQH(-G[3*7XYF2E9,D&T!6E90H*"AAI`JJ] -M:P8XZ0,I`?`&I63)"-`1I67)`O`)J0"%9.9E3-?XQF1,"_VE!RF`Q6;0`6"% -M9LF`\`%@I6/)`K`#3'OX3'CYI0P;0#B#Y^]`FI60%9?`@(%OYI64* -M"AAI$JBE9`H*&&D$JB"U^ZD3(*CPJ0!,V?M,6_G&9*5DR?_0#Z5E\`FI!X5D -MQF5,%!*`0O>,$R?_P6;UC!$D"G6,$O0L&$`D8?:,$L!9,5OL8?:,$D`VI_YWC -M!*D`G6,$3)/[G:,$O2L&$`D8?>,$L`E,5OL8?>,$L-R=XP2E!-`2O0L&()C[ -MG0L&O2L&()C[G2L&Z(C0G&#P"1`$&&D!8#CI`6"@$*D`G6,$J?^=XP3HB-#R -M8)A("@H*&&D*A7&*2#CI!`H*"AAI#85P(/G[\`,@:/IHJFBH8$@@`/QHG6L& -M8"``_*5D\`^]:P;0"LJ]:P;0!,9DT/9@(`#\O6L&8*5E"@H*&&5DJF"E8@H* -M"@H*A7:%+:5C"@H*2`H*&&E`A7>%+V@896*-?0!I`Z9[(.#RIGL@6_*E90H* -M"@H*&&F0..5W2DI*2H5YI60XY6(*A7BI$(5ZK7T`"@H*"H4$J0`&!"H&!"H8 -M:0*-`T"E!(T"0*DDC0!`J?F-`4"I%(U\`&"E?/`)QGS0!:DPC0!`I7K0`6#& -M>M`)IGNI_X4O3%ORI78897B%=H4MI7<897F%=X4OIGM,6_*%&H0?AGZI`(4> -M(+7SI1X8:0')$-#RYA_&?M#J8*9_I(#(P`70`Z``Z(2`X`C0`J(`AG^]`_V- -M0P2I`8U`!*D_C4$$J0>-0@1,N?$A+"LH)R4D+*:!I(*$@ZFJ(.SWI648:0*% -M@J5DA8$@/?VF@:2"J55,[/>OKZ^OKZ^OK_KZ^OKZ^OKZI8/%@O!%J2.-002I -MX(U"!*`?J?^90P29(`2($/6I((U`!""Y\:6"..D""@H*&&G@C4($J2.-002@ -M#[DM_9E#!(@0]ZD0C4`$(+GQ8*4'*3#0!:D!A81@I83P^ZD`C0`@C0$@J6N% -M@*D&A8&ID(6"J0"%@Z(/J?^5D,H0^ZD#A8BI[X6&J0*%AZEQA8F@`(2$L8#P -M%SCI`RD/2@6$D8"I`"H*"@J%A,C`"-#EA(7`"/`'P`;P"DQP_J`#L8!,`/Z@ -M`[&`H`"Q@"D'!821@*(`AH2\MOZQ@`H*"@KHO+;^$8"DA)F*`.:$Z.`(T.6E -MBBE_A8JEBJ:+Q9#0!.21\#7%E-`$Y)7P+<68T`3DF?`EH`&YB@"1@H@0^*`# -MN8D`D8*(N8L`D8*EB26&IH7@"-`"!8>%B3@FA@:'I8`8:0B%@)`"YH&E@AAI -M!(6"D`+F@\:(\`-,R?VB&+V?_I40RA#X3!``H@NUD)T!@,H0^*6)C0"`J0"- -M`(!L_/\#!0($`0`'!@`J`#``;@!R`'P`A@"0`)H`I`"N`+@`P@#,`-8`X`#J -M`/0`_@$(`1(!'`@"`2-%9QX$+,````````+,````"```4C+,798LY`4C+.3< -M:BSD8"H`55J@0`8"H$!0JJ!`#$#`1$@,Q`#$#,1`B`S$`@*Q@`0$"@`%4*S@ -MQ,0$!(W@!Q`%((S`!`2-8`>0!0",``0$"6"@!8$D"$`$!*S@`D`D((S`!`3D -MY`9`)&#$Q`0$C0`%``4@C,`$!.3DH*"@H`Q`!`0)Q:`Q@04(P`0$C:0'0`5@ -MC(0$!`Y`"@`*``Q`!`0L<(<0(.`,0`0$KN`*``H`#$`$!.3D@9`&0`@`!`3D -MY`9`"@`,0`0$X.2FH*#@Q(`$!```(S$`````!00`<`,[<0[_4`S$`SMQ#O]0 -M#,0``````````````*I]\`#P__\``````````````````````````/#P\/`` -M````\/#P\``````/#P\/``````\/#P\`````_____P````#_____\/#P\``` -M``#P\/#P`````/#P\/#P\/#P\/#P\/#P\/#P\/#P#P\/#_#P\/`/#P\/\/#P -M\/_____P\/#P_____P\/#P\`````#P\/#P`````/#P\/\/#P\`\/#P_P\/#P -M#P\/#P\/#P\/#P\/#P\/#P\/#P______#P\/#___________`````/____\` -M````______#P\/#_____\/#P\/____\/#P\/_____P\/#P______________ -M________``````````````````````````#P\/#P`````/#P\/``````#P\/ -M#P`````/#P\/`````/____\`````______#P\/``````\/#P\`````#P\/#P -M\/#P\/#P\/#P\/#P\/#P\`\/#P_P\/#P#P\/#_#P\/#_____\/#P\/____\/ -M#P\/``````\/#P\`````#P\/#_#P\/`/#P\/\/#P\`\/#P\/#P\/#P\/#P\/ -M#P\/#P\/_____P\/#P___________P````#_____`````/_____P\/#P____ -M__#P\/#_____#P\/#_____\/#P\/_____________________P`````````` -M````````````````\/#P\`````#P\/#P``````\/#P\`````#P\/#P````#_ -M____`````/_____P\/#P`````/#P\/``````\/#P\/#P\/#P\/#P\/#P\/#P -M\/`/#P\/\/#P\`\/#P_P\/#P______#P\/#_____#P\/#P`````/#P\/```` -M``\/#P_P\/#P#P\/#_#P\/`/#P\/#P\/#P\/#P\/#P\/#P\/#_____\/#P\/ -M__________\`````_____P````#_____\/#P\/_____P\/#P_____P\/#P__ -M____#P\/#_____________________\``````````````````````````/#P -M\/``````\/#P\``````/#P\/``````\/#P\`````_____P````#_____\/#P -M\`````#P\/#P`````/#P\/#P\/#P\/#P\/#P\/#P\/#P#P\/#_#P\/`/#P\/ -M\/#P\/_____P\/#P_____P\/#P\`````#P\/#P`````/#P\/\/#P\`\/#P_P -M\/#P#P\/#P\/#P\/#P\/#P\/#P\/#P______#P\/#___________`````/__ -M__\`````______#P\/#_____\/#P\/____\/#P\/_____P\/#P__________ -M____________``````````````````````````#P\/#P`````/#P\/`````` -M#P\/#P`````/#P\/`````/____\`````______#P\/``````\/#P\`````#P -M\/#P\/#P\/#P\/#P\/#P\/#P\`\/#P_P\/#P#P\/#_#P\/#_____\/#P\/__ -M__\/#P\/``````\/#P\`````#P\/#_#P\/`/#P\/\/#P\`\/#P\/#P\/#P\/ -M#P\/#P\/#P\/_____P\/#P___________P````#_____`````/_____P\/#P -M______#P\/#_____#P\/#_____\/#P\/_____________________P`````` -M````````````````````\/#P\`````#P\/#P``````\/#P\`````#P\/#P`` -M``#_____`````/_____P\/#P`````/#P\/``````\/#P\/#P\/#P\/#P\/#P -M\/#P\/`/#P\/\/#P\`\/#P_P\/#P______#P\/#_____#P\/#P`````/#P\/ -M``````\/#P_P\/#P#P\/#_#P\/`/#P\/#P\/#P\/#P\/#P\/#P\/#_____\/ -M#P\/__________\`````_____P````#_____\/#P\/_____P\/#P_____P\/ -M#P______#P\/#_____________________\````````````````````````` -M`/#P\/``````\/#P\``````/#P\/``````\/#P\`````_____P````#_____ -M\/#P\`````#P\/#P`````/#P\/#P\/#P\/#P\/#P\/#P\/#P#P\/#_#P\/`/ -M#P\/\/#P\/_____P\/#P_____P\/#P\`````#P\/#P`````/#P\/\/#P\`\/ -M#P_P\/#P#P\/#P\/#P\/#P\/#P\/#P\/#P______#P\/#___________```` -M`/____\`````______#P\/#_____\/#P\/____\/#P\/_____P\/#P______ -M________________``````````````````````````#P\/#P`````/#P\/`` -M````#P\/#P`````/#P\/`````/____\`````______#P\/``````\/#P\``` -M``#P\/#P\/#P\/#P\/#P\/#P\/#P\`\/#P_P\/#P#P\/#_#P\/#_____\/#P -M\/____\/#P\/``````\/#P\`````#P\/#_#P\/`/#P\/\/#P\`\/#P\/#P\/ -M#P\/#P\/#P\/#P\/_____P\/#P___________P````#_____`````/_____P -M\/#P______#P\/#_____#P\/#_____\/#P\/_____________________P`` -M````````````````````````\/#P\`````#P\/#P``````\/#P\`````#P\/ -M#P````#_____`````/_____P\/#P`````/#P\/``````\/#P\/#P\/#P\/#P -M\/#P\/#P\/`/#P\/\/#P\`\/#P_P\/#P______#P\/#_____#P\/#P`````/ -M#P\/``````\/#P_P\/#P#P\/#_#P\/`/#P\/#P\/#P\/#P\/#P\/#P\/#___ -M__\/#P\/__________\`````_____P````#_____\/#P\/_____P\/#P____ -M_P\/#P______#P\/#_____________________\````````````````````` -M`````/#P\/``````\/#P\``````/#P\/``````\/#P\`````_____P````#_ -M____\/#P\`````#P\/#P`````/#P\/#P\/#P\/#P\/#P\/#P\/#P#P\/#_#P -M\/`/#P\/\/#P\/_____P\/#P_____P\/#P\`````#P\/#P`````/#P\/\/#P -M\`\/#P_P\/#P#P\/#P\/#P\/#P\/#P\/#P\/#P______#P\/#___________ -M`````/____\`````______#P\/#_____\/#P\/____\/#P\/_____P\/#P__ -M____________________``````````````````````````#P\/#P`````/#P -M\/``````#P\/#P`````/#P\/`````/____\`````______#P\/``````\/#P -M\`````#P\/#P\/#P\/#P\/#P\/#P\/#P\`\/#P_P\/#P#P\/#_#P\/#_____ -M\/#P\/____\/#P\/``````\/#P\`````#P\/#_#P\/`/#P\/\/#P\`\/#P\/ -M#P\/#P\/#P\/#P\/#P\/_____P\/#P___________P````#_____`````/__ -M___P\/#P______#P\/#_____#P\/#_____\/#P\/____________________ -M_P``````````````````````````\/#P\`````#P\/#P``````\/#P\````` -M#P\/#P````#_____`````/_____P\/#P`````/#P\/``````\/#P\/#P\/#P -M\/#P\/#P\/#P\/`/#P\/\/#P\`\/#P_P\/#P______#P\/#_____#P\/#P`` -M```/#P\/``````\/#P_P\/#P#P\/#_#P\/`/#P\/#P\/#P\/#P\/#P\/#P\/ -M#_____\/#P\/__________\`````_____P````#_____\/#P\/_____P\/#P -M_____P\/#P______#P\/#_____________________\````````````````` -M`````````/#P\/``````\/#P\``````/#P\/``````\/#P\`````_____P`` -M``#_____\/#P\`````#P\/#P`````/#P\/#P\/#P\/#P\/#P\/#P\/#P#P\/ -M#_#P\/`/#P\/\/#P\/_____P\/#P_____P\/#P\`````#P\/#P`````/#P\/ -M\/#P\`\/#P_P\/#P#P\/#P\/#P\/#P\/#P\/#P\/#P______#P\/#_______ -M____`````/____\`````______#P\/#_____\/#P\/____\/#P\/_____P\/ -M#P______________________``````````````````````````#P\/#P```` -M`/#P\/``````#P\/#P`````/#P\/`````/____\`````______#P\/`````` -M\/#P\`````#P\/#P\/#P\/#P\/#P\/#P\/#P\`\/#P_P\/#P#P\/#_#P\/#_ -M____\/#P\/____\/#P\/``````\/#P\`````#P\/#_#P\/`/#P\/\/#P\`\/ -M#P\/#P\/#P\/#P\/#P\/#P\/_____P\/#P___________P````#_____```` -M`/_____P\/#P______#P\/#_____#P\/#_____\/#P\/________________ -M_____P``````````````````````````\/#P\`````#P\/#P``````\/#P\` -M````#P\/#P````#_____`````/_____P\/#P`````/#P\/``````\/#P\/#P -M\/#P\/#P\/#P\/#P\/`/#P\/\/#P\`\/#P_P\/#P______#P\/#_____#P\/ -M#P`````/#P\/``````\/#P_P\/#P#P\/#_#P\/`/#P\/#P\/#P\/#P\/#P\/ -M#P\/#_____\/#P\/__________\`````_____P````#_____\/#P\/_____P -M\/#P_____P\/#P______#P\/#_____________________\````````````` -M`````````````/#P\/``````\/#P\``````/#P\/``````\/#P\`````____ -M_P````#_____\/#P\`````#P\/#P`````/#P\/#P\/#P\/#P\/#P\/#P\/#P -M#P\/#_#P\/`/#P\/\/#P\/_____P\/#P_____P\/#P\`````#P\/#P`````/ -M#P\/\/#P\`\/#P_P\/#P#P\/#P\/#P\/#P\/#P\/#P\/#P______#P\/#___ -M________`````/____\`````______#P\/#_____\/#P\/____\/#P\/____ -M_P\/#P______________________``````````````````````````#P\/#P -M`````/#P\/``````#P\/#P`````/#P\/`````/____\`````______#P\/`` -M````\/#P\`````#P\/#P\/#P\/#P\/#P\/#P\/#P\`\/#P_P\/#P#P\/#_#P -M\/#_____\/#P\/____\/#P\/``````\/#P\`````#P\/#_#P\/`/#P\/\/#P -M\`\/#P\/#P\/#P\/#P\/#P\/#P\/_____P\/#P___________P````#_____ -M`````/_____P\/#P______#P\/#_____#P\/#_____\/#P\/____________ -M_________P``````````````````````````\/#P\`````#P\/#P``````\/ -M#P\`````#P\/#P````#_____`````/_____P\/#P`````/#P\/``````\/#P -M\/#P\/#P\/#P\/#P\/#P\/`/#P\/\/#P\`\/#P_P\/#P______#P\/#_____ -M#P\/#P`````/#P\/``````\/#P_P\/#P#P\/#_#P\/`/#P\/#P\/#P\/#P\/ -M#P\/#P\/#_____\/#P\/__________\`````_____P````#_____\/#P\/__ -M___P\/#P_____P\/#P______#P\/#_____________________\````````` -M`````````````````/#P\/``````\/#P\``````/#P\/``````\/#P\````` -M_____P````#_____\/#P\`````#P\/#P`````/#P\/#P\/#P\/#P\/#P\/#P -M\/#P#P\/#_#P\/`/#P\/\/#P\/_____P\/#P_____P\/#P\`````#P\/#P`` -M```/#P\/\/#P\`\/#P_P\/#P#P\/#P\/#P\/#P\/#P\/#P\/#P______#P\/ -M#___________`````/____\`````______#P\/#_____\/#P\/____\/#P\/ -M_____P\/#P______________________``````````````````````````#P -M\/#P`````/#P\/``````#P\/#P`````/#P\/`````/____\`````______#P -M\/``````\/#P\`````#P\/#P\/#P\/#P\/#P\/#P\/#P\`\/#P_P\/#P#P\/ -M#_#P\/#_____\/#P\/____\/#P\/``````\/#P\`````#P\/#_#P\/`/#P\/ -M\/#P\`\/#P\/#P\/#P\/#P\/#P\/#P\/_____P\/#P___________P````#_ -M____`````/_____P\/#P______#P\/#_____#P\/#_____\/#P\/________ -M_____________P``````````````````````````\/#P\`````#P\/#P```` -M``\/#P\`````#P\/#P````#_____`````/_____P\/#P`````/#P\/`````` -M\/#P\/#P\/#P\/#P\/#P\/#P\/`/#P\/\/#P\`\/#P_P\/#P______#P\/#_ -M____#P\/#P`````/#P\/``````\/#P_P\/#P#P\/#_#P\/`/#P\/#P\/#P\/ -M#P\/#P\/#P\/#_____\/#P\/__________\`````_____P````#_____\/#P -M\/_____P\/#P_____P\/#P______#P\/#_____________________\````` -M`````````````````````/#P\/``````\/#P\``````/#P\/``````\/#P\` -M````_____P````#_____\/#P\`````#P\/#P`````/#P\/#P\/#P\/#P\/#P -M\/#P\/#P#P\/#_#P\/`/#P\/\/#P\/_____P\/#P_____P\/#P\`````#P\/ -M#P`````/#P\/\/#P\`\/#P_P\/#P#P\/#P\/#P\/#P\/#P\/#P\/#P______ -M#P\/#___________`````/____\`````______#P\/#_____\/#P\/____\/ -M#P\/_____P\/#P______________________```````````````````````` -M``#P\/#P`````/#P\/``````#P\/#P`````/#P\/`````/____\`````____ -M__#P\/``````\/#P\`````#P\/#P\/#P\/#P\/#P\/#P\/#P\`\/#P_P\/#P -M#P\/#_#P\/#_____\/#P\/____\/#P\/``````\/#P\`````#P\/#_#P\/`/ -M#P\/\/#P\`\/#P\/#P\/#P\/#P\/#P\/#P\/_____P\/#P___________P`` -M``#_____`````/_____P\/#P______#P\/#_____#P\/#_____\/#P\/____ -M_________________P``````````````````````````\/#P\`````#P\/#P -M``````\/#P\`````#P\/#P````#_____`````/_____P\/#P`````/#P\/`` -M````\/#P\/#P\/#P\/#P\/#P\/#P\/`/#P\/\/#P\`\/#P_P\/#P______#P -M\/#_____#P\/#P`````/#P\/``````\/#P_P\/#P#P\/#_#P\/`/#P\/#P\/ -M#P\/#P\/#P\/#P\/#_____\/#P\/__________\`````_____P````#_____ -M\/#P\/_____P\/#P_____P\/#P______#P\/#_____________________\` -M`````````````````````````/#P\/``````\/#P\``````/#P\/``````\/ -M#P\`````_____P````#_____\/#P\`````#P\/#P`````/#P\/#P\/#P\/#P -M\/#P\/#P\/#P#P\/#_#P\/`/#P\/\/#P\/_____P\/#P_____P\/#P\````` -M#P\/#P`````/#P\/\/#P\`\/#P_P\/#P#P\/#P\/#P\/#P\/#P\/#P\/#P__ -M____#P\/#___________`````/____\`````______#P\/#_____\/#P\/__ -M__\/#P\/_____P\/#P______________________```````````````````` -M``````#P\/#P`````/#P\/``````#P\/#P`````/#P\/`````/____\````` -M______#P\/``````\/#P\`````#P\/#P\/#P\/#P\/#P\/#P\/#P\`\/#P_P -M\/#P#P\/#_#P\/#_____\/#P\/____\/#P\/``````\/#P\`````#P\/#_#P -M\/`/#P\/\/#P\`\/#P\/#P\/#P\/#P\/#P\/#P\/_____P\/#P__________ -M_P````#_____`````/_____P\/#P______#P\/#_____#P\/#_____\/#P\/ -M_____________________P``````````````````````````\/#P\`````#P -M\/#P``````\/#P\`````#P\/#P````#_____`````/_____P\/#P`````/#P -M\/``````\/#P\/#P\/#P\/#P\/#P\/#P\/`/#P\/\/#P\`\/#P_P\/#P____ -M__#P\/#_____#P\/#P`````/#P\/``````\/#P_P\/#P#P\/#_#P\/`/#P\/ -M#P\/#P\/#P\/#P\/#P\/#_____\/#P\/__________\`````_____P````#_ -M____\/#P\/_____P\/#P_____P\/#P______#P\/#___________________ -M__\``````````````````````````/#P\/``````\/#P\``````/#P\/```` -M``\/#P\`````_____P````#_____\/#P\`````#P\/#P`````/#P\/#P\/#P -M\/#P\/#P\/#P\/#P#P\/#_#P\/`/#P\/\/#P\/_____P\/#P_____P\/#P\` -M````#P\/#P`````/#P\/\/#P\`\/#P_P\/#P#P\/#P\/#P\/#P\/#P\/#P\/ -M#P______#P\/#___________`````/____\`````______#P\/#_____\/#P -M\/____\/#P\/_____P\/#P______________________```````````````` -M``````````#P\/#P`````/#P\/``````#P\/#P`````/#P\/`````/____\` -M````______#P\/``````\/#P\`````#P\/#P\/#P\/#P\/#P\/#P\/#P\`\/ -M#P_P\/#P#P\/#_#P\/#_____\/#P\/____\/#P\/``````\/#P\`````#P\/ -M#_#P\/`/#P\/\/#P\`\/#P\/#P\/#P\/#P\/#P\/#P\/_____P\/#P______ -M_____P````#_____`````/_____P\/#P______#P\/#_____#P\/#_____\/ -M#P\/_____________________P``````````````````````````\/#P\``` -M``#P\/#P``````\/#P\`````#P\/#P````#_____`````/_____P\/#P```` -M`/#P\/``````\/#P\/#P\/#P\/#P\/#P\/#P\/`/#P\/\/#P\`\/#P_P\/#P -M______#P\/#_____#P\/#P`````/#P\/``````\/#P_P\/#P#P\/#_#P\/`/ -M#P\/#P\/#P\/#P\/#P\/#P\/#_____\/#P\/__________\`````_____P`` -M``#_____\/#P\/_____P\/#P_____P\/#P______#P\/#_______________ -M______\``````````````````````````/#P\/``````\/#P\``````/#P\/ -M``````\/#P\`````_____P````#_____\/#P\`````#P\/#P`````/#P\/#P -M\/#P\/#P\/#P\/#P\/#P#P\/#_#P\/`/#P\/\/#P\/_____P\/#P_____P\/ -M#P\`````#P\/#P`````/#P\/\/#P\`\/#P_P\/#P#P\/#P\/#P\/#P\/#P\/ -M#P\/#P______#P\/#___________`````/____\`````______#P\/#_____ -M\/#P\/____\/#P\/_____P\/#P______________________```````````` -M``````````````#P\/#P`````/#P\/``````#P\/#P`````/#P\/`````/__ -M__\`````______#P\/``````\/#P\`````#P\/#P\/#P\/#P\/#P\/#P\/#P -M\`\/#P_P\/#P#P\/#_#P\/#_____\/#P\/____\/#P\/``````\/#P\````` -M#P\/#_#P\/`/#P\/\/#P\`\/#P\/#P\/#P\/#P\/#P\/#P\/_____P\/#P__ -M_________P````#_____`````/_____P\/#P______#P\/#_____#P\/#___ -6__\/#P\/_____________________P`` -` -end diff -ruN hobones-0.2/www/hobones.html /root/nes/www/hobones.html --- hobones-0.2/www/hobones.html 2006-09-30 18:21:30.000000000 -0500 +++ /root/nes/www/hobones.html 1969-12-31 18:00:00.000000000 -0600 @@ -1,68 +0,0 @@ - - -
-
-
-
-

SYNOPSIS

-       hobones [-g] [gg codes] [nostart] [rom file/self] [-c <config file>]
-
-
-
-

DESCRIPTION

-       Hobones  is  a  Nintendo emulator. If no arguments are provided hobones
-       will start up in a rom chooser menu. If -g is provided hobones will  do
-       a  game genie befor anything else. If there are gg codes provided (tak-
-       ing the form of +CODE) they will be entered into the game genie screen.
-       if  nostart  is provided after entering game genie codes start will not
-       be pressed.If a rom file is provided hobones will load and  start  that
-       rom.  If  self is provided instead of a rom file hobones will go into a
-       self test. If the -c is provided followed by a file name that file will
-       be  used  as the configuration file as appose to the default configura-
-       tion file.
-
-       default key-binding:
-
-       t         Dump PC trace log
-
-       m         Prepair and execute memory comparison
-
-       up        up (controller 1)
-
-       down      down (controller 1)
-
-       left      left (controller 1)
-
-       right     right (contoller 1)
-
-       return    start (controller 1)
-
-       tab       select (controller 1)
-
-       space     a (controller 1)
-
-       b         b (controller 1)
-
-       f1        Enter debugger
-
-       f2        Toggle fullscreen
-
-       c         Toggle cursor
-
-       f3        Pause/step
-
-       f4        Unpause
-
-       f6        load state
-
-       f7        save state
-
-       s         free scroll with mouse
-
-
-
-Man(1) output converted with -man2html -
- - diff -ruN hobones-0.2/www/index.in /root/nes/www/index.in --- hobones-0.2/www/index.in 2006-09-30 18:21:30.000000000 -0500 +++ /root/nes/www/index.in 1969-12-31 18:00:00.000000000 -0600 @@ -1,70 +0,0 @@ -

-Hey, I'm Thea. People sometimes come up to me and say- Thea! Another fucking Nintendo emulator! Another mutha fuckin' Nintendo emulator?!! Just what the fuck am I going to do with another nintendo emulator? Print out the source and fuck myself with it?

... to witch I usually respond-

FOOL!!!

Writing Nintendo emulators are fun and this is for me and not you, you selfish pig!! At that point ass-kicking usually ensues.

-Here it is: hobones-qqVERSION.tar.gz(sig) older releases. It's for unix/linux. Don't expect it to "work" util version 1.0! (manual) if you have any comments, patches, free beer, whatever (a new krad ascii logo would be great) you may send them to: theaX, erase X and append desilva (so that theadesilva you now have) at g mail dot com. you can get my public PGP key here http://pgp.mit.edu:11371/pks/lookup?op=get&search=0xE62782F5 - -

-

-

-new documents: gg_interaction.txt

-

News: Friday the 30th of September 2006



-Added buggy support of for horizontal mirroring, Touched up configure and did a few other things here and there

-

News: Friday the 9th September 2006



-If you render the ppu with a one frame latency and write cpu changes to the
-ppu to a buffer you'll fix all you timing problems... maybe... working on it

-

News: Friday the 1st September 2006



-Just called a terrorist by the cops today!

-So, I was at the Mall of America today in one of the food-courts with
-my laptop working on my nintendo emulator, as I do quite often, and drinking
-some soda. I picked up my computer and went to the bathroom, on my way back
-I noticed a security gaurd walking away from around where my backpack is. I
-sat down, set my computer back up and another security gaurd comes up to me
-"Hey, I'm blah with Mall security...", "what's up?" I ask. "Oh nothing we
-just like to do a survey here at the mall, get to know some of our customers..."
-and he started asking be a bunch of bull-shit questions- it lasted awhile. couple
-of minutes roll by and I ask,
- "how long is this going to last? What do you want from me?"
- "oh we just need to do a survey..."
- "alright, I'm leaving" ( I started packing up my stuff )
- "we just need to ask you a few questions.."
- "I'm leaving"
- "Oh! we need to finish the survey with some verification"(as I start walking off)
- "Verification of what?"
- "you're name, stuff like that.. if you just have a state ID or something..."
- "You a cop?"
- "No"
- "I'm leaving"
- "We only want to assist you.."
- "I'm I doing anything wrong?"
- "No, we just want to assist you"
- "I'm leaving"
-I walked accross camp-snoopy to the other side of the mall (side my bike was on)
-and this fucking bull-shit kept on going on. I kept asking, "I'm I doing anything
-wrong?" and he kept saying "No, we just need to assist you" I asked him this
-like five times. I got out the the parking-lot (fortunately I didn't park my bike
-on mall property) and he started to to put his arms out blocking me. I kept on
-asking, "did I do anything wrong?" and he kept saying no and I kept on trying
-to get off the fucking property. Three other security-gaurds show up. I few
-minutes later I give up. "Fine, here's my bloody ID," He grabs it and walks off
-so I can't take it back from him. Few minutes roll by, Bloomington cops show up.
-Police officers I'm real respectful of, bull-shit security gaurds not so much.
-Cops ask me a few questions I answer them, I'm now being very polite. "You mind
-if we take a look inside your bag?", "Yeah I mind I don't want people looking
-through my stuff". "uh, well can you show us your computer, you know for
-verificatoin". I pull out my computer show them the bloody program I was working
-on. Cop says "You know, there are a lot of access points at the mall and uh that's
-terrorism, you can... blah fucking blah". Cop actually used the word terrorism,
-I think he was refering to hacking now being conciderd terrorism. "no, I'm
-just working on a program- SEE" pointed out my name in one of the source-files.
-More bull-shit goes by, cop actually asked me "are you a terrorist" I said "no,
-I don't believe I am" - "you don't believe you are?" - "No I'm not a terrorist"
-Cop goes back near is car. Three cops, four security gaurds looking at me some
-time goes by. "Alright, you're free to go" and I jet.
- -I'm fucking going back there again, nobody said I was kicked out, and doing the
-same fucking I was doing before. That was bull-shit.
- -So, biking back to Minneapolis I realize that I left my bag at one of the tables
-while I went to the bathroom, the probably thought that was a fucking bomb. While
-I was waiting in the parking lot goons probably said the word terrorism to the
-cops. - Binary files hobones-0.2/www/logo.gif and /root/nes/www/logo.gif differ diff -ruN hobones-0.2/www/old.html /root/nes/www/old.html --- hobones-0.2/www/old.html 2006-09-30 18:21:30.000000000 -0500 +++ /root/nes/www/old.html 1969-12-31 18:00:00.000000000 -0600 @@ -1,2 +0,0 @@ -
back

HOLY SHIT!

older versions
hobones-0.1.tar.gz(sig)
- Binary files hobones-0.2/www/pay_phone.gif and /root/nes/www/pay_phone.gif differ Binary files hobones-0.2/www/screen1.jpg and /root/nes/www/screen1.jpg differ Binary files hobones-0.2/www/screen2.jpg and /root/nes/www/screen2.jpg differ Binary files hobones-0.2/www/screen3.jpg and /root/nes/www/screen3.jpg differ Binary files hobones-0.2/www/screen4.jpg and /root/nes/www/screen4.jpg differ