This is a Karnak mapper test program for Bandai WonderSwan (Color/Crystal) & Benesse PocketChallenge V2.
Make sure it can be compiled as a ROM.
Load the ROM in an emulator or use the bootfriend (bfb) file to test on your WonderSwan. The program will go through all the tests and then write "Ok". You use the X1-X4 to navigate the menus, A to select an option, B to go back.
I use nasm https://nasm.us/ by running "nasm -f bin -o KarnakTest.bfb KarnakTest.asm".
Use WS X1 & X3 to navigate the menus. A to select/continue failed test, B to go back/skip failed test.
If a test fails it will write out the ADPCM value written and the current index (row) plus the previous value and index (since the lowest bit can not be read out), also the tested PCM value and expected PCM value. Continuing the test will fail all remaining tests since the results are dependant on previous results.
This test tries to access all ADPCM diff table values, though it doesn't test all minus values.
This test make sure that 0x1FF, 0x200, 0x2FF, 0x300, 0x3FF & 0x000 give the right output.
This just test 64k random values.
This test reads 0xD9 twice instead of just once.
This test writes 0xD9 twice instead of just once.
This test disables & enables ADPCM through out the test.
This test tries to read result as fast as possible, not really a test. Conversion can take up to 16 cpu cycles between write and read, but also down to 0 cpu cycles.
Not a test, writes out the result from writing a sequence of the same nybbles.
Not a test, writes out the result from writing a sequence of the same nybbles, resets the ADPCM after changing value.
Bit #7 of IO address 0xD6 turns on/off ADPCM and a timer, setting the bit to 0 resets the ADPCM output to 0x80 (accumulator is 0x100) (and probably odd/even & index). Writing the same value again doesn't affect the ADPCM engine. The lower 7 bits are the timer value ((val + 1) * 2), in 384kHz (cartridge clocks). Reading 0xD6 returns the value written to 0xD6. After enabling ADPCM the output value is still 0x80 (accumulator is 0x100), the index is 0 and the top nybble is decoded first.
ADPCM values (nybbles) are written to IO address 0xD8, decoded PCM samples can then be read from 0xD9. Every other write uses the top/bottom nybble, top first , so you write the same byte twice and read samples after each write. The conversion requires up to 2 Cartridge clocks (16 cpu clocks) between write and read. Reading IO address 0xD8 returns its last written value, no matter if ADPCM is on or off. Writing to 0xD9 doesn't seem to do anything, no matter if ADPCM is on or off. Only writing changes the state of the ADPCM engine, reading does not.
The actual ADPCM algorithm is the same as the NEC upd775x chips (but without any format/headers handling). Though one thing I haven't seen documented (or it is specific to the Karnak chip) is the saturation handling, the accumulator is 10bits with the middle 8bits output except when values are 0x200-0x2FF they are output as 0xFF and when values are 0x300-0x3FF they are output as 0x00, the accumulator is not saturated only the output.
Fredrik Ahlström
Twitter @TheRealFluBBa