Monday, February 29, 2016

Trying out the Targus ACP70USZ

I got my hands on a targus docking station that's USB 3.0 and I thought I'd give it a go with Ubuntu 14.04. Since I installed the drivers from displaylink already, it was detected upon first plug in and works great. What's cool is that it supports dual monitors, both DVI and HDMI. Nice. Now if my Optiplex 760 supported USB 3.0 I would really be flying, but it's only USB 2.0.

I still get a few odd quirks with the displaylink thing, like my Toshiba TV on the HDMI disappeared and I had to fiddle to get it to come back up. Having 4 monitors, 2 on the integrated graphics, and 2 on the targus acp70usz is awesome. I think that multimonitor on linux is like the Holy Grail, especially anything more than dual monitors.


edit: I tried it out with another hdmi device, and it's running fine for about 10 minutes with firefox, then boom the screen goes blank. The system doesn't crash, it just goes blank. Weird.



http://targus.com/form/download.aspx?region=7&sku=ACP70USZ


Sunday, February 28, 2016

This would be awesome on the nose of my car

http://www.scallopimaging.com/products/d7-180-camera/

My most hated move in driving is having to pull out onto a busy street when there are cars parked and you can't see the cross traffic. If you had something like this on the front of your car, you could see both directions by just sticking the nose out.

If you had one on the tail of your car, backing up would be safer too.

Saturday, February 27, 2016

Memory Upgrade weirdness

So I've been suffering with only 2GB on my optiplex 760 so I thought I'd upgrade it. I got 2x2GB corsair and plugged it into the open slots. It's supposed to support 8GB maximum so it should be able to handle this memory just fine.


Only it won't boot, chirp chirp chirp.

I took out 1 stick of the new memory and it booted fine.

So I put the other stick in and now it booted. Weird.

After running a memory diagnostic with memtest86 everything seemed fine. Now to run ubuntu. But I get graphical corruption, due to an "odd" memory size.


http://askubuntu.com/questions/527564/why-am-i-experiencing-visual-corruption-with-intel-x4500-graphics-card-on-14-04


I looked in the bios and it said that I was in "flex mode", not dual channel mode. The memory sticks are in the wrong slot combination for dual channel mode (there's only so many ways to put 4 sticks into 4 slots and I've got it backwards). Rearranging the sticks makes the computer not boot again.

I gave up on it after the umpteenth "unplug/swap memory/plug back in" cycle so now I'm running just the 2x2GB new sticks which is still an improvement.

More memory, less thrashing, tastes great, less filling.


Thursday, February 25, 2016

An ugly hack but it seems to work for wpdata watchpoint reads


So I added this to device_debug::watchpoint_check()


if (type & WATCHPOINT_READ)
global->wpdata = debug_read_memory(space,address,1,false);
//UINT64 debug_read_memory(address_space &space, offs_t address, int size, int apply_translation)



I'm not sure what the values should be to properly pass to debug_read_memory but this seems to work for my purposes.

It's an ugly hack to be sure...


WP 9800,200,r,1,{tracelog " READ addr=%x data=%x \n", wpaddr,wpdata;g}
WP 9800,200,w,1,{tracelog " WRITE addr=%x data=%x \n", wpaddr,wpdata;g}
trace >>mytrace3.txt,0,{tracelog "A=%02X EA=%04X HL=%04X DE=%04X BC=%04X SKIP=%1X 9937=%02X | ",a,ea,hl,de,bc,(psw&0x20)!=0,pb@9937}


gives me this trace:

A=20 EA=0FFE HL=7CAC DE=0000 BC=00C7 SKIP=0 9937=76 | 7AC4: ONIW VV:0F,$18
READ addr=980F data=80
A=20 EA=0FFE HL=7CAC DE=0000 BC=00C7 SKIP=0 9937=76 | 7AC7: RET
A=20 EA=0FFE HL=7CAC DE=0000 BC=00C7 SKIP=0 9937=76 | 7A2B: CALL $7A99
A=20 EA=0FFE HL=7CAC DE=0000 BC=00C7 SKIP=0 9937=76 | 7A99: OFFIW VV:0F,$69
READ addr=980F data=80
A=20 EA=0FFE HL=7CAC DE=0000 BC=00C7 SKIP=1 9937=76 | 7A9C: RET
A=20 EA=0FFE HL=7CAC DE=0000 BC=00C7 SKIP=0 9937=76 | 7A9D: CALL $7B1D
A=20 EA=0FFE HL=7CAC DE=0000 BC=00C7 SKIP=0 9937=76 | 7B1D: LXI HL,$9949
A=20 EA=0FFE HL=9949 DE=0000 BC=00C7 SKIP=0 9937=76 | 7B20: CALT ($00BE)
A=20 EA=0FFE HL=9949 DE=0000 BC=00C7 SKIP=0 9937=76 | 0041: LDEAX (HL)
READ addr=9949 data=38
READ addr=994A data=0
A=20 EA=0038 HL=9949 DE=0000 BC=00C7 SKIP=0 9937=76 | 0043: DCX EA
A=20 EA=0037 HL=9949 DE=0000 BC=00C7 SKIP=0 9937=76 | 0044: STEAX (HL)
WRITE addr=9949 data=37
WRITE addr=994A data=0
A=20 EA=0037 HL=9949 DE=0000 BC=00C7 SKIP=0 9937=76 | 0046: RET
A=20 EA=0037 HL=9949 DE=0000 BC=00C7 SKIP=0 9937=76 | 7B21: BIT 7,VV:00
READ addr=9800 data=5

that looks much better.

Where does wpdata get set in debugcpu

Hmmmm. Perusing emu/debug/debugcpu.cpp we find the elusive wpdata.


struct debugcpu_private
{
...

UINT64 wpdata;
UINT64 wpaddr;
UINT64 tempvar[NUM_TEMP_VARIABLES];

osd_ticks_t last_periodic_update_time;

bool comments_loaded;
};


//-------------------------------------------------
// watchpoint_check - check the watchpoints
// for a given CPU and address space
//-------------------------------------------------

void device_debug::watchpoint_check(address_space &space, int type, offs_t address, UINT64 value_to_write, UINT64 mem_mask)

...

// if we are a write watchpoint, stash the value that will be written
global->wpaddr = address;
if (type & WATCHPOINT_WRITE)
global->wpdata = value_to_write;

...

but there's no corresponding code to modify global->wpdata for WATCHPOINT_READ for just reading values so it doesn't get updated for reads.






Watchpoint data reads don't seem to display the right data for wpdata

I thought I'd add some "memory snooping" to my trace to see what is read and written and upon close inspection the wpdata doesn't seem to display correctly.


WP 9800,200,rw,1,{tracelog " addr=%x data=%x ", wpaddr,wpdata;g}

trace >>mytrace.txt,0,{tracelog "A=%02X EA=%04X HL=%04X DE=%04X BC=%04X SKIP=%1X 9937=%02X | ",a,ea,hl,de,bc,(psw&0x20)!=0,pb@9937}

which generates this:

A=68 EA=0078 HL=2D00 DE=8007 BC=0080 SKIP=0 9937=76 | 221B: CALL $2205
A=68 EA=0078 HL=2D00 DE=8007 BC=0080 SKIP=0 9937=76 | 2205: LBCD $9939
addr=9939 data=1E addr=993A data=1E
A=68 EA=0078 HL=2D00 DE=8007 BC=9A79 SKIP=0 9937=76 | 2209: LXI EA,$9DA9
A=68 EA=9DA9 HL=2D00 DE=8007 BC=9A79 SKIP=0 9937=76 | 220C: DGT EA,BC
A=68 EA=9DA9 HL=2D00 DE=8007 BC=9A79 SKIP=1 9937=76 | 220E: RET
A=68 EA=9DA9 HL=2D00 DE=8007 BC=9A79 SKIP=0 9937=76 | 220F: RETS
A=68 EA=9DA9 HL=2D00 DE=8007 BC=9A79 SKIP=1 9937=76 | 221E: CALT ($0096)
A=68 EA=9DA9 HL=2D00 DE=8007 BC=9A79 SKIP=0 9937=76 | 221F: ANIW VV:03,$7F
addr=9803 data=1E addr=9803 data=8
A=68 EA=9DA9 HL=2D00 DE=8007 BC=9A79 SKIP=0 9937=76 | 2222: LXI HL,$9901
A=68 EA=9DA9 HL=9901 DE=8007 BC=9A79 SKIP=0 9937=76 | 2225: LDEAX (HL)
addr=9901 data=8 addr=9902 data=8
A=68 EA=0000 HL=9901 DE=8007 BC=9A79 SKIP=0 9937=76 | 2227: LDED $993B
addr=993B data=8 addr=993C data=8
A=68 EA=0000 HL=9901 DE=0078 BC=9A79 SKIP=0 9937=76 | 222B: DADD EA,DE
A=68 EA=0078 HL=9901 DE=0078 BC=9A79 SKIP=0 9937=76 | 222D: STEAX (HL)
addr=9901 data=78 addr=9902 data=0
A=68 EA=0078 HL=9901 DE=0078 BC=9A79 SKIP=0 9937=76 | 222F: OFFIW VV:09,$10
addr=9809 data=0
A=68 EA=0078 HL=9901 DE=0078 BC=9A79 SKIP=1 9937=76 | 2232: ORIW VV:11,$10
A=68 EA=0078 HL=9901 DE=0078 BC=9A79 SKIP=0 9937=76 | 2235: OFFIW VV:08,$20
addr=9808 data=0
A=68 EA=0078 HL=9901 DE=0078 BC=9A79 SKIP=1 9937=76 | 2238: ORIW VV:11,$08
A=68 EA=0078 HL=9901 DE=0078 BC=9A79 SKIP=0 9937=76 | 223B: LXI HL,$9808
A=68 EA=0078 HL=9808 DE=0078 BC=9A79 SKIP=0 9937=76 | 223E: LDEAX (HL)

if you look at the 221F: ANIW VV:03,$7F the first one should be the read, 9803 data=1E, AND with $7F then ends up writing 9803 data=8.

That can't be right. It looks like the wpdata doesn't get updated for a read, instead displaying the wpdata for the last value that was written.


LDED $9938 loads DE=0078 but it wpdata says it read the values 8 and 8.

Tuesday, February 23, 2016

click selects all in firefox with ubuntu

I use firefox under ubuntu and windows and one thing that is different is that a single click in the Location (URL) bar will select everything in windows, but the linux version will require a doubleclick.

So a little searching brought up this page:


http://www.askvg.com/hack-single-click-select-all-feature-in-mozilla-firefox-addressbar/


Bringing up about:config searching on "selects", a couple of right click and "toggle"s

and harmony in the universe is restored.





Monday, February 22, 2016

Trying to get displaylink working under ubuntu - yay

Just for fun, I thought I'd see if my displaylink usb adapters would work under ubuntu 14.04. Sadly, after plugging it in it seems to have a lot of flashing led activity and ubuntu acts like it's aware of another monitor. However, the screen never comes up and the mouse gets very slow and stuttery.

I tried upgrading the kernel to the LTS Enablement, but it didn't make any difference.

https://wiki.ubuntu.com/Kernel/LTSEnablementStack

I even tried the drivers from displaylink's website.

http://support.displaylink.com/knowledgebase/articles/684649-how-to-install-displaylink-software-on-ubuntu

I would love for it to work, but it just doesn't.... sigh... At least I can do dual monitors on the Optiplex 760 on the internal graphics with no problem.


edit: IT WORKS!!!! IT'S ALIVE!!!

I just needed to reboot, and after plugging in the displaylink usb, it didn't have the led flicker storm as before. I was able to easily turn on the display in system settings/display and it comes up beautifully. Hooray!

The only strange issue is that the launcher bar won't show up on one of the screens, even if I specify that the launcher bar is on all screens.

Triple monitor goodness AT LAST!

Sunday, February 21, 2016

Driving the cr stepper motor

$C008 is where the action happens for driving the cr (carriage) stepper motor.

so running 'grep "$C008" ap2k_disasm' gives me


~/Downloads/mame$ grep '$C008' ap2k_disasm
000077B6: 70 79 08 C0 MOV ($C008),A
000077CE: 70 79 08 C0 MOV ($C008),A
00007851: 70 69 08 C0 MOV A,($C008)
00007B51: 70 69 08 C0 MOV A,($C008)
00007B5A: 70 79 08 C0 MOV ($C008),A
00007B5F: 70 79 08 C0 MOV ($C008),A

so we'll investigate these addresses.





Here it looks like some setup code around $77B4 writing zeroes to $C008 and then eventually initializing $C008 with $0d.

There's a table base address that gets put into $991D and $991E with LXI HL, $7B76 (load HL with the immediate value $7B76) and SHLD $991d (store HL direct to memory)



This table gets used later where at $7B4D, we LHLD $991D, which gets the base address of the table.

We get the current phase and put it into A with MOV A,($C008)

then LDAX (HL+A) gets the value for the next phase
and MOV ($C008),A writes it into $C008.

But if you look closely at our table at $7B66 and $7B76 the values look strange and the sequence is different.



The sequence runs for $7B66:

D5FBE6C8D

and for the reverse direction at $7B76:

D8C6EBF5D

and if you look at the code in e05a30.cpp, there's a difference: there's a SLA7020M that is actually driving the cr stepper. So we translate to the format that the SLA7020M wants.



So for fun I wanted to see exactly what this function would output: (hope this hilite.me thing works)

#include <stdio.h>
#include <string.h>
typedef int bool;

#define BIT(data,bit) (data&(1<<bit))

static int cr_sla7020m(int data)
{
	bool ina = BIT(data, 0);
	bool inb = BIT(data, 1);
	bool tda = BIT(data, 2);
	bool tdb = BIT(data, 3);
	bool outa0 =  ina && tda;
	bool outa1 = !ina && tda;
	bool outb0 =  inb && tdb;
	bool outb1 = !inb && tdb;
	return (outb1<<3)|(outb0<<2)|(outa1<<1)|(outa0<<0);
}



int hexchar2int(thischar){
if (thischar >= '0' && thischar <= '9') return thischar - '0';
else if (thischar >= 'A' && thischar <= 'F') return thischar - 'A'+10;
else printf("woo hoo");
}


void main (int argc, char *argv[]){

int i;
printf("translating 0 to 15\n");
for (i=0;i<16;i++) printf("%x %x\n",i,cr_sla7020m(i));


char * dostr = "D5FBE6C8D";
printf ("translating %s:\n",dostr);
for (i=0;i<strlen(dostr);i++){printf("%c %d -> %x \n",dostr[i],hexchar2int(dostr[i]),cr_sla7020m(hexchar2int(dostr[i])));}

char * dostr2 = "D8C6EBF5D";
printf ("translating %s:\n",dostr2);
for (i=0;i<strlen(dostr2);i++){printf("%c %d -> %x\n",dostr2[i],hexchar2int(dostr2[i]),cr_sla7020m(hexchar2int(dostr2[i])));}



}





~/Downloads/mame$ cc test_cr_sla_works.c
~/Downloads/mame$ ./a.out
translating 0 to 15
0 0
1 0
2 0
3 0
4 2
5 1
6 2
7 1
8 8
9 8
a 4
b 4
c a
d 9
e 6
f 5
translating D5FBE6C8D:
D 13 -> 9
5 5 -> 1
F 15 -> 5
B 11 -> 4
E 14 -> 6
6 6 -> 2
C 12 -> a
8 8 -> 8
D 13 -> 9
translating D8C6EBF5D:
D 13 -> 9
8 8 -> 8
C 12 -> a
6 6 -> 2
E 14 -> 6
B 11 -> 4
F 15 -> 5
5 5 -> 1
D 13 -> 9

and sure enough, this matches the sequence for the regular "NOT_A_REEL" stepper motor once filtered through the cr_sla7020m function.

Saturday, February 20, 2016

Driving the pf stepper motor in ap2000

I like to skip around when I get stuck... so I happened upon some code that looks like where it drives the pf (paper feed) stepper motor. It's actually a pretty simple fragment.

Fragments like this are so simple and elegant.



It checks the high bit of $9801 and sets the base address of the stepper table in HL.

So one table at $3289 for one direction, and another at $3293 for the other direction. To save a couple of bytes, they overlapped the tables a little bit.



Then we get the current phase at $C007, and look up the next phase with LDAX (HL+A).

We save a copy in B, write the new phase to $C007.

The we look up another phase, wait a couple of cycles and write that phase and return.



so if we're at phase 1, the next will be 5


if we are at 5 the next will be 4



Starting at 1, this will generate the sequence 1 5 4 6 2 A 8 9 1... and backwards for the other direction which matches the sequence for NOT_A_REEL in steppers.cpp.




Friday, February 19, 2016

Ethernet comes up after every other suspend with Ubuntu 14.04

I've got this Optiplex 760 that I'm using with Ubuntu 14.04 and it's running really nicely. Ubuntu is a pretty slick setup and it works well and is very reliable.

But there's one thing that's driving me bats: My ethernet adapter disappears after every other suspend, forcing me to suspend again to bring it back.

I don't see that there's anything esoteric about my hardware, and it works fine once it comes back. Weird.

lspci
00:00.0 Host bridge: Intel Corporation 4 Series Chipset DRAM Controller (rev 03)
00:02.0 VGA compatible controller: Intel Corporation 4 Series Chipset Integrated Graphics Controller (rev 03)
00:02.1 Display controller: Intel Corporation 4 Series Chipset Integrated Graphics Controller (rev 03)
00:03.0 Communication controller: Intel Corporation 4 Series Chipset HECI Controller (rev 03)
00:03.2 IDE interface: Intel Corporation 4 Series Chipset PT IDER Controller (rev 03)
00:03.3 Serial controller: Intel Corporation 4 Series Chipset Serial KT Controller (rev 03)
00:19.0 Ethernet controller: Intel Corporation 82567LM-3 Gigabit Network Connection (rev 02)
00:1a.0 USB controller: Intel Corporation 82801JD/DO (ICH10 Family) USB UHCI Controller #4 (rev 02)
00:1a.1 USB controller: Intel Corporation 82801JD/DO (ICH10 Family) USB UHCI Controller #5 (rev 02)
00:1a.2 USB controller: Intel Corporation 82801JD/DO (ICH10 Family) USB UHCI Controller #6 (rev 02)
00:1a.7 USB controller: Intel Corporation 82801JD/DO (ICH10 Family) USB2 EHCI Controller #2 (rev 02)
00:1b.0 Audio device: Intel Corporation 82801JD/DO (ICH10 Family) HD Audio Controller (rev 02)
00:1c.0 PCI bridge: Intel Corporation 82801JD/DO (ICH10 Family) PCI Express Port 1 (rev 02)
00:1c.1 PCI bridge: Intel Corporation 82801JD/DO (ICH10 Family) PCI Express Port 2 (rev 02)
00:1d.0 USB controller: Intel Corporation 82801JD/DO (ICH10 Family) USB UHCI Controller #1 (rev 02)
00:1d.1 USB controller: Intel Corporation 82801JD/DO (ICH10 Family) USB UHCI Controller #2 (rev 02)
00:1d.2 USB controller: Intel Corporation 82801JD/DO (ICH10 Family) USB UHCI Controller #3 (rev 02)
00:1d.7 USB controller: Intel Corporation 82801JD/DO (ICH10 Family) USB2 EHCI Controller #1 (rev 02)
00:1e.0 PCI bridge: Intel Corporation 82801 PCI Bridge (rev a2)
00:1f.0 ISA bridge: Intel Corporation 82801JD (ICH10D) LPC Interface Controller (rev 02)
00:1f.2 SATA controller: Intel Corporation 82801JD/DO (ICH10 Family) SATA AHCI Controller (rev 02)
00:1f.3 SMBus: Intel Corporation 82801JD/DO (ICH10 Family) SMBus Controller (rev 02)

uname -r
3.19.0-47-generic

History in the "right" order

I love the history command, but I can't handle the reverse sequential order.

So changing this in debugcmd.cpp

/*-------------------------------------------------
    execute_history - execute the history command
-------------------------------------------------*/

static void execute_history(running_machine &machine, int ref, int params, const char *param[])
{

...

           for (int index = (int) count - 1; index >= 0; index--)

//ORIGINAL for (int index = 0; index < (int) count; index++) 

all we have to do is make the index go backwards...
and if you want a segfault, just forget to specify the cpu number. boom goes the dynamite!

history ,10

Thursday, February 18, 2016

Adding a %c to printf

So looking at debugcmd.cpp there's a routine to do printf.


/*-------------------------------------------------
mini_printf - safe printf to a buffer
-------------------------------------------------*/

static int mini_printf(running_machine &machine, char *buffer, const char *format, int params, UINT64 *param)
{


and if I add this just underneath the case 'D'
    case 'c':
    if (params == 0)
    {
     debug_console_printf(machine, "Not enough parameters for format!\n");
     return 0;
    }
    p += sprintf(p, "%c", (UINT32)*param);
    param++;
    params--;
    break;

I can do this:


Perfecting the trace

I discovered how to print memory in the mame debugger.

If you type "help expressions" it gives you a nice rundown.

you can print

b@addr byte
w@addr word
d@addr doubleword
q@addr quadword

and you can prefix with (p=program, d=data, i=io) so pw@9921 will mean the word at program memory space 9921.

So now I've got a pretty good tracelog line:

trace trace0.txt,0,{tracelog "A=%02X EA=%04X HL=%04X DE=%04X BC=%04X SKIP=%1X 9921=%04X | ",a,ea,hl,de,bc,(psw&0x20)!=0,pw@9921}

and it generates:
A=00 EA=00D1 HL=C002 DE=000A BC=0090 SKIP=0 9921=0286  |  0008: EXX     
A=00 EA=00D1 HL=7B76 DE=0000 BC=0200 SKIP=0 9921=0286  |  0009: EXA     
A=CB EA=0286 HL=7B76 DE=0000 BC=0200 SKIP=0 9921=0286  |  000A: JMP     $9817
A=CB EA=0286 HL=7B76 DE=0000 BC=0200 SKIP=0 9921=0286  |  9817: JMP     $7A04
A=CB EA=0286 HL=7B76 DE=0000 BC=0200 SKIP=0 9921=0286  |  7A04: DMOV    EA,ECNT
A=CB EA=0685 HL=7B76 DE=0000 BC=0200 SKIP=0 9921=0286  |  7A06: DMOV    HL,EA
A=CB EA=0685 HL=0685 DE=0000 BC=0200 SKIP=0 9921=0286  |  7A07: SHLD    $9921
A=CB EA=0685 HL=0685 DE=0000 BC=0200 SKIP=0 9921=0685  |  7A0B: CALL    $7A34
A=CB EA=0685 HL=0685 DE=0000 BC=0200 SKIP=0 9921=0685  |  7A34: ONIW    VV:0F,$41
A=CB EA=0685 HL=0685 DE=0000 BC=0200 SKIP=0 9921=0685  |  7A37: RET     

Making IRR visible in the debugger

I thought, why not have the IRR visible in the debugger window. So adding the line

state_add( UPD7810_IRR, "IRR", m_irr).formatstr("%04X");

to upd7810.cpp

and

UPD7810_IRR to this enum in upd7810.h

enum
{
UPD7810_PC=1, UPD7810_SP, UPD7810_PSW,
UPD7810_EA, UPD7810_V, UPD7810_A, UPD7810_VA,
UPD7810_BC, UPD7810_B, UPD7810_C, UPD7810_DE, UPD7810_D, UPD7810_E, UPD7810_HL, UPD7810_H, UPD7810_L,
UPD7810_EA2, UPD7810_V2, UPD7810_A2, UPD7810_VA2,
...
UPD7810_LV0, UPD7810_LV1,
UPD7810_IRR
};


gives me this:



It shows up at the position you add it in the list in upd7810.cpp.

And one side effect of this is that now you can print this from the debugger, and use in tracelog:

print irr
printf "%04X",irr

Wednesday, February 17, 2016

More tables for ESC processing

For processing ESC 0 ($30) to ESC Z ($5A) there's a jump table at $140C.



So basically get the next char, put it into A.

If A is between $30 and $5A then jump to $13c2.



At $13c2, subtract $30 multiply by 2 and use that as the index into the jump table at $140c.



I made a crap bash script to generate the characters from $30 to $5a, directed it to a file and loaded it at $ff00 so I could open up another memory dump window and line it up all neatly for the screenshot.




Howabout that ubuntu high contrast screen theme. Pretty garish, but it makes for a little cleaner screenshot.

ok so let's look at the processing for ESC 0:





so for ESC 0 jump to $1743 which puts 27 into A and stores that in $982C. $982C holds the current line spacing in 1/216 in. 27/216 is 1/8th inch.



for ESC 1 jump to $1745 which puts 21 into A and stores that in $982C. 21/216 = 7/72 inch (why? for 7 bit systems)
for ESC 2 jump to $1747 which puts 36 into A and stores that in $982C. 36/216 = 1/6 inch

ESC 3 is kind of interesting where you set n/216 line spacing, jump to $174A, grab the next character and put that into $982C.


Fun fun fun!



ESC em processing in Action Printer 2000

So now that we've found that $13A3 is the ESC processing routine, let's do some disassembly.



000013A3: 9E                 CALT    ($00BC)  get next char
000013A4: 67 19              NEI     A,$19   is it cut sheet feeder mode
000013A6: CC                 JR      $13B3
000013A7: 77 7F              EQI     A,$7F   equal to 7F delete
000013A9: 27 1F              GTI     A,$1F   not equal to 7F, are we greater than 31
000013AB: 4E 25              JRE     $13D2   so less than or equal to 31 or equal to 7F jump to 13d2
000013AD: 27 2F              GTI     A,$2F    2F=/  decimal 47
000013AF: C3                 JR      $13B3   less than equal to 47 jump to 13b3
000013B0: 27 5A              GTI     A,$5A    greater than Z  5a is 90 = Z
000013B2: CF                 JR      $13C2   so here we are from 48 to 90


Anyway, let's not get confused with too many details. We'll get the next char and compare it to $19. $19 is the ascii code for EM (or end medium). If we are equal to $19 then jump to $13b3.

000013B3: 34 62 14           LXI     HL,$1462
000013B6: 1A                 MOV     B,A
000013B7: 2D                 LDAX    (HL+)
000013B8: 67 00              NEI     A,$00
000013BA: B8                 RET     
000013BB: 48 85              LDEAX   (HL++)
000013BD: 60 FA              EQA     A,B
000013BF: F7                 JR      $13B7
000013C0: 48 28              JEA     

and this code will scan through a table beginning at $1462 in a special format of 3 byte triplets. First byte is the ESC code, and the following two bytes are the address to jump to.



At the end of the table is a 00 at $14b3 which will stop the loop if we don't find our ESC code in the table and will execute the RET at $13ba.



So looking at the first triplet, it happens to be our entry for $19.



and it points to the address $175d.
0000175D: 9E                 CALT    ($00BC)   get next
0000175E: 67 30              NEI     A,$30      
00001760: C7                 JR      $1768       is next equal "0" jump to 1768
00001761: 77 34              EQI     A,$34       is it "4"
00001763: B8                 RET                 not 4 then return
00001764: 15 02 20           ORIW    VV:02,$20   set bit 5 of $9802
00001767: B8                 RET                 done
00001768: 05 02 DF           ANIW    VV:02,$DF   clear bit 5 of $9802
0000176B: B8                 RET                 done

which very neatly implements the ESC em command.



Now to investigate the rest of the table.

Tuesday, February 16, 2016

Processing control characters

So how does ap2000 process control characters like ESC?

I was watching the memory around $9800 and sending ESC M and ESC P would change the memory location $980a.



Typing trackmem enabled memory tracking and the relevant PC for $980a was $1510.



Setting a breakpoint on 1510 and then running history gave me enough info to figure out what was happening.




First it checks $C002. If the high bit is set, then there's data latched in $C003. So read that data and acknowledge by writing to $C004. You're looking at a history so it's in reverse chronological order (sequence goes from the bottom up).



Then we look at the byte, we check if it's less than 32 (nonprinting control characters) with LTI A,$20.

Eventually subtracting 7 and then shifting left (multiplying by 2), we get the offset into a jump table at $13DA.

SUINB A,$07 subract immediate value 7 and skip next if NB no borrow (result is greater than or equal to 0)
RET (skip this)
SLL A multiply by 2 with a shift left

LXI HL, $13DA put 13DA into HL

ADD L,A so now add A to L
ACI H,$00 add immediate with carry to H

LDEAX (HL) load EA indirect with the memory address pointed to by HL

JEA jump to value in EA




We have our table at 13DA:



and at address $1402 ($13DA + ($1b - 7) * 2) is the pointer to the routine for processing ESC, $13A3.



It's interesting to see in the table that with control characters that are ignored, like $1C, the jump address is $14b6 (shows up in the table as B6 14 because low byte is first) which points to just a single RET instruction.

Sunday, February 14, 2016

To save tires drive under 35

It's interesting to look at the rationing that took place during world war 2. Is this trip really necessary?




http://www.ameshistory.org/exhibits/events/rationing.htm

Xfinity DC50Xu keeps going nonresponsive

So I leave the Pace DC50Xu DTA overnight, and in the morning it won't respond to the remote.

I figured out that if I hit the red power button in the upper left and change the channel while the OSD is on, that it becomes responsive again.

That is the worst designed piece of equipment ever...

Xfinity rolled out an online TV guide function and it's been horribly irritating to me. Now the keypad has a different meaning than 123456789. While the OSD is active, 2 4 6 8 are up left right and down, with 5 being OK. The most frustrating thing is that I want to type another number immediately but it thinks I want to move the cursor instead.

If only the INFO button would take you out of the OSD. It'd be nice to use the INFO button as an "escape key".

The channel LAST button will take you out of the OSD, but it tells you what the current channel is and leaves the OSD open for a few more seconds.

The 5 second OSD delay just destroys the user's "illusion of control". Looking closer in the setup menu, you can disable the "Smart Bar" OSD or set the delay to 5, 7 or 10 seconds.

Observing the interrupt flags

In the mame debugger I can see most of the cpu registers, but IRR (interrupt flags) isn't visible. However, it does show up as uPD7810/:centronics:ap2000:maincpu/0/m_irr in a memory view window.

If I'm careful I can just see it set the INTAD (INTFAD = 0x0100) flag before it clears it with SKIT FAD.

I set a breakpoint at 10F with "bpset 10F" and then step about 55 instructions or so with "s 55".







Watching the memory change

It's neat to open up memory windows in the mame debugger and see things changing in real time.

echo 'Memory 8000-9000 input buffer' > lp0
echo 'also see input at $9A79' > lp0

Saturday, February 13, 2016

Trying to echo null characters

I was trying to send some null characters \x00 to the ap2000 using echo, but it didn't work.

The idea here was to generate a small amount of graphics with ESC * 0 (single density graphics) specifying 4 columns of graphics.

The escape codes would be ESC * 0 \x04 \x00 followed by 4 bytes of dummy graphics \xFF \x00 \xFF \x00.

I could not figure out what was wrong...until I realized that hex 00 would be interpreted as "nothing".

Why? C strings are terminated when there's a \x00 character.

bash escape codes with $'\x00' disappear:

echo $'\e*0\x01\x001234' | hexdump -C
00000000 1b 2a 30 01 0a |.*0..|
00000005

but if I use echo -e all of the characters come through.

echo -e '\e*0\x01\x001234' | hexdump -C
00000000 1b 2a 30 01 00 31 32 33 34 0a |.*0..1234.|
0000000a

I also used printf and it was happy to emit \x00.

printf '\x1b*0\x04\x00\xff\x00\xff\x00' > lp0

printf '\x1bx0TEST\x1bx1TEST\x1bx0TEST\x1bx1TEST\n' > lp0

Strings strings strings


strings -t x roms/ap2k.ic3c | less

(the -t x gives you the hexadecimal offset in the file)

38b PS2414
403 Data Dump Mode
553 NLQ H /Adjust=
565 Draft H /Adjust=
578 NLQ L /Adjust=
58a Draft L /Adjust=

9d5 Character Pitch
9e5 12 CPI
9ec 10 CPI
9f9 Shape of Zero
a07 0 (Slashed)
a13 0 (Unslashed)
...
bbc Valid
bc2 Depend on I/F
bd6 Draft Print Speed
be8 Normal
bef High
e0e This is the first line.
e26 This is line


And so for a given string, let's see if we can find the offset in the disassembly:


38b PS2414

cat ap2k_disasm | grep '038B'
00000353: 34 8B 03 LXI HL,$038B

403 Data Dump Mode

cat ap2k_disasm | grep '0403'
00000398: 34 03 04 LXI HL,$0403
0000104E: 34 03 04 LXI HL,$0403

553 NLQ H /Adjust=
565 Draft H /Adjust=

cat ap2k_disasm | grep '0553'
000004F2: 34 53 05 LXI HL,$0553
cat ap2k_disasm | grep '0565'
000004EF: 34 65 05 LXI HL,$0565

e0e This is the first line.
e26 This is line

cat ap2k_disasm | grep '0E0E'
00000DC7: 34 0E 0E LXI HL,$0E0E
cat ap2k_disasm | grep '0E26'
00000DF0: 34 26 0E LXI HL,$0E26



Friday, February 12, 2016

I just want a simple calendar, man

I liked the way Word 97 and Publisher 97 would make you very simple black and white monthly calendars. So I'm using Word 2013 and it wants to do these fancy looking calendars but I just want it plain jane.

I spent a lot of time trying to eliminate the background picture embedded in the headers and footers, extraneous stuff like "Notes:" and I even ended up with "type text here" on the printout.

It's not really a step forward...sometimes simple is better.

Grep is your friend

I like to use grep to find strings in the disassembly.

./unidasm roms/ap2k.ic3c -arch upd7810 >ap2k_disasm

cat ap2k_disasm | grep '9911'
00002023: 34 11 99 LXI HL,$9911
000020AC: 70 2F 11 99 LDED $9911
000020B3: 70 2E 11 99 SDED $9911
000020DE: 70 2F 11 99 LDED $9911
000020E4: 70 2E 11 99 SDED $9911

cat ap2k_disasm | grep 'C004'
00000125: 70 79 04 C0 MOV ($C004),A
00000C3F: 70 79 04 C0 MOV ($C004),A
00000FB3: 34 04 C0 LXI HL,$C004
0000109B: 34 04 C0 LXI HL,$C004
000010A1: 34 04 C0 LXI HL,$C004
00002FBD: 70 69 04 C0 MOV A,($C004)
00002FC3: 70 79 04 C0 MOV ($C004),A
00002FFC: 70 69 04 C0 MOV A,($C004)
00003002: 70 79 04 C0 MOV ($C004),A

Fun fun fun...I'll figure out how this code works eventually.

Thursday, February 11, 2016

Mame debugger is cool

I've been trying to figure out the upd7810 processor and the ap2000 driver with the aid of the mame debugger. I would *never* be able to do this without it. It's got so many neat features.

I must have about 10 different windows open, multiple disassemblies, multiple memory windows, watchpoints and breakpoints. It's really slick.

Perusing the debugcmd.cpp file gives a bunch of useful commands like:

history (interestingly, the history is printed out most recent statement first, oldest statement last)
trackmem
trackpc

I particularly like the ability to right click on a memory location and see what the PC was when it was last written.

Great stuff and it makes it fun to watch the cpu work.

Wednesday, February 10, 2016

Those little eureka moments

I live for the little eureka moments when I figure stuff out.

Yesterday I wondered where Mame builds the tools like unidasm. So perusing the makefile all I had to do was uncomment the hash # TOOLS=1 and do a make and bob's your uncle.

Just today I discovered that rolling the mousewheel over the sidebar taskbar icons in Ubuntu would cycle through the windows for that application.

Not huge discoveries but it makes me happy.

Tuesday, February 9, 2016

Not enough USB bandwidth for two usb webcams

Just for fun I thought I'd try to get 2 webcams running at the same time with Ubuntu. After figuring out how to launch VLC twice, I asked it to play /dev/video0 in one window, and /dev/video1 in the other. One at a time worked well, but I couldn't get both to work simultaneously.

Then it hit me: there isn't enough usb bandwidth for both. So ratcheting the resolution down to 320x240 for each one, it works!

Tuesday, February 2, 2016

Skipping along with upd7810

I'm fascinated by the ap2000 driver in mess and was trying to wrap my head around the "skippy" nature of the cpu. If the skip flag is set, skip the current instruction.

So let's trace in the mess debugger.

trace mytrace.tr,0,{tracelog "PSW_SKIP= %02X ",psw&0x20}

creates this trace log:

PSW_SKIP= 00 2C4F: CALT ($00B2)
PSW_SKIP= 00 0050: CALB
PSW_SKIP= 00 0FE4: CALL $0FBF
PSW_SKIP= 00 0FBF: MOV A,PA
PSW_SKIP= 00 0FC1: MOV B,A
PSW_SKIP= 00 0FC2: MOV A,PA
PSW_SKIP= 00 0FC4: EQA A,B
PSW_SKIP= 20 0FC6: JR $0FBF
PSW_SKIP= 00 0FC7: RET
PSW_SKIP= 00 0FE7: ONI A,$40
PSW_SKIP= 20 0FE9: RETS
PSW_SKIP= 00 0FEA: RET
PSW_SKIP= 00 0052: RETS
PSW_SKIP= 20 2C50: CALL $2C79
PSW_SKIP= 00 2C53: LXI BC,$0FEB
PSW_SKIP= 00 2C56: CALT ($00B2)
PSW_SKIP= 00 0050: CALB
PSW_SKIP= 00 0FEB: CALL $0FBF

(loops for 6 instructions)


Ah. Much better.