S90 Porting Thread - page 5 - DryOS Development - CHDK Forum

S90 Porting Thread

  • 397 Replies
  • 116880 Views
Re: S90 Porting Thread
« Reply #40 on: 01 / February / 2010, 10:31:33 »
Advertisements
Unfortunately, the porting process has stalled, waiting for someone to come along who wants to and is able to actually disassemble the firmware, find the entry points to functions, figure out what they do, and write C code to call them from CHDK.   

Re: S90 Porting Thread
« Reply #41 on: 02 / February / 2010, 19:11:17 »
Hello, just started following the process described here http://chdk.wikia.com/wiki/Adding_support_for_a_new_camera and also had a look at the G11 CHDK port  thread.

I managed to get to the point where the compiler is not complaining about any unreferenced symbols. The automatically generated stubs_entry.S file very much reminds me of G11's stubs_entry file. As you can see below the same stubs were found with the same probability:


S90's stubs_entry.S file
Code: [Select]
// !!! THIS FILE IS GENERATED. DO NOT EDIT. !!!
#include "stubs_asm.h"

NSTUB(AllocateMemory, 0xffa9d168)
NSTUB(AllocateUncacheableMemory, 0xff838dcc)
NSTUB(Close, 0xff835414)
NSTUB(CreateTask, 0xff81e5b4)
NSTUB(DeleteFile_Fut, 0xff834da0)
// ERROR: EnterToCompensationEVF is not found!
NSTUB(ExecuteEventProcedure, 0xff888d74)
// ERROR: ExitFromCompensationEVF is not found!
// Best match: 57%
NSTUB(ExitTask, 0xff81e844)
NSTUB(Fclose_Fut, 0xff834f1c)
NSTUB(Feof_Fut, 0xff835108)
NSTUB(Fflush_Fut, 0xff835144)
NSTUB(Fgets_Fut, 0xff835070)
NSTUB(Fopen_Fut, 0xff834edc)
NSTUB(Fread_Fut, 0xff834fc8)
NSTUB(FreeMemory, 0xffa9d160)
// Best match: 91%
NSTUB(FreeUncacheableMemory, 0xff838e0c)
NSTUB(Fseek_Fut, 0xff8350bc)
NSTUB(Fwrite_Fut, 0xff83501c)
// Best match: 52%
NSTUB(GetBatteryTemperature, 0xff8615f0)
// Best match: 52%
NSTUB(GetCCDTemperature, 0xff86157c)
// Best match: 85%
NSTUB(GetCurrentAvValue, 0xff95a354)
NSTUB(GetDrive_ClusterSize, 0xff86e380)
NSTUB(GetDrive_FreeClusters, 0xff86e3e0)
NSTUB(GetDrive_TotalClusters, 0xff86e3b4)
// Best match: 64%
NSTUB(GetFocusLensSubjectDistance, 0xff958928)
NSTUB(GetFocusLensSubjectDistanceFromLens, 0xff958d70)
// Best match: 96%
NSTUB(GetOpticalTemperature, 0xff861664)
// Best match: 66%
NSTUB(GetParameterData, 0xff994a7c)
// Best match: 72%
NSTUB(GetPropertyCase, 0xff88ca64)
// Best match: 96%
NSTUB(GetSystemTime, 0xffa9d1c0)
// Best match: 74%
NSTUB(GetZoomLensCurrentPoint, 0xff95d9ec)
NSTUB(GetZoomLensCurrentPosition, 0xffa90e0c)
// Best match: 64%
NSTUB(IsStrobeChargeCompleted, 0xff8d8710)
NSTUB(LocalTime, 0xff886670)
// Best match: 93%
NSTUB(LockMainPower, 0xff89467c)
// ERROR: Lseek is not found!
// Best match: 92%
NSTUB(MakeDirectory_Fut, 0xff834e14)
// Best match: 57%
NSTUB(MoveFocusLensToDistance, 0xffafbcf0)
// Best match: 58%
NSTUB(MoveZoomLensWithPoint, 0xffa9b1a8)
// Best match: 62%
NSTUB(NewTaskShell, 0xff88c510)
NSTUB(Open, 0xff8353bc)
// ERROR: PT_PlaySound is not found!
// Best match: 86%
NSTUB(PostLogicalEventForNotPowerType, 0xff8924a8)
// Best match: 92%
NSTUB(PostLogicalEventToUI, 0xff8924f4)
NSTUB(Read, 0xff81ab78)
NSTUB(ReadFastDir, 0xffa7d748)
// ERROR: RefreshPhysicalScreen is not found!
// ERROR: Remove is not found!
// Best match: 53%
NSTUB(RenameFile_Fut, 0xff834ed8)
// ALT: NSTUB(RenameFile_Fut, 0xffa69a44) // 8/7
// ALT: NSTUB(RenameFile_Fut, 0xffa69a94) // 8/7
// Best match: 93%
NSTUB(SetAutoShutdownTime, 0xff8946f0)
// Best match: 81%
NSTUB(SetCurrentCaptureModeType, 0xff89b7b4)
// Best match: 55%
NSTUB(SetFileTimeStamp, 0xff9496e8)
// Best match: 64%
NSTUB(SetLogicalEventActive, 0xff8943cc)
// Best match: 68%
NSTUB(SetParameterData, 0xff994958)
// Best match: 89%
NSTUB(SetPropertyCase, 0xff88c960)
// Best match: 92%
NSTUB(SleepTask, 0xff838a50)
// Best match: 60%
NSTUB(TakeSemaphore, 0xff838718)
// ERROR: TurnOffBackLight is not found!
// ERROR: TurnOnBackLight is not found!
// ERROR: UIFS_WriteFirmInfoToFile is not found!
// Best match: 93%
NSTUB(UnlockMainPower, 0xff8945d0)
NSTUB(UpdateMBROnFlash, 0xff813f74)
NSTUB(VbattGet, 0xff831e04)
NSTUB(Write, 0xff8354a4)
NSTUB(_log, 0xffb365f8)
NSTUB(_log10, 0xffb35284)
NSTUB(_pow, 0xffb353f4)
NSTUB(_sqrt, 0xffb3819c)
NSTUB(close, 0xff81a990)
NSTUB(closedir, 0xffa7d5d0)
// Best match: 71%
NSTUB(closefastdir, 0xffa7d8e4)
// Best match: 95%
NSTUB(free, 0xff814138)
// Best match: 86%
NSTUB(kbd_p1_f, 0xff833630)
// Best match: 86%
NSTUB(kbd_p1_f_cont, 0xff83363c)
NSTUB(kbd_p2_f, 0xff832ed8)
// ERROR: kbd_pwr_off is not found!
// ERROR: kbd_pwr_on is not found!
NSTUB(kbd_read_keys, 0xff8335b4)
// Best match: 81%
NSTUB(kbd_read_keys_r2, 0xff85db5c)
NSTUB(lseek, 0xff835530)
NSTUB(malloc, 0xff8140dc)
NSTUB(memcmp, 0xff8203e8)
NSTUB(memcpy, 0xff83e43c)
NSTUB(memset, 0xffa0c7f8)
NSTUB(mkdir, 0xff835888)
NSTUB(mktime_ext, 0xff8ac304)
NSTUB(open, 0xff81a8e0)
NSTUB(opendir, 0xffa7d614)
// ERROR: openfastdir is not found!
NSTUB(qsort, 0xffaec3d8)
// Best match: 95%
NSTUB(rand, 0xff8204f0)
NSTUB(read, 0xff81ab78)
// ERROR: readfastdir is not found!
// ERROR: rename is not found!
// Best match: 95%
NSTUB(srand, 0xff8204e4)
NSTUB(stat, 0xff83556c)
// ALT: NSTUB(stat, 0xff86b7c4) // 30/0
// Best match: 61%
NSTUB(strcat, 0xff813f38)
// Best match: 56%
NSTUB(strchr, 0xff813fc0)
NSTUB(strcmp, 0xff8203a4)
NSTUB(strcpy, 0xff82038c)
NSTUB(strftime, 0xff8abd0c)
NSTUB(strlen, 0xff81400c)
NSTUB(strncmp, 0xff813f74)
// Best match: 73%
NSTUB(strncpy, 0xff813f38)
// Best match: 71%
NSTUB(strrchr, 0xff83e414)
// ALT: NSTUB(strrchr, 0xff8abad4) // 18/8
// Best match: 96%
NSTUB(strtol, 0xff83e71c)
NSTUB(strtolx, 0xff83e520)
// Best match: 86%
NSTUB(time, 0xff886be8)
NSTUB(vsprintf, 0xff820350)
NSTUB(write, 0xff81abd8)

And the same stubs are missing so I added them to stubs_entry_2.S. Hope that someone with ARM ASM knowledge can fill in the gaps:

S90's stubs_entry_2.S file
Code: [Select]
#include "stubs_asm.h"

// Not found by sigfind
NHSTUB(EnterToCompensationEVF, 0x12345678)
NHSTUB(ExitFromCompensationEVF, 0x12345678)
NHSTUB(Lseek, 0xff835530) // same as lseek
NHSTUB(PT_PlaySound, 0x12345678)
NHSTUB(RefreshPhysicalScreen, 0x12345678)
NHSTUB(Remove, 0x12345678)
NHSTUB(TurnOffBackLight, 0x12345678)
NHSTUB(TurnOnBackLight, 0x12345678)
NHSTUB(UIFS_WriteFirmInfoToFile, 0x12345678)
NHSTUB(kbd_pwr_off, 0x12345678)
NHSTUB(kbd_pwr_on, 0x12345678)
NHSTUB(openfastdir, 0x12345678)
NHSTUB(readfastdir, 0x12345678)
NHSTUB(rename, 0x12345678)

// defined elsewhere
NHSTUB(SetScriptMode, 0x12345678)
NHSTUB(apex2us, 0x12345678)
NHSTUB(MakeAFScan, 0x12345678)
NHSTUB(ExpCtrlTool_StartContiAE, 0x12345678)
NHSTUB(WriteSDCard, 0x12345678)
NHSTUB(UnlockAF, 0x12345678)
NHSTUB(DoAFLock, 0x12345678)
NHSTUB(GetKbdState, 0x12345678)
NHSTUB(UnsetZoomForMovie, 0x12345678)
NHSTUB(LEDDrive, 0x12345678)
NHSTUB(ScreenLock, 0x12345678)
NHSTUB(ScreenUnlock, 0x12345678)


// nullsubs (as defined in G11's stubs file)
NHSTUB(rewinddirkbd_pwr_on, 0x12345678)  // nullsub
NHSTUB(Unmount_FileSystem, 0x12345678)  // nullsub
NHSTUB(Mount_FileSystem, 0x12345678)  // nullsub
NHSTUB(SetZoomActuatorSpeedPercent, 0x12345678)  // nullsub

So I assume that someone with C and ASM knowledge could make a successful S90 CHDK port based on the G11 project.
« Last Edit: 03 / February / 2010, 06:30:52 by battika »

Re: S90 Porting Thread
« Reply #42 on: 03 / February / 2010, 02:59:32 »
Good news, thanks drewm1980 and battika.

I don't care that much about HD Video, but using CHDK for the S90 would be awesome.

Re: S90 Porting Thread
« Reply #43 on: 03 / February / 2010, 05:08:09 »
Yeah, I guess we should forget about HD Video on S90/G11 due to hardware limitation.

Anyways, here is my makefile.inc, not sure if my MEMISOSTART value is correct given I have never seen ARM ASM code before. My test project compiles Okay, all I need is a card reader so that I can transfer DISKBOOT.BIN to my SD card  :)

S90's makefile.inc
Code: [Select]
#31E1
PLATFORMID=12769

PLATFORMOS=dryos

MEMBASEADDR=0x1900
RESTARTSTART=0x50000
MEMISOSTART=0x141DBC
ROMBASEADDR=0xff810000
NEED_ENCODED_DISKBOOT=3

PLFLAGS=-DMEMBASEADDR=$(MEMBASEADDR) -DMEMISOSTART=$(MEMISOSTART) -DMEMISOSIZE=$(MEMISOSIZE)
PLFLAGS+=-DRESTARTSTART=$(RESTARTSTART)

KEYSYS=d4
« Last Edit: 03 / February / 2010, 06:29:45 by battika »


*

Offline ERR99

  • ****
  • 339
Re: S90 Porting Thread
« Reply #44 on: 03 / February / 2010, 07:52:28 »
MEMISO start looks correct for S90.
But please dont forget to update also the ASM code. Even if the G11 asm-code looks similar to the S90 bootcode, it is not 100% the same. I have taken a quick look on the S90 Firmware and i found allready some different sub_function adresses in boot.c code. So it is absolutly necessary to update the complete ASM code, the G11 ASM code will not work for this port. If you try to build the G11 Port, only with makefile.inc and stubs_entry2.s adapted, the diskboot.bin will not work and the camera crashes direct during startup.
But hopefully the G11 port is a little help for your porting work.  ;)

Re: S90 Porting Thread
« Reply #45 on: 03 / February / 2010, 10:55:06 »
Thanks ERR99 for your suggestions, I will have a look into the boot code shortly. I'm very new to this porting process and your efforts with the G11 port has helped me a lot. You made a terrific job there.

Re: S90 Porting Thread
« Reply #46 on: 03 / February / 2010, 11:50:11 »
I think ERR99 could be of very great help to you after his very recent good G11 work.

No-one has ever spelled-out every single step of the porting process.

Maybe you could as you go along ?



David

Re: S90 Porting Thread
« Reply #47 on: 06 / February / 2010, 11:38:20 »
Unfortunately, the porting process has stalled, waiting for someone to come along who wants to and is able to actually disassemble the firmware, find the entry points to functions, figure out what they do, and write C code to call them from CHDK.   

Yes, due to the fact that there are other pressures on my time atm. I'll be getting back to it soon. i have most of the stubs and so on sorted from previously anyway. So I'll have another crack at things this week.


Re: S90 Porting Thread
« Reply #48 on: 06 / February / 2010, 14:18:21 »
stubs_entry.S
Code: [Select]
// !!! THIS FILE IS GENERATED. DO NOT EDIT. !!!
#include "stubs_asm.h"

NSTUB(AllocateMemory, 0xffaa3438)
NSTUB(AllocateUncacheableMemory, 0xff8393ec)
NSTUB(Close, 0xff835980)
NSTUB(CreateTask, 0xff81e5b4)
NSTUB(DeleteFile_Fut, 0xff83530c)
// ERROR: EnterToCompensationEVF is not found!
NSTUB(ExecuteEventProcedure, 0xff8898ac)
// ERROR: ExitFromCompensationEVF is not found!
// Best match: 57%
NSTUB(ExitTask, 0xff81e844)
NSTUB(Fclose_Fut, 0xff835488)
NSTUB(Feof_Fut, 0xff835674)
NSTUB(Fflush_Fut, 0xff8356b0)
NSTUB(Fgets_Fut, 0xff8355dc)
NSTUB(Fopen_Fut, 0xff835448)
NSTUB(Fread_Fut, 0xff835534)
NSTUB(FreeMemory, 0xffaa3430)
// Best match: 91%
NSTUB(FreeUncacheableMemory, 0xff83942c)
NSTUB(Fseek_Fut, 0xff835628)
NSTUB(Fwrite_Fut, 0xff835588)
// Best match: 52%
NSTUB(GetBatteryTemperature, 0xff863588)
// Best match: 52%
NSTUB(GetCCDTemperature, 0xff863514)
// Best match: 85%
NSTUB(GetCurrentAvValue, 0xff95c14c)
NSTUB(GetDrive_ClusterSize, 0xff86fc30)
NSTUB(GetDrive_FreeClusters, 0xff86fc90)
NSTUB(GetDrive_TotalClusters, 0xff86fc64)
// Best match: 64%
NSTUB(GetFocusLensSubjectDistance, 0xff95a720)
NSTUB(GetFocusLensSubjectDistanceFromLens, 0xff95ab68)
// Best match: 96%
NSTUB(GetOpticalTemperature, 0xff8635fc)
// Best match: 66%
NSTUB(GetParameterData, 0xff996808)
// Best match: 72%
NSTUB(GetPropertyCase, 0xff88d5e0)
// Best match: 96%
NSTUB(GetSystemTime, 0xffaa3490)
// Best match: 74%
NSTUB(GetZoomLensCurrentPoint, 0xff95ed28)
NSTUB(GetZoomLensCurrentPosition, 0xffa9669c)
// Best match: 64%
NSTUB(IsStrobeChargeCompleted, 0xff8db30c)
NSTUB(LocalTime, 0xff8871a8)
// Best match: 93%
NSTUB(LockMainPower, 0xff895274)
// ERROR: Lseek is not found!
// Best match: 92%
NSTUB(MakeDirectory_Fut, 0xff835380)
// Best match: 57%
NSTUB(MoveFocusLensToDistance, 0xffb030c8)
// Best match: 58%
NSTUB(MoveZoomLensWithPoint, 0xffaa0a5c)
// Best match: 62%
NSTUB(NewTaskShell, 0xff88d08c)
NSTUB(Open, 0xff835928)
// ERROR: PT_PlaySound is not found!
// Best match: 86%
NSTUB(PostLogicalEventForNotPowerType, 0xff8930a0)
// Best match: 92%
NSTUB(PostLogicalEventToUI, 0xff8930ec)
NSTUB(Read, 0xff81ab78)
NSTUB(ReadFastDir, 0xffa8416c)
// ERROR: RefreshPhysicalScreen is not found!
// ERROR: Remove is not found!
// Best match: 53%
NSTUB(RenameFile_Fut, 0xff835444)
// ALT: NSTUB(RenameFile_Fut, 0xffa70478) // 8/7
// ALT: NSTUB(RenameFile_Fut, 0xffa704c8) // 8/7
// Best match: 93%
NSTUB(SetAutoShutdownTime, 0xff8952e8)
// Best match: 81%
NSTUB(SetCurrentCaptureModeType, 0xff89ca38)
// Best match: 55%
NSTUB(SetFileTimeStamp, 0xff94a7f8)
// Best match: 64%
NSTUB(SetLogicalEventActive, 0xff894fc4)
// Best match: 68%
NSTUB(SetParameterData, 0xff9966e4)
// Best match: 89%
NSTUB(SetPropertyCase, 0xff88d4dc)
// Best match: 92%
NSTUB(SleepTask, 0xff839070)
// Best match: 60%
NSTUB(TakeSemaphore, 0xff838d38)
// ERROR: TurnOffBackLight is not found!
// ERROR: TurnOnBackLight is not found!
// ERROR: UIFS_WriteFirmInfoToFile is not found!
// Best match: 93%
NSTUB(UnlockMainPower, 0xff8951c8)
NSTUB(UpdateMBROnFlash, 0xff813f74)
NSTUB(VbattGet, 0xff831e08)
NSTUB(Write, 0xff835a10)
NSTUB(_log, 0xffb3dd88)
NSTUB(_log10, 0xffb3cccc)
NSTUB(_pow, 0xffb3ce3c)
NSTUB(_sqrt, 0xffb3f0f0)
NSTUB(close, 0xff81a990)
NSTUB(closedir, 0xffa83ff4)
// Best match: 71%
NSTUB(closefastdir, 0xffa84308)
// Best match: 95%
NSTUB(free, 0xff814138)
// Best match: 86%
NSTUB(kbd_p1_f, 0xff8335d0)
// Best match: 86%
NSTUB(kbd_p1_f_cont, 0xff8335dc)
// Best match: 86%
NSTUB(kbd_p2_f, 0xff832e90)
// Best match: 51%
NSTUB(kbd_pwr_off, 0xff8603ec)
// ERROR: kbd_pwr_on is not found!
// Best match: 84%
NSTUB(kbd_read_keys, 0xff833554)
// Best match: 78%
NSTUB(kbd_read_keys_r2, 0xff85fb68)
// ALT: NSTUB(kbd_read_keys_r2, 0xff85fb4c) // 17/5
NSTUB(lseek, 0xff835a9c)
NSTUB(malloc, 0xff8140dc)
NSTUB(memcmp, 0xff8203ec)
NSTUB(memcpy, 0xff83e9ec)
NSTUB(memset, 0xffa1389c)
NSTUB(mkdir, 0xff835df4)
NSTUB(mktime_ext, 0xff8aaf6c)
NSTUB(open, 0xff81a8e0)
NSTUB(opendir, 0xffa84038)
// ERROR: openfastdir is not found!
NSTUB(qsort, 0xffaf37d8)
// Best match: 95%
NSTUB(rand, 0xff8204f4)
NSTUB(read, 0xff81ab78)
// ERROR: readfastdir is not found!
// ERROR: rename is not found!
// Best match: 95%
NSTUB(srand, 0xff8204e8)
NSTUB(stat, 0xff835ad8)
// ALT: NSTUB(stat, 0xff86d074) // 30/0
// Best match: 61%
NSTUB(strcat, 0xff813f38)
// Best match: 56%
NSTUB(strchr, 0xff813fc0)
NSTUB(strcmp, 0xff8203a8)
NSTUB(strcpy, 0xff820390)
NSTUB(strftime, 0xff8aa974)
NSTUB(strlen, 0xff81400c)
NSTUB(strncmp, 0xff813f74)
// Best match: 73%
NSTUB(strncpy, 0xff813f38)
// Best match: 71%
NSTUB(strrchr, 0xff83e9c4)
// ALT: NSTUB(strrchr, 0xff8aa73c) // 18/8
// Best match: 96%
NSTUB(strtol, 0xff83eccc)
NSTUB(strtolx, 0xff83ead0)
// Best match: 86%
NSTUB(time, 0xff887720)
NSTUB(vsprintf, 0xff820354)
NSTUB(write, 0xff81abd8)

stubs_entry_2.S
Code: [Select]
#include "stubs_asm.h"
//FOUND
NHSTUB(TurnOffBackLight, 0xFF8A3FD0)
NHSTUB(TurnOnBackLight,  0xFF8A3FE8)
NHSTUB(EnterToCompensationEVF, 0xFF836D0C)
NHSTUB(ExitFromCompensationEVF, 0xFF836D50)
NHSTUB(Lseek, 0xFF835530)
NHSTUB(PT_PlaySound, 0xFF88173C)
NHSTUB(RefreshPhysicalScreen, 0xFFA08E40)
NHSTUB(Remove, 0xFF835418)
NHSTUB(UIFS_WriteFirmInfoToFile, 0xFF97E91C)
NHSTUB(kbd_pwr_off, 0xFF86089C)
NHSTUB(openfastdir, 0xFFA7D510)
NHSTUB(readfastdir, 0xFFA7D644)
NHSTUB(rename, 0xFF8354C0)
NHSTUB(LEDDrive, 0xFF85D5F8)
NHSTUB(SetScriptMode, 0xFF810EE4) //not definite, recheck later
NHSTUB(apex2us, 0xFFA0D734)
NHSTUB(MakeAFScan, 0xFF9645F0)
NHSTUB(ExpCtrlTool_StartContiAE, 0xFF8446CB)
NHSTUB(WriteSDCard, 0xFF94A478)
NHSTUB(UnlockAF, 0xFF836BA0)
NHSTUB(DoAFLock, 0xFF836B68)
NHSTUB(UnsetZoomForMovie, FF8A0DC0)

//NOTFOUND - nullsub

NHSTUB(kbd_pwr_on, 0xFF810B04)//cannot locate
NHSTUB(rewinddir, 0xFF810B04)//cannot locate
NHSTUB(SetZoomActuatorSpeedPercent, 0xFF810B04)//cannot locate
NHSTUB(Unmount_FileSystem, 0xFF810B04)//cannot locate
NHSTUB(Mount_FileSystem, 0xFF810B04)//cannot locate
//NHSTUB(platformsub_kbd_fetch_data, 0xFF833350)

stubs_min.S
Code: [Select]
#include "stubs_asm.h"

DEF(physw_status, 0x330d8)                
DEF(physw_run, 0x1C38 + 0x0C)            
DEF(FlashParamsTable,0xFFBEFB70)      
DEF(zoom_busy, 0x7a00)          
DEF(focus_busy, 0x78d4 + 8)              
DEF(canon_menu_active, 0x3034 + 4)        
DEF(canon_shoot_menu_active, 0x8944 + 1)  
DEF(recreview_hold, 0x8944)    
DEF(zoom_status, 0x8A84)                  
DEF(movie_status, 0x7ab0 + 0x38)        
DEF(enabled_refresh_physical_screen, 0xa36c)
DEF(playrec_mode, 0x2d60+0x4)        
DEF(some_flag_for_af_scan, 0x7FF4)    
DEF(led_table, 0x24AC + 0x04)            
DEF(levent_table,0xFFB95D20) //uncertain

lib.c and boot.c is pretty much done. need to look at movie_rec and capt_seq still then move on to other stuff.
« Last Edit: 06 / February / 2010, 14:26:19 by rachelkitty »

Re: S90 Porting Thread
« Reply #49 on: 06 / February / 2010, 16:19:27 »
It is a lot of work and we are all so busy with our brief lives.
Good to see you getting back to this  :)

Remember, ERR99 now has all the time in the World and I am sure would be only too happy to advise !



David

 

Related Topics