********************************************************************** * GX Memory Dump Program ********************************************************************** ********************************************************************** * This program dumps the entire G/GX memory using xmodem protocol. * The output file is a direct binary image of ROM, most programs * using the dump use nibble/byte storage so you may need a converter. * * The program can also handle covered memory banks. Since the program * may reside anywhere it has to use some of the lower RAM area to * store the covered access subroutines. uart_buffer is not used so that * area is chosen. * * To make the program simple the following subroutines are used: * * CopyBlock - copies next block to be sent to IRAMBUFF * SendBlock - sends the block in IRAMBUFF * * Special care is taken for the ROM areas handling bankswitching * and the area not accessible as a bank (memory test code) * * (C) Mika Heiskanen, 1994 * --> mheiskan@gamma.hut.fi ********************************************************************** ********************************************************************** * XMODEM SPECIAL CODES ********************************************************************** ASSEMBLE SOH EQU 1 Not CRC EOT EQU 4 End Of Transmission ACK EQU 6 Acknowledge block NAK EQU 15 Block was not ok RPL ******************************************************************************* * Unsupported entries ******************************************************************************* ASSEMBLE =AllowPRLCD EQU #324C8 =WIPEOUT EQU #0675C =xBUFLEN EQU #22087 =xSRECV EQU #21E95 =G_XeqInPlace EQU #7008B * #026CA doesn't restore bank =ACCESSD EQU #726A1 * Access #82000-#8FFFF =ACCESSE EQU #72386 * Access #90000-#BFFFF =ACCESSF EQU #70B38 * Access #C0000-#FFFFF =G_IRAMBUFF EQU #800F5 =G_uart_buffer EQU #80319 * XeqInPlace moves RAM to #C0000, so: =U_IRAMBUFF EQU #C00F5 =U_uart_buffer EQU #C0319 RPL ******************************************************************************* :: CK0NOLASTWD * Init uart AllowPRLCD xBUFLEN DROP xSRECV 2DROP CODE * Register usage: * * R0 ->address * R1 ( * The ACPTR copy subroutine uses this * ) * R2 block number * R3 CHK counter * R4 access routine address * Initialize variables GOSBVL =SAVPTR A=0 A R0=A A Current address A=A+1 A R2=A B Block number ST=0 15 Interrupts off GOSUB InitCopier Setup the copy subroutine DumpLoop GOSUB CopyBlock Copy next block to IRAMBUFF GOC DumpLast GOSUB SendBlock GOTO DumpLoop DumpLast GOSUB SendBlock ST=1 15 GOVLNG =GETPTRLOOP ********************************************************************** * CopyBlock utility: Copy a single xmodem block of memory to IRAMBUFF. * Use proper access methods when applicable. * Entry: R0[A] ->address * Exit: R0[A] ->tail CS if set to 0! * XMODEM block in IRAMBUFF * Note: Assumes bank boundary is not crossed during copy. * No worries if using xmodem block size. ********************************************************************** CopyBlock A=R0 A LC(5) #82000 Address of first bank ?A>=C A GOYES copybank LC(5) #80000 ?A>=C A GOYES copyhidden D1=(5) =G_IRAMBUFF ->copy to LC(5) #7F000 Prevent bank switching ?A=C A GOYES copyzeros D0=A ->address LC(5) 256 256 nibbles A=A+C A R0=A A GOVLNG =MOVEDOWN Returns CC * Copier for area #7F000-#7F0FF = bank switch area copyzeros LC(5) 256 A=A+C A R0=A A GOVLNG =WIPEOUT Returns CC * Copier for area #80000-#81FFF = covered ROM (NOT ACCESSD!) copyhidden LC(5) (=U_uart_buffer)+(RomFetch)-(BankFetch) GOSBVL =G_XeqInPlace RTNCC CC: Not end yet copybank LC(5) #90000 ?A<C A GOYES copybankd LC(5) #C0000 ?A>=C A GOYES copybankf copybanke LC(5) =ACCESSE * Area #90000-#BFFFF GONC copybankx copybankd LC(5) =ACCESSD * Area #82000-#8FFFF GOC copybankx copybankf LC(5) =ACCESSF * Area #C0000-#FFFFF copybankx R4=C A Set access subroutine GOVLNG =G_uart_buffer Call the copy subroutine ********************************************************************** * Init a copier to uart_buffer ********************************************************************** InitCopier GOSUB PassCopy * This code will go to uart_buffer BankFetch P= 0 Uncover bank GOSUB CallAccess LC(5) =G_IRAMBUFF R1=C A ->copy to LA(5) 256 256 nibbles P= 2 Copy A[A] nibbles from R0[A] to R1[A] C=0 S Copy *to* RAM GOSUB CallAccess C=R0 A ->copytail ?C=0 A Return CS if copied last block RTNYES RTNCC CallAccess C=R4.F A ->access subroutine (Keep R4.F! ) PC=C RomFetch A=R0 A D0=A D1=(5) =U_IRAMBUFF LC(5) 256 A=A+C A R0=A A GOVLNG =MOVEDOWN * Code ends here PassCopy A=PC Tail address C=RSTK Start address D0=C C=A-C A nibbles D1=(5) =G_uart_buffer GOVLNG =MOVEDOWN ********************************************************************** * Send block in IRAMBUFF using xmodem protocol. * Entry: R2[B] = block number * Use: R3[B] = CHK value ********************************************************************** SendBlock * Send opening sequence LC(2) SOH GOSUB SendChar C=R2 B GOSUB SendChar C=R2 B C=-C-1 A GOSUB SendChar D0=(5) =G_IRAMBUFF ->chars to send C=0 A R3=C A Init CHK LC(2) 128-1 Characters to send D=C A * Send data itself SendBlockLp C=DAT0 B char D0=D0+ 2 A=R3 B Update CHK A=A+C A R3=A B GOSUB SendChar D=D-1 A GONC SendBlockLp * Send CHK value C=R3 B Send CHK after block GOSUB SendChar * And wait for ack GOSUB WaitAck LC(2) NAK Not ok? ?A=C B GOYES SendBlock Yep - try again LC(2) ACK ?A=C B GOYES sndgotack LC(2) #18 Abort? ?A#C B GOYES SendBlock Nope - try again then GOTO ExitNow Abort * Got ack - update things sndgotack A=R2 B A=A+1 A block number++ R2=A B RTN ******************************************************************************* * Wait response to send data ********************************************************************** WaitAck D1=(5) =IOC LC(2) #88 DAT1=C B D1=(2) =RCS WaitAckLp GOSUB ?Exit C=DAT1 B ?CBIT=0 0 GOYES WaitAckLp Wait until RBF LCHEX 8 DAT1=C 1 RX D1=(2) =RBR A=DAT1 B RTN ********************************************************************** * Send character in C[B] ********************************************************************** SendChar A=C B D1=(5) =IOC LC(2) #B8 DAT1=C B D1=(2) =TCS SendCharLp C=DAT1 B ?CBIT=1 0 GOYES SendCharLp Wait until TBF not set D1=(2) =TBR DAT1=A B RTN ********************************************************************** * Exit if any key has been pressed ********************************************************************** ?Exit C=0 A GOSBVL =CINRTN ?C=0 A RTNYES LC(2) #18 Let the other side know D1=(5) =TBR DAT1=C B ExitNow ST=1 15 GOVLNG =GETPTRLOOP ********************************************************************** ENDCODE FLUSHRSBUF CLOSEUART FLUSH ;