Wednesday, January 16, 2013

Reverse engendering of 680x0 assembly code.

Trying to make sense of it all, IRA the disassembler has been really help full to gives some clues; by providing EQU constants for hardware registers, and some other stuff I don't know what is.


It is worth to point out that any access to hardware registers are illegal under AmigaOS4.1, unless your running on old hardware, so we need to replace it whit system friendly code, so we need to look for any references to this constants, that I have marked, and replace the code.


Next thing that is a issue is to understand what the code does, there are some clues, see the lines that starts whit JSR, JSR is short for Jump To Sub Routine. In front of A6 (address register 6), you have a negative value, this is a offset value we call LVO, A6 is loaded whit library base address, we just need to find what library and compare the LVO values to that library offsets, LVO number are not unique to one library they can be the same for number of libraries, so we can't just auto replace the values whit constants.

Another thing that will help making it possible to understand some thing is to look at bottom of the code, this where you find data, like strings.


DC and DS is defines data space, DC is for values you enter, while DS just reserves chunk of space, it is the DC that we are most interested, in front of DC there is label it represent a reference to the data, the label has been generated by IRA disassembler and not human understandable, we need to replace the label name whit some thing we understand, so we replace LAB_0F71 whit LAB_STERO_LEVEL, and LAB_0F6B whit LAB_VOLUME_BOOST, we do that for all readable strings, we most be careful to replace every reference of LAB_0F6B and LAB_0F71.

Saturday, January 12, 2013

Paula sound, so where does that 14bit audio come from?

So where does that 14bit stereo sound come from? You might have wondered, well after reading the hardware reference manual, it explains that 4 audio channels can be combined in to two.

In this mode, one of channels controls the volume (a value from 0 to 63) 6bits, and wave from is (127 to -127) 8bit, so if you add that up 6+8 = 14bit.

This not a hack, that's a urban myth, it was designed to be like this. Its properly more complicated to calculate wave form and volume, and also it does not take advantage of all bits in the audio channels, plus it does need a bit more CPU if I'm not mistaken.

Its a shame they did not provided a proper 16bit D/A converter instead, anyway the sound was not that bad compared some early sound blaster sound cards that sounded a bit sour.


I think this graph illustrates the dilemma, where audio quality is better at lower amplitude, then on higher, as as the amplitude increases, because the 8bits are more compressed at lower volume. So you do not get popper 14bit, where the bits are evenly spread out, what you get if you made a sinus or a sawtooth, you see that top and bottom of sinus are more pixelated then in the center of sinus.

I have also played whit Paula whit some help, few small errors, and this codes players a beep. I have not really found out about interrupts, the DMA is supposed to trigger a interrupt when sound was played, so you fill the buffer whit new sound, but I can't find any interrupt vector to configure in the hardware reference manual.


EXECBASE EQU 4

OldOpenLibrary EQU -$0198
WriteChars EQU -$03AE
CloseLibrary EQU -$019E
Delay EQU -198

ALLOCMEM    EQU -198
FREEMEM        EQU    -210

CUSTOM        EQU    $DFF000
AUD0LCH        EQU    $0A0
AUD0LCL        EQU $0A2
AUD0LEN        EQU $0A4
AUD0VOL        EQU    $0A8
AUD0PER        EQU    $0A6
DMACON        EQU $096

    SECTION MAIN,CODE

MAIN:
        LEA DOS(pc),A1
        MOVE.l #0,D0
        MOVE.l EXECBASE,a6
        jsr     OldOpenLibrary(a6)
        move.l  d0,DOSBASE
        beq.s   .Out

        move.l  #msg_start,d1
        moveq  #9,d2
        JSR .Write

        ; Alloc Sound wave
        MOVE.l #100,D0    ; size
        MOVE.l #2,D1        ; chip mem
        MOVE.l EXECBASE,a6
        JSR ALLOCMEM(a6)
        MOVE.l d0,SINDATA
        BEQ.s    .NOMEM
   
        ; Setup sound wave
        MOVE.L SINDATA,a1
        MOVE.b 0,0(a1)
        MOVE.b 90,1(a1)
        MOVE.b 127,2(a1)
        MOVE.b 90,3(a1)
        MOVE.b 0,4(a1)
        MOVE.b -90,5(a1)
        MOVE.b -127,6(a1)
        MOVE.b -90,7(a1)

        ; Play sound
        LEA.l CUSTOM,a0
        MOVE.l SINDATA,AUD0LCH(a0)  ; sound wave to play
        MOVE.W #4,AUD0LEN(a0) ; length of sound wave
        MOVE.W #64,AUD0VOL(a0) ; sound volume
        MOVE.W #447,AUD0PER(a0) ; set audio period
        ; enable (bit 15) dma (bit 9), audio channel 0 (bit 0)
        MOVE.W #$8201,DMACON(a0)

        ; Wait for sound to be played
        move.l DOSBASE,A6
        move.l #40,D1
        JSR Delay(A6)

        LEA.l CUSTOM,a0
        MOVE.W #1,AUD0VOL(a0) ; sound volume
        MOVE.W #0,AUD0LEN(a0) ; length of sound wave
        MOVE.W #220,AUD0PER(a0) ; set audio period
        MOVE.W #$0001,DMACON(a0)

        move.l  #msg_step,d1
        moveq  #7,d2
        JSR .Write

        ; Wait for sound to be played
        move.l DOSBASE,A6
        move.l #20,D1
        JSR Delay(A6)

        ; Free sound wave
        MOVE.l #100,D0
        MOVE.l SINDATA,a1
        MOVE.l EXECBASE,a6
        JSR FREEMEM(a6)

        move.l  #msg_ok,d1
        moveq  #7,d2
        JSR .Write
        JMP .Out      
.NOMEM:
        move.l  #msg_nomem,d1
        moveq  #13,d2
        JSR .Write
        JMP .Out      
.Write:
        move.l DOSBASE,A6
        jsr     WriteChars(a6)
        RTS
.Out:
        move.l  DOSBASE,a1
        move.l  EXECBASE,a6
        jsr     CloseLibrary(a6)
        RTS
DOS:
        dc.b    "dos.library",0
DOSBASE:
        dc.l 0
SINDATA:
        DC.L    0
msg_start:
        dc.b   "START!!!",$A,0
msg_step
        dc.b    "STEP!!",$A,0
msg_ok:
        dc.b    "OK!!!!",$A,0
msg_nomem:
        dc.b    "AllocMem failed, no memory!",$A,0

Saturday, December 29, 2012

680x0 development enviroment on AmigaOS4.1?

Yesterday I was wondering was, is it possible to setup a 680x0 development enviroment on AmigaOS4.1, whit out depending on UAE.

And the answer is yes.

Well first I tried AsmPRO, while program seams to work, it does give me some DSI crashes some times when I start the program, it did compile my code, but when pressing “j” to run it crashed.

So AsmPRO does not work under AmigaOS4.1, I did not like the integrated text/source code editor anyway.

Next I looked at the vbcc package it has a 680x0 compiler, but it can only produce .o files, so I need vlink once found it, I wrote a tiny AmigaDOS script.


Saved it and added script flag to the file using the protect command in AmgaDOS.
Next I found a "hello world" example using google.



Compiled it, and it worked.

So what is this all about, way do I wont to write 680x0 assembler?

Well the answer to that question is, a question I have been asking my self, what if I disassembled some of old programs that don't work anymore, will I be able fix this programs up?

I have limited experience whit assembler, I did make a 3d routine in inline Assembler in BlitzBasic2 and it worked, (I did it that way because did not have the right books, when I was learning assembler.)

Saturday, December 15, 2012

Santa is working super hard to make it to christmas.


Bringing the Christmas felling to the Amiga desktop, Excalibur now running on my X1000, I might write some words about it.

It has taken allot more time then expected many of changes has resulted in having to fix new bugs, and many of previews bugs had to be fixed.

The list of changes is not short, its one of the biggest updates so it going to be called version 1.2.

* Button radius option in prefs
* Added border options for toolbar and menu 3D and XEN.
* Corrected many errors in calculations for menu.
* Background color for menu and toolbar are now individual.
* Improved rendering routines for toolbar icons
* Create_script() bug some files did not open when path was a volume.
* Fixed screen open/close notify bug. 
* Added XEN style to screens, clock and border.
* Set_screen_to_front() triggered a unnecessary refresh, bug fixed.
* Now prgram waits for singals like any normal programs does.
* Clock is now running as a subtask, and only renders when time updates,
  less CPU usage!.
* New about window is reaction, and the about event handler is running
  as a own task (bb2 legacy free.)
* CHIPMEM,FASTMEM,GFXMEM and so on, upgraded to unsigned long long int (uint64),
  should salve the negative memory problem.
* Mouse_over_clock() starts clock prefs app when clock is disabled, bug fixed.
* None initialized values in menu, can result in a crash, bug fixed.
* rendering bug when dropping icons on startbar, fixed.
* check_ext() only worked on .info files, bug fixed.
* disk.info was listed on volumes, bug fixed.
* When SYS:WBStartup is missing its created by the install script.
* Menu div can now be a transparent png image.
* menu div image can now be scaled. 
 

Wednesday, November 28, 2012

Multi treading in Excalibur

So what was done, the old event loop looked like this, the problem whit this code was that, the program did not wait for signals, it was busy looping due the clock that needed to be redrawn every 1secund, but I was not able to slow it down because that, will cause the events to be not read at correct time, there was a small delay of 0.1 sec in the loop.


 

After rewriting the code, the main event loop, waits for events before checking, it does not do anything unless something happens.

Membar is only triggered every 2 seconds, because we don't need instant update of memory, nor do we want that.

the Clock loop is only updated every 1 seconds.

  
Well so now Excalibur is Multicore ready, allowing Excalibur to wait on many cores at once.

Of cause it more to it then what I written her, most important is the Mutx protection.


Saturday, November 24, 2012

Dividing the code.

As it is written in the readme Excalibur was a a BlitzBasic program, typically for basic programs is that every thing is written in as one large source file, (not true for all modern basic programs).

One thing I have done for every version of Excalibur is to split the code up, I will explain it.

A typical basic program looks like this, you have every thing mixed, its complicated to find what your looking for, when every thing is mixed, and also in C there is ways you can speed up complication time by dividing the code in separate .c files.


When the content is split up it looks some thing like this:


As you can see now is easy, now is easy to find what your looking for, but when code is split up the compiler won't find what in the other files until linking. The source won't compile or the compiler will complain about incorrect declarations, to solve this problems you most create .h file that defines the functions whit in the *.c files.

This all well, blitz basic does not know about threads or task, every thing run from start to end, whit nothing running parallel, this is bad, in Excalibur you have a clock it has to update for every second, a good program should only do stuff when something happens, the program should wake up when its signaled to do something, then event routine should check what messages has been revised and act on this, well because clock interfered whit this it was no use checking for signals, and so main loop was running and wasting CPU cycles when noting new head happened, due to being single threaded.

I worked on this and by moving the code out of main application, I have made it easy to handle it all whit the clock.c file, I added a clock_proc function that should be spawned as own sub task, so that all rendering of clock was done in parallel whit main program, whit out interfering whit event loop in the main application, some extra work was need to prevent the code from rendering when window was closed, and allow it render when window was reopened, by using Mutex I fixed it so that variable whit clock.c was set on or off to allow rendering, the main event loop in clock.c was also mutex protected to so that only when variable was not being changed, it was allowed to render.

So way did I go trow all this trouble for just a CPU parentage? Well because Excalibur is a start menu, and its always there, you might need that percentage for your video player so it does not skip frames, or your music, or maybe you playing a game, I don't know but if every one wasted CPU cycles then there wont by any left for your applications.

Saturday, November 3, 2012

Its all about the details

Well some work on my hobby, its all about the details.

I'm going back to basic's I know many people like it simple, and are not so interested in all PNG images fancy bling bling, so going back to old colors and styles.

I was looking at workbench prefs and style called XEN, this where you have depth border and you have normal 3d border inside, to make it look like button or fame is not above but inside.

I liked this effect, and so I looked at ways to added it to borders.


Also some work on the selector box has been done, it was not correctly rendered, one pixel wrong there not rendered correct when scroll bar was inside the menu.

I have also worked on the prefs, I have rearrange, the visual effects, so they are nicely grouped by menu and toolbar.
I have also fund a few bugs, they are gone.